Redis实例目录
Redis面试常问,由于我在实际开发中很少用,所以虽然看了很多次,但都不够深刻,不能举一反三。为了深入理解,这里总结它的常用场景,深刻理解Redis
有需要的同学务必照着例子敲一遍,多思考、多回顾,才能在实际使用中如鱼得水
(一)String
(1)业务场景1——分库分表后获取唯一id
incr key //自增1
incrby key increment //增加指定数值
incrbyfloat key increment //增加一个浮点数
注意
- string在redis内部存储默认就是一个字符串,当遇到增减类操作incr,decr时会转成数值型进行计算
- redis所有的操作都是原子性的,采用单线程处理所有业务,命令是一个一个执行的,因此无需考虑并发带来的数据影响
- 按数值进行操作的数据,如果原始数据不能转成数值,或超过了redis数值上线范围,将会报错。9223372036854775807 (java中long型数据最大值,Long.MAX_VALUE)
(2)业务场景2——数据时效性设置
场景:
- 某某综艺”,启动海选投票,只能通过微信投票,每个微信号每4个小时只能投1票。
- 电商商家开启热门商品推荐,热门商品不能一直处于热门期,每种商品热门期维持3天,3天后自动取消热门
- 新闻网站会出现热点新闻,热点新闻最大的特征是对时效性,如何自动控制热点新闻的时效性
【解决思路】
设置数据具有指定的生命周期。redis 控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作。说白了,就是设置键的过期时间,业务层判断一个商品过期了,就不能放在热门商品推荐
- 增加/修改键值对并为其指定过期时间:
setex key seconds value
- 功能与上面一样,秒的单位不同:
psetex key milliseconds value
(3)业务场景3——高频数据访问显示
场景:主页高频访问信息显示控制,例如微博大V主页显示粉丝数与微博数量,这些数据就是热度数据,不断发生变化(一直有用户访问、数据在不断变化),这些数据如何放入Redis?

实现方式一
为大V用户设定用户信息,以用户主键和属性值作为key,后台设定时间定时刷新即可。
> set user:340823:blogs 100 //设置微博数量100
> set user:340823:fans 100000 //粉丝数100000
> set user:340823:focus 400 //关注数:400
在redis中的存储结构如下

实现方式二
以json格式存储大V用户,定时刷新,在代码中将对象转换为Json存储
(二)Hash
对某个门类,再进行细分
场景
- 比如说用户购物车,细分到用户有多个商品,每个商品有不同的属性;
- 商品优惠券,有不同的券额,30,50,100等等…获取的数量也不一样
- 库中已存在user的name为zhangsan的数据,再设置(
hset
)user的name为lisi,可以设置成功> hset user name lisi (integer) 0 >hget user name "lisi"
- 使用
hsetnx
修改user的name为wangwu>hsetnx user name wangwu (integer) 0 >hget user name "lisi"
hset
和hsetnx
命令,前者是覆盖之前的设置,后者是如果不存在才设置成功,存在就设置不成功
(1)业务场景1——购物车的实现

【基本操作】
-
以客户id(user1)作为key,每位客户创建一个hash存储结构存储对应的购物车信息
-
添加商品:追加全新的field和value
-
浏览,遍历hash
获取全部的属性名和属性值(获取商品及对应的数量):
hgetall user1
获取字段名(获取商品list):hkeys user1
获取字段值:hvals user1
-
更改数量:自增/自减,设置value的值
hincrby user1 food01 3
-
删除商品:删除field
hdel user1 food01
-
清空购物车,删除key
阶段一:仅存储商品数量

在Redis中存储的结构

当前仅仅是将数据存储到Redis中,并没有起到加速的作用,因为我们仅仅查询到了用户商品id和数量,商品详细信息还需要二次查询数据库;
阶段二:存储商品数量及其他信息(图片等等)
优化:购物车中的商品记录保存成两条field
field1:专用于保存购买数量
【g001:nums 2】
- 命名格式:商品id:nums
- 保存数据:数值(2)
field2 :专用于保存购物车中显示的信息,包含文字描述、图片地址、所属商家信息等等
【g001:info {images}】
- 命名格式:商品id:info (g001:info)
- 保存数据:json ({images})

在Redis中的存储结构

但是出现很多用户都将同一个商品加入购物车,就会出现大量的重复信息,例如商品信息重复

阶段三:商品信息保存为哈希
> hset g001 info {images}
(2)业务场景2——抢购活动,限购发放优惠券、激活码等

【解决方案】
- 以商家id作为key(比如电信)
- 将参与抢购的商品id作为field(30元的券、50元)
- 将参与抢购的商品数量作为对应的value(各含1000张)
- 抢购时使用降至的方式控制产品数量
(三)List(有序的)
使用场景
- 朋友圈点赞
- 微信消息提醒,最近的消息在最上面
- 微博个人关注列表,最近关注的在最上面
【基本操作】
lpush key value1[value2]...
rpush key value[value2]...
查看所有key:lrange key 0 -1
获取并删除左边第一个元素:lpop key
获取并删除右边第一个元素:rpop key
(1)业务场景1——朋友圈点赞
功能:按照点赞顺序显示点赞好友信息,如果取消点赞,移除对应好友信息

