这是我参与「第五届青训营 」伴学笔记创作活动的第 17 天
本节课介绍了Redis的基本工作原理、Redis应用案例,还有字节跳动中使用Redis的注意事项
1、什么是Redis
数据从单表演进出分库分表
MySQL从单机演进出集群:数据量增长、读写数据压力的不断增加
数据分冷热:热数据存储到内存中
1.1 Redis基本工作原理
数据从内存中读写
数据保存到硬盘上防止重启数据丢失
增量数据保存到AOF文件
全量数据RDB文件
单线程处理所有操作命令
2、Redis应用案例
2.1 掘金连续签到
GET/SET,Key过期
String数据结构:可以存储字符串、数字、二进制数据;通常配合expire使用;用于存储计数、Session
2.2 消息通知
用list作为消息队列
Quicklist:由一个双向链表和listpack实现
2.3 掘金用户计数,使用到hash
一个用户有多项计数需求,可通过hash结构存储
hash数据结构dict:
rehash:将ht[0]中的数据全部迁移到ht[1]中。数据量小的场景下,直接将数据从ht[0]拷贝到ht[1]速度是较快的。数据量大的场景,迁移过程将会明显阻塞用户请求;渐进式rehash:每次用户访问时都会迁移少量数据,将整个迁移过程平摊到所有的访问用不请求过程中
2.4 排行榜zset
使用setnx实现分布式锁
结合dict可实现通过key操作跳表的功能
2.5 zest数据结构zskiplist
查找数字7的路径,head,3,3,7
结合dict(哈希)后可实现通过key操作跳表的功能
2.5 限流
要求1秒内放行的请求为N,超过N则禁止访问
Key:comment_freq_limit_1671356046
对这个Key调用incr,超过限制N则禁止访问。1671356046是当前时间戳
2.6 分布式锁
并发场景,要求一次只能有一个协程执行
执行完成后,其他等待中的协程才能执行
可以使用redis的setnx实现,利用了两个特性:Redis是单线程执行命令、setnx只有未设置过才能执行成功
3、Redis使用注意事项
3.1 大key(查询)
value(string类型)大于10KB就是大key,元素个数大于5000个或总value大于10MB就是大key(hash/set/zset/list等复杂数据结构类型),使用大key将导致Redis系统不稳定、读取成本高、慢查询、主从复制异常、无法正常响应请求
业务侧使用大key:请求Redis超时报错
3.1.1 解决方案
拆分:拆分为小key
压缩:将value压缩后写入Redis,读取时解压后使用。压缩算法可以是gzip、snappy、lz4等
对于hash、list、zset、set:
(1)拆分:hash取余、位掩码方式决定存放在哪个key中
(2)区分冷热:如榜单列表场景使用zset,只缓存前10页数据,后续数据走DB
3.2 热Key
一个Key的QPS特别高,将导致Redis实例出现负载突增,负责均衡流量不均的情况。QPS超过500就有可能被识别为热key
3.2.1 解决方案
设置Localcache:降低Redis的QPS。LocalCache中缓存过期或未命中,则从Redis中将数据更新到LocalCache
拆分:将key:value复制写入多份,访问时访问多个key,但是value是同一个,将QPS分散到不同实例上,降低负载。但是更新时需要更新多个key,存在数据短暂不一致的风险
使用Redis代理的热key承载能力
3.3 慢查询
大key、热key的读写;一次操作过多key(mset/hmset/sadd/zadd),单批次不要超过100
3.4 导致缓存穿透、缓存雪崩
缓存穿透:热点数据查询绕过缓存,直接查询数据库
缓存雪崩:大量缓存同时过期
3.4.1 缓存穿透的危害
查询一个一定不存在的数据:查询请求直接打到DB,如果有系统bug或人为攻击,容易导致DB响应慢甚至宕机
3.4.2 缓存雪崩的危害
缓存过期时:在高并发场景下,一个热key同时过期,会有大量请求同时击穿DB,同一时间有大量key集中过期时,会导致大量请求打到DB上,导致查询变慢,甚至出现DB无法响应新的查询
3.4.3 减少缓存穿透
缓存空值:缓存空值,下次再查缓存直接返回空值
布隆过滤器:存储合法key
3.4.4 避免缓存雪崩
缓存空值,将缓存失效时间分散开,例如在原有失效时间基础上增加一个随机值。对于热点数据,过期时间尽量设置得长一些,冷门的数据可以相对设置短一些。使用缓存集群,避免单机宕机
课后个人总结
本节课介绍了Redis的基本工作原理、Redis应用案例,还有字节跳动中使用Redis的注意事项。关于Redis,我在day22、24、25、26、28阅读的文章中都有提到,所以比较了解它的工作原理、工作方法以及它能解决的问题。我觉得本节课学到的更多的是Redis的实战方法