Redis - 大厂程序员是怎么用的 | 青训营笔记

126 阅读4分钟

这是我参与「第五届青训营」笔记创作活动的第14天

1. 本堂课重点内容

  • 为什么需要redis,redis的基本工作原理
  • Redis应用案例
  • 在字节跳动,使用redis有那些主要事项

2. 为什么需要redis?

数据量小的时候我们可能使用单个数据库表就可以了,数据量增长,我们可以使用分库,分表,数据库集群,但是当数据量特别大的时候,如秒杀,抢票...,数据库的读写压力不断增大。

  • 数据从单表演进出了分库分表
  • Mysql从单机演进出了集群
    • 数据量增长
    • 读写数据压力不断增加

图片.png

  • 数据分冷热
    • 热数据:经常被访问的数据
  • 将热数据存储到内存中

图片.png

3. redis的基本工作原理

  • 数据从内存中读写
  • 数据保存到硬盘上防止重启数据丢失
    • 增量数据保存到AOF文件
    • 全量数据RDB文件
  • 单线程处理所有操作命令

图片.png

图片.png

4. redis应用案例

4.1 连续签到(String数据类型)

  • key
  • value
  • expireAt

String数据结构

  • 可以存储字符串、数字、二进制数据
  • 通常和expire配合使用
  • 场景:存储计数、Session

图片.png

4.2 消息通知 (List数据结构)

  • 使用场景:例如文章更新时,将更新后的文章推送到ES,用户就能搜索到最新的文章数据

图片.png

List数据结构Quicklist

  • Quicklist由一个双向链表和listpack实现

图片.png

  • Listpack数据结构

图片.png

4.3 计数 (哈希数据结构)

  • 一个用户有多项计数需求,可通过hash结构存储 Hash数据结构dict
  • rehash
  • 渐进式rehash

图片.png

4.4 排行榜(Zset数据结构)

  • 积分变化时,排名要实时变更
  • 结合dict后,可实现通过key操作跳表的功能
    • ZINCRBY myzset 2 "Alex"
    • ZSCORE myzset "Alex"

Zset数据结构

图片.png

图片.png

4.5 限流

  • 要求一秒放行的请求为N,超过N则禁止访问

图片.png

4.6 分布式锁

并发场景,要求一次只能由一个协程执行,执行完成后,其他等待中的协程才能执行。

可以使用redis的setnx实现,利用了两个特性

  • redis是单线程执行命令
  • setnx只有未设置过才能执行成功

图片.png

5. redis注意事项

5.1 大key、热key

5.1.1 大key的定义

图片.png

5.1.2 大key的危害
  • 读取成本高
  • 容易导致慢查询(过期、删除)
  • 主从复制异常,服务阻塞,无法正常响应请求
  • 业务侧使用大key的表现
    • 请求redis超时报错

图片.png

5.1.3 消除大key的方法

1.拆分

  • 将大key拆分为小key,例如一个String拆分成多个String

图片.png

  1. 压缩
  • 将value压缩读取解压后再使用

5.2 热key

5.2.1 热key的定义

用户访问一个key的QPS特别高,导致server实例出现cpu负载突增或者不均的情况,热key没有明确的标准,QPS超过500就有可能被识别为热key

图片.png

5.2.2 解决热key的方法
  1. 设置Localcache 在访问redis前,在业务服务侧设置Localcache, 降低访问redis的QPS.LocalCache中缓存过期或未命中,则从redis中将数据更新到LocalCache.

图片.png 2. 拆分 将key:value这一个热key复制多份使用

图片.png

  1. 字节跳动如何解决

图片.png

5.3 慢查询场景

  1. 批量操作一次性传入过多key/value, 如mset/hmset/sadd/zadd等O(n)操作,建议单批次不要超过100,超过100之后性能下降明显
  2. zset大部分命令都是O(log(n)), 当大小超过5k以上时,简单的zadd/zrem也可能导致慢查询
  3. 操作的单个value过大,超过10kb
  4. 对大key的delete/expire操作也可能导致慢查询

5.4 缓存穿透、缓存雪崩

  • 缓存穿透:热点数据查询绕过缓存, 直接查询数据库
  • 缓存雪崩:大量缓存同时过期

5.4.1 缓存穿透的危害

  1. 查询一个一定不存在的数据 通常不会缓存不存在的数据,这类查询请求会直接打到db,如果有系统bug或人为攻击,那么容易导致db响应慢甚至宕机
  2. 缓存过期时 在高并发场景下,一个热key如果过期,会有大量请求同时击穿至db,容易影响性能和稳定。同一时间大量key集中过期,也会导致大量请求落到db上。

5.4.2 减少/避免缓存穿透

  1. 缓存空值 如果不存在的userId,这个id在缓存和数据库中都不存在,则可以缓存一个空值,下次查直接返回
  2. 布隆过滤器

5.4.3 如何避免缓存雪崩

  1. 缓存空值 将缓存失效时间分散开,比如在原有的失效时间上面增加一个随机值。
  2. 使用缓存集群,避免宕机造成的缓存雪崩