文章目录
- string
- 存储对象
- 分布式锁
- 其他场景
- hash
- 对象缓存
- 购物车
- list
- 微博消息和工作号
- set
- 微信小程序抽奖
- 微信点赞,收藏
- 微博关注模型
- 电商搜索模型
- zset
- 微博排行榜
- 一些面试题
- Scan指令
string
set key value # 设置一个key value 存在就覆盖
mset key value key1 value1 #批量设置key value 存在就覆盖
get key #根据一个key得到一个value 没有key返回空
get key key1 # 批量获取key
del key # 删除一个
expire key seconds # 给一个key设置一个秒数为seconds的过期时间
incr key # 给一个key原子加1,没有key就新建key+1. value类型不同会报错
decr key # 给一个key原子减1 没有key就新建key-1,可以负数
setnx key value # 当key不存在的时候设置 不然不生效
存储对象
set user:1 value(对象json)
mset user:1:name ck user:1:age 20 #分存每个属性 适合某个字段经常修改
分布式锁
setnx lock true # 返回1代表设置成功 返回0代表设置失败(判断是否加锁成功)
del lock # 解锁
set key vale ex seconds nx # 设置一个key vlue并且给他seconds的失效时间
其他场景
- 和spring一起做分布式session
- 利用 incr key做分布式自增id 和 类似一篇文章被点击过多少次
hash
类似java中的 Map<String,Map<String,Object>>
hset person name ck age 18 # 设置一个key为person value为Map(name,ck)(age,18) 返回成功插入的int数量
hsetnx person name 1 # 尝试在一个key为person中设置value为Map(name,1)只有在name不存在的情况下才能设置
hmset person1 name cyz age 19 sex man- # 设置一个key为person1 value为Map(name,cyz)(age,19)(sex,man) 返回ok
HGET person name # 获取key为person中的 Map(key=mame)的value
HMGET person name age # 批量获取key为person中的 Map(key=name 和 key=age)的value
hdel person name age #删除key为person中的 Map(key=name 和 key=age)的value,如果删光了 最外层的key也会消失
HLEN person2 # 返回key为peron2中有多少个元素 int类型
HGETALL person2 #返回key为person2中所有的key 和 value的值
HINCRBY person2 age increment #key person2 中的age自增increment的数量
对象缓存
redis集群架构下如果hash中的值过大,不好做多个集群分配。因为只有一个key。
购物车
list
lpush list1 cyz # 从左边插入 可批量
rpush list1 ck # 从右边插入 可批量
lpop list1 # 从左边弹出值 弹出后list中这个值会消失
rpop list1 # 从右边弹出
lrange list1 start end # 从左边获取start到end的元素
BLPOP list1 timeout # 阻塞从左边弹出 在timeout的等待时间内
BRPOP list1 timeout # 阻塞从右边弹出 在timeout的等待时间内
常用的数据结构实现
Stack(栈) = LPUSH + LPOP
Queue(队列)= LPUSH + RPOP
Blocking MQ(阻塞队列)= LPUSH + BRPOP
微博消息和工作号
类似你订阅了一些微博和公众号,如何在订阅消息中获取
# 某个公众号号主发送一条新内容
lpush msg:user1Id 1008 #1008为消息的id
# 另一个公众号号主发送一条新内容
lpush msg:user1Id 1009
# 用户打开消息 接收消息,而且这样自身就是按时间排序
lrange list1 0 2
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中
微信小程序抽奖
srandmember 不删除元素 还可以继续抽
spop 删除元素 中了一次就不能再抽
微信点赞,收藏
微博关注模型
A 关注的人 ASet-> {B,C,D,E}
B 关注的人 BSet->{A,F,C,D,G}
A和B共同关注的人(求交集)
SINTER A B--> {C, D}
可能认识的人
SDIFF A B ->{A,F G} 去掉自己A
电商搜索模型
也就是求交集
zset
微博排行榜
七日搜索榜单的计算解释
ZUNIONSTORE hotNews:20190813-20190819 7
hotNews:20190813 hotNews:20190814... hotNews:20190819
ZUNIONSTORE 求并集指令
hotNews:20190813-20190819 新的key 代表13号~19之间所有的set并集
7:代表有几个元素
hotNews:20190813~hotNews:20190819: 都是key 表示这几个set放进来求并集
一些面试题
Redis是单线程吗?
Redis 的单线程主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。
Redis 单线程为什么还能这么快?
因为它所有的数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换性能损耗问题。正因为 Redis 是单线程,所以要小心使用 Redis 指令,对于那些耗时的指令(比如keys),一定要谨慎使用,一不小心就可能会导致 Redis 卡顿。
Redis 单线程如何处理那么多的并发客户端连接?
Redis的IO多路复用:redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。
Scan指令
假如在redis中有10个key 为 con1~10
假如我要查找所有con开头的
如果con开头的有几百万 几千万 keys 的效率非常差。可以采用scan
SCAN cursor [MATCH pattern] [COUNT count]
存放key的存储结构类似于hashMap 有一个桶+链表
cursor: 整数值 hash桶的索引值 一般第一次为0
Match:要匹配的规则
count:遍历key的数量。可能不准
第一次运行
第二次运行要将他返回的4 放在cursor的位置上
重复第二步直到返回0为止
所有的返回结果拼凑成完整结果
注意:但是scan并非完美无瑕, 如果在scan的过程中如果有键的变化(增加、 删除、 修改) ,那么遍历效果可能会碰到如下问题: 新增的键可能没有遍历到, 遍历出了重复的键等情况, 也就是说scan并不能保证完整的遍历出来所有的键, 这些是我们在开发时需要考虑的