这是我参与「第五届青训营 」伴学笔记创作活动的第 17 天
目录
- Redis 是什么
- Redis 应用案例
- Redis 使用注意事项
为什么需要Redis
- 数据库从单表到分库分表
- MySQL从单机演进到集群
- 数据量急剧增长
- 读写数据压力的不断增加
- 数据的冷热程度不同
- 热数据经常被访问(比如用户的头像等)
- 将热数据存储到内存
Redis基本工作原理
- 数据从内存中读写
- 数据保存到硬盘
- AOF:增量数据保存到AOF文件
- RDB:全量数据保存到RDB文件
- 单线程
Redis 应用案例
- 连续签到
- 掘金用户的每日签到打卡,断签计数归0
- expire:设置为后天的0点
- 消息通知
- 用list作为消息队列
- 例如当文章更新时,将更新的文字推送到ES,用户就能搜索到最新的文章数
- 计数
- 比如文章的点赞数(如果文章数过多,那么统计会很耗时间)
- 使用hash结构存储
- 排行榜
- 排行榜经常被访问,有序且经常变更
- zset有序
- 结合dict后,可实现通过key操作跳表的功能
- zincrby myzset 2 "Alex"
- zscore myzset "Alex
- 限流
- 如果要求一秒内的最大请求数为N,超过N则禁止访问
- 分布式锁
- 并发场景下只能一个写,可以使用sds中的setnx
- Redis Setnx( SET if Not Exists )命令在指定的 key 不存在时,为 key 设置指定的值,这种情况下等同 SET 命令。当
key存在时,什么也不做
redis> SETNX mykey "Hello"
(integer) 1
redis> SETNX mykey "World"
(integer) 0
redis> GET mykey
"Hello"
SDS
- SDS是Redis中的字符串
- 可以存储字符串、数字、二进制
- 通常和expire配合使用
- 场景:存储计数、Session
- 支持c的字符串函数
Redis 使用注意事项
大Key
- 什么是大Key
- sds:value的字节数大于10kb
- Hash/set/zset/list等:元素个数大于5000个或总value字节数大于10MB
- 大Key的危害
- 读取成本高
- 容易导致慢查询(过期、删除)
- 主从复制异常、服务阻塞
- 表现
- 请求Redis超时报错
- 如何消除大Key
- sds
- 拆分:将大key拆分为小key
- 压缩:将value压缩写入,读取时解压再使用
- 集合类hash/list/set/zset
- 拆分,利用hash取余,位掩码的方式决定放在哪个key
- 区分冷热:比如榜单列表使用zset,只存前10页的数据,后续走db
- sds
热Key
- 用户访问一个key的QPS特别高
- 解决热Key的方法
- Localcache:弊端是一个业务需要Localcache
- 拆分:将热key写入多份,代价是更新需要更新多个key
- 使用Redis代理的热key承载能力:结合了上面两个功能
慢查询场景
- 批量操作:一次传输过多的key/value(mset,hmset,sadd,zadd)一次建议不超过100
- zset大部分命令都是O(log(n))当大小超过5k以上时,简单的zadd、zrem也可能导致慢查询
- 操作的单个value过大
- 对大key建delete、expire,Redis4.0之前不支持异步删除unlink
缓存穿透、缓存雪崩
- 缓存穿透: 热点数据查询绕过缓存,直接查询DB
- 危害
- 大量查询不存在的key:容易导致db响应慢或宕机
- 热key缓存过期时:会有大量请求同时击穿至于db
- 如果减少缓存穿透
- 缓存空值:如果一个key在缓存和db都不存在,则可以给他缓存一个空值
- 布隆过滤器:可以快速查询该key是否存在于db,缺点是占内存
- 危害
- 缓存雪崩:大量缓存同时过期
- 如何避免缓存雪崩
- 缓存失效时间分布均匀:将epxire时间分散开,避免大量同时失效
- 缓存集群:避免单机宕机造成的缓存雪崩
- 加锁排队
- 数据预热
- 定时更新缓存策略
- 双层缓存策略:C1为长期缓存,C2为短期你缓存,平时访问C2,失效时访问C1
- 如何避免缓存雪崩