这是我参与「第五届青训营 」伴学笔记创作活动的第 15 天
为什么需要Redis
- Redis能够提高数据查询请求的响应速度,性能更优
- 支持热数据的频繁访问
Redis原理
- 数据在内存中进行读写
- 数据同步保存在磁盘上防止数据丢失
- 增量数据保存在AOF文件
- 全量数据RDB文件
- 单线程处理所有操作命令
Redis应用场景&常用数据结构
-
连续签到
需求:如果断签则连续签到计数归零,每天23:59:59过期
实现:将uid+连续计数+过期时间拼接成一个字符串存储在Redis,借助Redis的过期处理归零
使用的Redis数据结构:字符串(String)
- 数据结构--sds
- 可以存储字符串、数字、二进制数据
- 通常和expire配合使用
- 使用场景:存储计数、Session
-
消息通知
需求:掘金写文章上传后,如何通知ES服务,有新的任务需要处理
实现:用Redis中list存储文章信息,服务监听Redis并读取
使用的Redis数据结构:Quicklist
- 由一个双向链表和listpack组成
-
计数
需求:一个用户有多项计数需求,例如:视频的点赞数,评论数
实现:使用Redis的Hash结构存储,用uid拼接成一个key,value中存储多个计数种类以及具体数值组成的key-value
使用的Redis数据结构:Hash
- rehash:因为hash需要扩容
- 渐进式rehash:每次用户访问都会拷贝少量数据至新的扩容结构中
-
排行榜
需求:积分排行榜需要实时变化
实现:使用zset存储排行榜数据
使用的Redis数据结构:Zset数据结构是zskiplist(跳表)
-
限流
需求:限制短时间内请求的次数,拒绝超过的次数
实现:String存储由uid+限制次数+时间戳组成的字符串,每次请求都查询这个String,超过次数则拒绝
-
分布式锁
需求:要求只有一个协程执行,执行完成后,其协程才能执行
实现:使用Redis的setnx实现
使用的Redis数据结构:setnx
- 单线程处理
- 只有未设置成功,才能被设置
注意事项
-
大Key,热Key
-
大key定义
数据类型 大key标准 String value的字节数大于10KB即为大key Hash/Set/Zset/list 元素个数大于5000个或总value字节数大于10MB即为大key -
大key危害
- 读写成本高
- 容易导致慢查询
- 主从复制阻塞正常请求响应
-
消除大key的方法
- 拆分:拆分成多个key
- 压缩:使用压缩算法压缩数据后再存储到Redis,读取的时候解压再使用
- 区分冷热存储
-
热key定义
热key没有明确的标准,QPS 超过500就有可能被识别为热Key
-
热key危害
用户访问一个Key的OPS特别高,导致Server实例出现CPU负载突增或者不均的情况
-
消除热key的方法
- 业务侧设置Localcache,降低访问Redis的QPS
- 拆分:将热key复制写入多份,使得热key的QPS分摊到不同的实例
- 使用代理
-
-
慢查询
- 批量操作一次性传入过多的key/value,如mset/hmset/sadd/zadd等 O(n)操作建议单批次不要超过100,超过100之 后性能下降明显。
- zset大部分命令都是O(log(n)),当大小超过5k以上时,简单的zadd/zrem也可能导致慢查询
- 操作的单个value过大,超过10KB。 也即,避免使用大Key
- 对大key的delete/expire操作也可能导致慢查询,Redis4.0之 前不支持异步删除unlink,大key 删除会阻塞Redis
-
缓存穿透、缓存雪崩
- 缓存穿透:热点数据绕过Redis,直接查询数据库
- 缓存雪崩:大量缓存同时过期
参考资料
第五届青训-Redis-大厂程序员是怎么用的.pptx - 飞书云文档 (feishu.cn)