数据存储结构
字符串相关操作
字符串常用操作
SET key value //存入字符串键值对
MSET key value [key value ...] //批量存储字符串键值对
SETNX key value //存入一个不存在的字符串键值对
GET key //获取一个字符串键值
MGET key [key ...] //批量获取字符串键值
DEL key [key ...] //删除一个键
EXPIRE key seconds //设置一个键的过期时间(秒)
原子加减
INCR key //将key中储存的数字值加1
可以用在文章阅读次数、打开次数等场景
DECR key //将key中储存的数字值减1
INCRBY key increment //将key所储存的值加上increment
DECRBY key decrement //将key所储存的值减去decrement
String字符串应用场景
单值缓存
存值:set name zhangsan
取值:get name
删除
del name
设置过期时间
expire key seconds
设置key,6秒后过期
expire name 6
对象缓存
| ID | name | age |
|---|---|---|
| 1 | zhangsan | 25 |
| 2 | lisi | 26 |
| 3 | wangwu | 21 |
| 4 | zhaoliu | 27 |
| 5 | sunqi | 22 |
json格式存储
set user1 '{"id":1,"name":"zhangsan","age":25}'
对象序列化存储
可以将对象进行序列化之后存储到redis,取值之后再反序列化获得对象。
mset/mget 多key value存储
语法:mset key1 val1 key2 val2 keyn valn
实操
模糊查询
语法:keys key*
实操:keys user:3:*
分布式锁简单使用
语法:
setnx key val
说明:
将 key 的值设为 value,当且仅当 key 不存在。
若给定的 key 已经存在,则 SETNX 不做任何动作。
SETNX 是SET if Not eXists的简写。
使用场景
假设简单秒杀场景,N个用户进行秒杀操作,当第一个用户操作的时候可以使用 setnx product:10001 zhangsan,后面的用户在使用此命令的时候就无法将值存入redis,可以避免重复秒杀(此场景仅用于简单演示使用,不推荐用于实际场景)
演示
这样商品10001就只有zhangsan用户抢购成功,其他用户都无法继续抢购。
问题:假如用户抢购成功但是未付款,该怎么办?不能一直被他锁着吧,因此需要解决此类问题如下:
原理:\
SET key value [NX] [XX] [EX <seconds>] [PX [millseconds]]
必选参数说明
- SET:命令
- key:待设置的key
- value: 设置的key的value
可选参数说明
- NX:表示key不存在才设置,如果存在则返回NULL
- XX:表示key存在时才设置,如果不存在则返回NULL
- EX seconds:设置过期时间,过期时间精确为秒
- PX millseconds:设置过期时间,过期时间精确为毫秒
以上set 代替了 setnx + expire 需要分2次执行命令操作的方式,保证了原子性。
实际操作
set name zhangsan NX px 6000
设置如果key不存在则设置并且设置过期时间未6秒,如果存在则不设置
6秒后操作
通过key无法获取val,然后可以继续进行set key继续设置操作
Web集群 session + redis 实现session共享
Hash结构
优点
1)同类数据归类整合储存,方便数据管理
2)相比string操作消耗内存与cpu更小
3)相比string储存更节省空间\
缺点
过期功能不能使用在field上,只能用在key上
Redis集群架构下不适合大规模使用\
相关命令
HSET key field value //存储一个哈希表key的键值
HSETNX key field value //存储一个不存在的哈希表key的键值
HMSET key field value [field value ...] //在一个哈希表key中存储多个键值对
HGET key field //获取哈希表key对应的field键值
HMGET key field [field ...] //批量获取哈希表key中多个field键值
HDEL key field [field ...] //删除哈希表key中的field键值
HLEN key //返回哈希表key中field的数量
HGETALL key //返回哈希表key中所有的键值\
HINCRBY key field increment //为哈希表key中field键的值加上增量increment
使用场景
对象缓存
HMSET key field value [field value ...] //在一个哈希表key中存储多个键值对
HMGET key field [field ...] //批量获取哈希表key中多个field键值
电商购物车
相关命令
HSET key field value //存储一个哈希表key的键值
HINCRBY key field increment //为哈希表key中field键的值加上增量increment
HLEN key //返回哈希表key中field的数量
HGETALL key //返回哈希表key中所有的键值\
场景
电商购物车
1)以用户id为key
2)商品id为field
3)商品数量为value
购物车操作 添加商品hset cart:1001 10088 1 增加数量hincrby cart:1001 10088 1 商品总数hlen cart:1001 删除商品hdel cart:1001 10088 获取购物车所有商品hgetall cart:1001
list结构
LPUSH key value [value ...] //将一个或多个值value插入到key列表的表头(最左边)
RPUSH key value [value ...] //将一个或多个值value插入到key列表的表尾(最右边)
LPOP key //移除并返回key列表的头元素
RPOP key //移除并返回key列表的尾元素
LRANGE key start stop //返回列表key中指定区间内的元素,区间以偏移量start和stop指定\
BLPOP key [key ...] timeout //从key列表表头弹出一个元素,若列表中没有元素,阻塞等待 timeout秒,如果timeout=0,一直阻塞等待 BRPOP key [key ...] timeout //从key列表表尾弹出一个元素,若列表中没有元素,阻塞等待 \ timeout秒,如果timeout=0,一直阻塞等待
lpush向左插入值 rpush向右插入值
lpush key val[val]
rpush key val[val]
lpop从左侧删除元素;rpop从右侧删除元素
lpop key count :从左侧删除key的count个值(count不填默认1)
rpop key count :从右侧删除key的count个值(count不填默认1)
blpop从左侧删除一个元素;brpop从右侧删除一个元素
blpop key timout :从左侧删除一个元素,如果没有则阻塞队列timout秒,如果timeout为0,则一直阻塞
rlpop key timout :从右侧删除一个元素,如果没有则阻塞队列timout秒,如果timeout为0,则一直阻塞
如下情况,如果list为空,并且blpop timeout=0 队列一直阻塞,当有值被填入list中是,此被阻塞队列获得元素,并且返回阻塞时长
常用数据结构
常用数据结构
Stack(栈) = LPUSH + LPOP
Queue(队列)= LPUSH + RPOP
Blocking MQ(阻塞队列)= LPUSH + BRPOP
应用场景
如张三关注了A、B、C、D 公众账号,当他们发布消息的时候给张三进行推送消息(仅举例,不实用)。
1)A发布消息,消息ID为10001
lpush msg:zhangsan 10001
2) B发布消息,消息ID为10002
lpush msg:zhangsan 10001
3) C发布消息,消息ID为10003
lpush msg:zhangsan 10003
4) 张三读取微信公众号前10条消息
lrange msg:zhangsan 0 10
Set 结构
Set常用操作
SADD key member [member ...] //往集合key中存入元素,元素存在则忽略,若key不存在则新建
SREM key member [member ...] //从集合key中删除元素
SMEMBERS key //获取集合key中所有元素
SCARD key //获取集合key的元素个数
SISMEMBER key member //判断member元素是否存在于集合key中
SRANDMEMBER key [count] //从集合key中选出count个元素,元素不从key中删除
SPOP key [count] //从集合key中选出count个元素,元素从key中删除\
Set运算操作
SINTER key [key ...] //交集运算
SINTERSTORE destination key [key ..] //将交集结果存入新集合destination中
SUNION key [key ..] //并集运算
SUNIONSTORE destination key [key ...] //将并集结果存入新集合destination中
SDIFF key [key ...] //差集运算
SDIFFSTORE destination key [key ...] //将差集结果存入新集合destination中
基本操作命令
sadd:添加元素,如果val存在则不做任何操作
sadd key val[val]
sadd member a b c d
smembers 查询set中所有元素
smembers key
smembers member\
srandmember从set中随机获取元素,获取后不删除set中元素
srandmember key count:随机从set为key的值中获取count个元素
srandmember member 2
spop从set中随机获取元素,获取后会删除set中元素
spop key count:随机从set为key的值中获取count个元素,并同时删除
spop member 2
###利用sadd srandmember/spop 进行一个抽奖功能
1)A加入奖池
sadd member A
2) B加入奖池
sadd member B
3) C加入奖池
sadd member C
4) D加入奖池
sadd member D
抽奖并且后面不能再次抽奖
spop member 1:从member的值中随机抽取一个值
抽奖并且后面还可以再次进行抽奖
srandmember member 1:从member的值中随机抽取一个值
srem 删除set中指定的key val
srem key val
srem member d
sismember 查看是否添加过指定的key val
sismember key val
sismember member a
scard 查看set指定的key有多少个值
scard key
scard key
###利用sadd srem sismember smembers scard模拟点赞功能
1)A用户点赞
sadd good A
2) B用户点赞
sadd good B
3) C用户点赞
sadd good C
4) A用户取消点赞
srem good A
5) 检查B是否点过赞
sismember good B
6) 查看点赞用户列表
smembers good
7) 获取用户点赞数
scard good
集合操作
交集:SINTER set1 set2 set3 ->{ c }\
并集:SUNION set1 set2 set3 ->{ a,b,c,d,e }\
差集:SDIFF set1 set2 set3 -> { a }\
###利用集合实现微博微信关注模型
1)张三关注的人 zhangsanset -> {lisi,wangwu}
sadd zhangsanset lisi wangwu
2) 二麻子关注的人 ermaziset->{zhangsan zhaoliu sunqi wangwu}
sadd ermaziset zhangsan zhaoliu sunqi wangwu
3) 孙七关注的人 sunqiset ->{zhangsan ermazi zhaoliu wangwu zhouban}
4)张三和二麻子共同关注过的人
sinter zhangsanset ermaziset
5)张三关注的人也关注二麻子
sismember lisiset ermazi
sismember wangwuset ermazi
6)张三可能认识的人
sdiff zhangsanset ermaziset ->{lisi,zhangsan,zhouliu,sunqi}
###集合实现电商商品筛选
添加商品信息
SADD brand:huawei P40
SADD brand:xiaomi mi-10
SADD brand:iPhone iphone12
SADD os:android P40 mi-10
SADD cpu:brand:intel P40 mi-10
SADD ram:8G P40 mi-10 iphone12
筛选安卓系统 CPU是intel ram为8G的手机
SINTER os:android cpu:brand:intel ram:8G {P40,mi-10}\
zset 有序集合结构
ZSet常用操作
ZADD key score member [[score member]…] //往有序集合key中加入带分值元素
ZREM key member [member …] //从有序集合key中删除元素
ZSCORE key member //返回有序集合key中元素member的分值
ZINCRBY key increment member //为有序集合key中元素member的分值加上increment
ZCARD key //返回有序集合key中元素个数
ZRANGE key start stop [WITHSCORES] //正序获取有序集合key从start下标到stop下标的元素
ZREVRANGE key start stop [WITHSCORES] //倒序获取有序集合key从start下标到stop下标的元素\
Zset集合操作
ZUNIONSTORE destkey numkeys key [key ...] //并集计算
ZINTERSTORE destkey numkeys key [key …] //交集计算
zset基本操作命令
zadd 向有序集合中添加带分值的元素
zadd key score member[score member]
zadd shuxue 99 zhangsan 98 lisi 95 wangwu 60 zhaoliu
zscore 获得有序集合key中元素内容的分值
zscore key member 获得key中member的分值
zscore shuxue wangwu
zrem 删除有序集合key中的值
zrem key member 删除集合key中member的元素
zrem shuxue lisi
zincrby 给集合key中的元素member元素加分值
zincrby key increment member 给集合key中元素member加 increment
zincrby shuxue 20 zhaoliu
zcard 返回集合key元素的数量
zcard key 、
zcard shuxue
ZRANGE 正序返回集合中的元素
zrange key start stop [withscores]正序返回key元素从start到stop的元素[withscores]:是否返回分值,start开始取值,stop结束取值,当为-1时,则取到最后
正序查询所有数学成绩,并且返回分值
zrange shuxue 0 -1 withscores
zrevrange 倒序返回集合中的元素
zrevrange key start sotp [withscores]倒序返回key元素从start到stop的元素[withscores]:是否返回分值,start开始取值,stop结束取值,当为-1时,则取到最后
倒序查询所有数学成绩,并且返回分值
zrevrange shuxue 0 -1 withscores
zset集合操作命令
ZUNIONSTORE destkey numkeys key [key ...] //并集计算
ZINTERSTORE destkey numkeys key [key …] //交集计算
zunionstore 集合的并集,并可进行加权处理
语法:
zunionstore newkeyname keynumbers key [key...] [weights weight] [aggregate sum/min/max]
zunionstore newkey 2 key1 key2 weigths 1 3
将2个key,key1 key2 合并到 newkey中,并且给key1中的score1,key2中的score3,如果key1和key2中有相同值,则加权之后再相加(aggregate 不设置,默认是sum)
1)张三考试的分值
zadd zhangsan 80 shuxue 90 yuwen 85 yingyu
2)李四考试的分值
zadd lisi 75 tiyu 85 shuxue 79 meishu 100 huaxue
3)计算各科目的总分,并且给李四的分值乘以2
其中:张三 李四都有数学科目,最终数学总分=张三数学分值+李四数学分值*2
zinterstore 集合的并集
zinterstore newkey numberkeys key [key....] [wigthts wieght] [aggregate sum/min/max]
将numkeys个集合交集到newkey中,并且进行加权,和取值(加/最小/最大)
zadd mynewkey 2 zhangsan lisi weights 1 2 aggregate min
将张三李四的分值进行交集,并且给李四进行加权*2,交集之后求最下值
其中:aggregate 不设置默认sum
scan渐进式遍历
SCAN cursor [MATCH pattern] [COUNT count]
scan 参数提供了三个参数,
第一个是 cursor 整数值(hash桶的索引值),
第二个是 key 的正则模式,
第三个是一次遍历的key的数量(参考值,底层遍历的数量不一定),
并不是符合条件的结果数量。第一次遍历时,cursor 值为 0,然后将返回结果中第一个整数值作为下一次遍历的 cursor。一直遍历到返回的 cursor 值为 0 时结束。
注意:scan并非完美无瑕, 如果在scan的过程中如果有键的变化(增加、 删除、 修改) ,那么遍历效果可能会碰到如下问题: 新增的键可能没有遍历到, 遍历出了重复的键等情况, 也就是说scan并不能保证完整的遍历出来所有的键, 这些是我们在开发时需要考虑的。
从所有key中查找开头是n的key,并且每次查询的结果数不多余3个
第一次需要从0开始找,第二次需要将第一次返回的hash同的索引值带入,至到最终索引值返回0则完成查找。
redis数据存储及查询原理解析(先简单了解,后面再深入)
redis底层为hash桶存储方式,每次set key的时候先对key进行hash计算,得到hash值对应槽位,然后将其存储到对应的槽位中,查询原理也是这样先计算key的hash值,再进行查找。
redis info信息
查看redis服务运行信息,分为 9 大块,每个块都有非常多的参数,这 9 个块分别是:
Server 服务器运行的环境参数
Clients 客户端相关信息
Memory 服务器运行内存统计数据
Persistence 持久化信息
Stats 通用统计数据
Replication 主从复制相关信息
CPU CPU 使用情况
Cluster 集群信息
KeySpace 键值对统计数量信息
关键数据解析
connected_clients:2 # 正在连接的客户端数量
instantaneous_ops_per_sec:789 # 每秒执行多少次指令
used_memory:929864 # Redis分配的内存总量(byte),包含redis进程内部的开销和数据占用的内存
used_memory_human:908.07K # Redis分配的内存总量(Kb,human会展示出单位)
used_memory_rss_human:2.28M # 向操作系统申请的内存大小(Mb)(这个值一般是大于used_memory的,因为Redis的内存分配策略会产生内存碎片)
used_memory_peak:929864 # redis的内存消耗峰值(byte)
used_memory_peak_human:908.07K # redis的内存消耗峰值(KB)
maxmemory:0 # 配置中设置的最大可使用内存值(byte),默认0,不限制
maxmemory_human:0B # 配置中设置的最大可使用内存值
maxmemory_policy:noeviction # 当达到maxmemory时的淘汰策略