【解决方案】
rpush
添加数据,先进先出
- 移除指定数据(类似某个人取消点赞)
(2)业务场景2——最新消息的展示,最近关注,粉丝列表等
使用场景
- 微博中关注列表需要按照用户的关注顺序进行展示,最新关注在最上面;粉丝列表同理
- 新闻、资讯类网站将最新的新闻或咨询按照发生的事件顺序展示
- 企业运营过程中,系统将产生大量的运营数据,如何保障堕胎服务器操作日志的统一顺序输出

【解决方案】
- 依赖list的数据具有顺序的特征对信息进行管理
- 使用队列模型解决多路信息汇总合并的问题
- 使用栈模型解决最新消息的问题
(四)Set(无序的,不能重复的)
使用场景
- 随机推荐类索引
- 每位员工有多个角色,角色权限的合并;
- 同类型不同数据的合并操作:两个用户的共同好友之类
- 访问量的统计
【基本操作】
- 添加数据:
sadd key member1[member2]
- 获取全部数据:
smembers keys
- 删除数据:
srem key member1[member2]
- 获取集合数据总量:
scard key
- 判断集合中是否包含指定数据:
sismember key member
- 随机获取集合中指定数量的数据:
srandmember key [count]
- 随机获取集合中的某个数据并将该数据移出集合:
spop key
(1)业务场景1——随机操作数据
【场景分析】
- 每位用户首次使用进入头条的时候会设置3项爱好的内容,但后期为了增加用户的活跃度、兴趣点、必须让用户对其他信息类别逐渐产生兴趣,增加用户留存度,如何实现?
【业务分析】
- 系统分析出各个类别的最新或最热点信息条目并组织成set集合,随机挑选其中部分信息
- 配合用户关注信息分类中的热点信息组织展示的全信息集合
【实战】
应用于随机推荐类信息检索,例如热点歌单推荐,热点新闻推荐,热点旅游线路,应用APP推荐,大V推荐
(2)业务场景2——共同好友

【解决方案】
- 求两个集合的交、并、差集
sinter key1[key2] #交集 sunion key1[key2] #并集 sdiff key1[key2] #差集(key1有但是key2没有)
- 求两个集合的交、并、差集并存储到指定集合中
sinterstore destination key1[key2] sunionstore destination key1[key2] sdiffstore destination key1[key2]
- 将指定数据从原始集合移动到目标集合中
smove source destination member
【总结】
Redis 应用于同类信息的关联搜索,二度关联搜索,深度关联搜索
- 显示共同好友,共同关注(一度)
- 由用户A出发,获取到好友用户B的好友信息列表
- 由用户A出发,获取到好友用户B的购物清单列表/游戏充值列表
(3)业务场景3——同类型不重复数据的合并操作

【解决方案】
依赖set集合数据不重复的特征,依赖set集合hash存储结构特征完整数据过滤与快速查询
- 根据用户id获取用户所有角色
- 根据用户所有角色获取用户所有操作权限
- 根据用户所有角色获取用户所有数据,这种耦合度太高
【实操】
(4)业务场景4——访问量统计去重

【解决方案】
针对不同的统计类型有不同的数据存储方式
- 建立String类型数据,利用incr统计日访问量(PV)
- 建立Set模型,记录不同cookie数量(UV)和不同IP数量(IP)
(5)业务场景5——黑白名单
(五)Sort_Set
【基本操作】
- 添加数据:
zadd key score1 member1 [score2 member2]
- 按照从小到大的顺序,加上withscores,就会带上scores一起显示:
zrange key start stop [withscores]
- 按照从大到小的顺序:
zrevrange key start stop [withscores]
- 删除数据:
zrem key member [member...]
- 查询scores在某个范围内的值:
zrangebyscore key min max [withscore] [limit]
- 查询key某个索引范围内的值:
zrevrangebyscore key max min [withscore]
- 删除有序集合中给定索引区间的所有成员:
zremrangebyrank key start stop
- 删除指定分数区间的所有成员:
zremrangebyscore key min max
【实战】
- 获取集合数据总量,两个集合求值等
zcard key #获取总量 zcount key min max # 获取某一范围的总量 Zinterstore destination numkeys key [key...] #求和,其中numkeys指定集合(key...)的数量 zunionstore destination numkeys key [key...]
【实操】
【小结】
- min , max用于限定搜索查询的条件
- start,stop作用于索引,表示开始和结束索引
- offset与count用于限定查询范围,作用于查询结构,表示开始位置和数据总量
(1)业务场景1——TOP10排行榜
- 票选10大杰出青年,各类综艺选秀海选投票
- 各类资源网站TOP10(电影,歌曲,文档,电商,游戏等)
- 聊天室活跃度统计
- 游戏好友亲密度

【用法】
- 正数第几位:
zrank key member
- 倒数第几位:
zrevrank key member
- 获取:
zscore key member
- score递增 increment:
zincrby key increment member
(2)业务场景2——会员短期体验之过期失效
参考资料
b站黑马教程