这是我参与「第五届青训营 」伴学笔记创作活动的第 9 天
1. Redis 的应用
- 稀土掘金中,被阅读次数高的文章被储存在 Redis 中,方便快速访问
- 一个用户有多项计数需求,其计数信息被储存在一个结构体中,接着用 uid 作为 key,哈希处理得到用户的计数信息
2. sds 数据结构
3. list消息队列
-
使用场景:
golang 中,可以维护一个 list 消息队列,然后将消息队列的内容推给目标程序
-
数据结构:
Quicklist,链表元素有next、prev、entry
entry 的数据结构是 listpack,listback 的组成包括 tot-bytes、num-elements、element-1、element-2 . . . element-N、listpack-end-byte(255)
4. Hash 数据结构
- hash 数据结构中包含一个槽位拉链,每个槽位代表一个 key 的 Hash 计算值
- 当随着数据量的增加,Hash 的槽位不够用时需要扩容,增加槽位的数量、改变 Hash 算法扩容的过程称为 ReHash
- 渐进式 ReHash 是重新开辟一个 Hash 槽位链表,然后每次用户访问一个数据时就会把数据同时存储到新的槽位链表中
5. 实时更新榜单的实现
- 结合dict,使用key操作跳表(SkipList),实现榜单的倒排序
6. 在字节跳动中使用 Redis 时的注意事项
-
大 Key 和热 Key
-
大key:
当key的value大于10KB时
当key的value是组合型,且元素数量大于5000时
读取成本高,容易导致慢查询(过期、删除),主从复制异常 服务异常 无法相应请求
大key的处理方法:将大 key 拆分成小 key,压缩 将value压缩后写入 redis,读取解压后使用,压缩算法可以是 gzip, snappy,lz4等 如果存储的时json字符串 可以使用 MessagePack 进行压缩,集合类结构可以对value区分冷热,比如榜单类数据可以只存储前10页数据,后续数据走db
-
热key:
解决方法:拆分 将同一个 value 对应不同的 key 分配到的实例上 代价是拷贝数据需要额外资源 存在主从不一致的风险;使用 Redis 的代理实现热 key 的承载能力 基础原理是 热key发现和 localcache
-
慢查询:
导致慢查询的操作:批量操作 一次传入大量数据 建议单批不超过100个数据;zset 大部分命令是 O(log(n)) 当超过5K时 性能下降明显
-
缓存穿透:
热点数据查询绕过缓存,直接查询数据库
减少缓存穿透:缓存空值 经常查询一个不存在的数据以空值形式存储到缓存
-
缓存雪崩:
大量缓存同时到期
避免缓存雪崩:将缓存失效事件分散开;使用缓存集群 避免单机宕机引发缓存雪崩