Redis | 青训营笔记

85 阅读4分钟

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

Redis

Redis是什么

速度催生Redis

问题

单表数据->分库分表

MySQL单机->MySQL集群(数据量增长、读写数据压力不断增加)

大量数据的读取走MySQL,从磁盘取出,速度太慢

解决

将经常访问的热数据直接存储到Redis(内存)中,冷数据存在MySQL中

在读数据时就可以先访问Redis,没有在访问MySQL,大大提高读取速度

在写入时也可以通过监听Binlog从而使写入的数据保存到Redis中

Redis基本工作原理

  1. 数据从内存中读写

  2. 单线程处理所有操作命令(按命令先后顺序执行)

  3. Redis两大文件存放在磁盘中防止重启数据丢失(解决了重启导致的内存清空问题,一定程度上实现了数据持久化

    1. AOF文件,保存增量数据,如果执行失败,重启时会重新执行
    2. RDB文件,保存Redis所有数据,重启时会读取该文件

Redis应用案例

扩展:我们在不同情况使用不同数据结构的原因,一是提升性能、一是压缩存储

数据结构-sds(Java-String)

  1. 可以存储字符串、数字、二进制
  2. 和expire配合使用
  3. 使用场景:存储计数、Session

image-20230215192729835.png

消息通知

使用list作为消息队列,实现消息通知

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

在Redis中,链表的一个节点不止存放一个数据,而是使用Listpack结构存储大量数据

image-20230215193843510.png

计数

使用hash数据结构实现

hash表满了之后存储数据会产生哈希冲突,可以通过相同节点下拉链表解决,但是链表太长严重影响hash查询速度,正常是O(1),因此当链表达到一定长度,会进行扩容,在扩容过程中会将链表数据存到新的节点(数据迁移),这就涉及到rehash,新建一个hash表,将旧表中的数据迁移到新表,但是扩容不能影响用户正常使用,因此需要渐进式rehash,基本原理就是,每次用户访问时都会迁移少量数据,将整个迁移过程,平摊到所有的访问过程。

排行榜

使用zset数据结构实现

限流

分布式锁

使用setnx实现,两个特性(Redis是单线程执行命令、setnx只有key未设置过才能执行成功)

存在的缺陷:业务超时解锁导致并发问题,业务执行时间超过锁超时时间、redis主备切换临界点问题,主备切换后,A持有的锁还未同步到新的主节点时,B可以在新主节点获取点,从而导致并发访问、redis集群脑裂,导致出现多个主节点

Redis使用注意事项

1.大Key

数据类型大Key标准
String类型value的字节数大于10kb
Hash/Set/Zset/list等复杂数据结构元素个数大于5000或总value字节数大于10MB

危害

  1. 读取成本高
  2. 容易导致慢查询(过期、删除)
  3. 主从复制异常,服务器阻塞,无法正常响应请求
  4. 请求Redis超时报错

解决

拆分、压缩(主要考虑解压缩问题,因为Redis写少读多)、冷热分离(zset只缓存前十页数据,后续走db)

2.热Key

用户访问一个Key的QPS特别高,导致Server实例出现cpu负载突增或者不均的情况,这种Key就是热Key

解决

1.设置Localcache

在业务服务侧设置Localcache,降低Redis的QPS。Localcache未命中或缓存过期,再从Redis更新数据。Java的Guava、Golang的Bigcache就是这类LocalCache

2.拆分

将热Key复制到多个实例中,降低单个实例的负载

3.Redis代理

具备热Key承载能力,具备热Key发现并且自己是实现了LocalCache功能

3,慢查询场景

批量操作一次性传入过多Key/Value,性能会明显下降、zset命令时间复杂度大部分都是O(log(n))等

4.缓存穿透、缓存雪崩

缓存穿透:热点数据查询绕过缓存,直接查询数据库

危害:查询不存在的数据,或者缓存过期时,大量数据会直接走db,短时间大量访问db会导致db宕机

缓存雪崩:大量缓存同时过期

解决

  1. 减少缓存穿透

    1. 缓存空值,数据在缓存和数据库都不存在,下次再访问直接返回空值
    2. 布隆过滤器,使用Bloom filter算法存储合法Key,该算法具有超高压缩率,占用极小空间就能存储大量key值
  2. 避免缓存雪崩

    1. 缓存空值,将缓存失效时间分散开
    2. 使用缓存集群,避免单机宕机造成的缓存雪崩