数据结构常见的应用方式
Redis Strings 字符串
值最大不能超过 512MB
业务不经常变更的数据,接口响应的json字符串等
图片的base64的值
数值,秒杀数量之类的,INCR , INCRBY , DECR , DECRBY 命令(内部就是同一个命令,只是看上去有点儿不同)会将字符串解析成整数进行原子操作。原子操作意味着多个客户端对同一个key发出INCR命令,也决不会导致竞争的情况。
统计数据,每小时更新访客信息计数器,GETSET可以和INCR一起使用实现支持重置的计数功能
redis> INCR mycounter //访问
(integer) 1
redis> GETSET mycounter "0" //获取并重置计数
"1"
redis> GET mycounter //获取重置后的数据
"0"
redis>
为减少等待时间,也可以一次存储或获取多个key对应的值,使用MSET和MGET命令
> mset a 10 b 20 c 30
OK
> mget a b c //返回由值组成的数组
1) "10"
2) "20"
3) "30"
Redis Hash 哈希
特别适合用于存储对象,Redis 中每个 hash (散列) 可以存储 232 – 1 键值对(40多亿)
系统参数常量配置功能
Redis Lists 列表
简单的消息队列
lpop
和rpush
(或者反过来,lpush
和rpop
)能实现队列的功能,BLPOP,BRPUSH阻塞式实现消息队列。
朋友圈的点赞列表、评论列表、排行榜:lpush
命令和lrange
命令能实现最新列表的功能,每次通过lpush
命令往列表里插入新的元素,然后通过lrange
命令读取最新的元素列表。
限速器,可用于限制某个用户访问某个接口的频率,比如秒杀场景用于防止用户快速点击带来不必要的压力
好友关系,利用集合的一些命令,比如交集、并集、差集等,实现共同好友、共同爱好之类的功能
Redis Set 集合
String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis Sorted Set 有序集合
string 类型元素的集合,且不允许重复的成员,每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
发布/订阅
redis实现消息队列(轻量级)的方案
消息队列特征 | 基于List | 基于streams | 基于发布订阅 |
消息保序 | 适用LPUSH/RPOP | 使用ADD/XREAD | |
阻塞读取 | 适用BRPOP | 使用XREAD block | |
重复消息处理 | 生产者自行实现全局唯一ID | Streams自动生成全局唯一ID | |
消息可靠性 | 适用BRPOP LPUSH | 使用PENDING List自动留存消息,使用XPENDING查看,使用XACK确认消息 | |
适用场景 | Redis5.0之前版本的部署环境消息总量少 | Redis5.0及以后的版本的部署环境消息总量大,需要消费组形式读取数据 |
缓存使用常见问题
如何保证双写一致性
Cache Aside Pattern 模式
读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。
更新的时候,先更新数据库,然后再删除缓存。删除缓存而不更新缓存的原因:有些需要进行复杂计算或查询的缓存场景,更新的操作成本太高。
不一致场景及解决方案
先删除缓存再更新数据库
进行更新操作时,先删除缓存,然后更新数据库,后续的请求再次读取时,会从数据库读取后再将新数据更新到缓存
先更新数据库再删除缓存
进行更新操作时,先更新 MySQL,成功之后,删除缓存,后续读取请求时再将新数据回写缓存。
存在的问题:更新 MySQL 和删除缓存这段时间内,请求读取的还是缓存的旧数据,不过等数据库更新完成,就会恢复一致,影响相对比较小。
异步更新缓存
数据库的更新操作完成后不直接操作缓存,而是把这个操作命令封装成消息扔到消息队列中,然后由 Redis 自己去消费更新数据,消息队列可以保证数据操作顺序一致性,确保缓存系统的数据正常。
Redis 缓存击穿、穿透、雪崩
相关文章和面试问题
redis的五种数据结构和应用场景【如微博微信点赞/共同关注/加购物车】