Day17 redis | 青训营笔记
这是我参与「第五届青训营」伴学笔记创作活动的第 17 天
为什么需要redis
数据分冷热
- 热数据:经常被访问的数据
经常访问的数据如果直接从数据库读取那么性能会非常差,因此将数据存储在内存中的redis应运而生
redis的使用分读写两种场景
-
读场景 客户端获取后台的数据前先从redis中读取,如果redis中没有相应的数据才会去数据库中读取,数据库中社区到数据之后会将数据存入redis
-
写场景
数据库中的数据发生改变,redis中如果有对应的数据,redis中的数据原需要修改
redis中的数据和mysql同步可以使用redis监听mysql的binlog来实现
基本工作原理
redis将数据存入内存会导致redis服务重启之后数据丢失,如果直接存入磁盘那么会导致redis的性能损耗
那么redis是怎么做到读写性能快,并且可以数据持久化的呢?
redis客户端对redis服务侥幸读写操作使用的是RESP协议
redis进行读写操作之前会将读写操作的日志写入磁盘中的AOF文件中
除了AOF文件,redis还会将数据存入RDB文件中,增量数据redis会存入AOF文件,全量数据redis会存入RDB文件,redis重启时会读取RDB文件
redis使用案例
-
连续签到
用户每日有一次签到机会,用户断签则将用户的签到计数归0 redis可以将用户的签到次数存入redis,并且设定为次日0点过期 签到次数建议使用String数据结构
-
消息通知 使用list作为消息队列 list数据结构(QuickList)由一个双向链表和listpack实现
redis中的双向链表的每个节点除了有前后指针,还包含一个listpack结构,listpack可以存储多个数据元素,每个listpack都包含一个
tot-bytes
表明listpack所申请的空间,以及一个num-elements
代表listpack中的元素个数,listpack的末尾还有一个listpack-end-byte
,限定为255,在listpack末尾占位 -
计数 一个用户有多项计数需求,可以使用hash结构存储 可以快速地从redis中取出多个数据
-
排行榜 积分变化,排名根据积分实时变更 使用zset
redis的zskiplist层数不会超过4层
-
限流 要求1秒内放行的请求数为N,超过N则禁止访问 key:
freq_limit_114514
(114514为时间戳) 对这个key调用自增,key的值超过N则禁止访问 -
分布式锁 一次只能由一个协程执行 可以用redis的setnx实现
- redis时单线程执行
- setnx只有未设置过才能执行成功
注意事项
大Key、热Key
大key:
数据类型 | 大key标准 |
---|---|
String | value的字节数大于10KB |
hash/set/zset/list等复杂数据类型 | 元素个数大于5000个或总字节数大于10MB |
危害:
- 读取成本过高
- 容易导致慢查询
- 主从复制异常
消除大key的方法
- 拆分 将大key拆分为小key。例如一个String拆分为多个String
- 压缩 将value压缩后写入redis,读取时解压后再使用,可以使用gzip、snappy、lz4等算法压缩数据。如果使用的是json数据,那么可以使用MessagePack进行序列化
- 对于集合类数据结构
- 拆分:可以用hash取余、位掩码(位掩码速度更快)的方式决定放在哪个key中
- 区分冷热:例如表单类场景使用zset,可以只存放前10页数据,其他数据从数据库中查询
热key:
用户访问一个key的qps特别高,就会导致server出现cpu负载突增或不均
热key没有明确定义,qps超过500就有可能被识别为热key
解决方法:
-
localcache 访问redis之前,在服务侧设置localcache,降低redis的qps(例如java的guava, golang的bigcache)
-
拆分
将
key:value
这个热key复制多分,例如拆分成key1:value
key2:value
,缺点是容易导致短暂的数据不一致 -
redis代理
本质是结合了
热key发现
和localcache
两个方功能客户端通过proxy访问redis,访问过程中会对key进行次数统计,如果判定一个key为热key,那么热key的数据就不再从redis中读取,而是从proxy服务的localcache读取
慢查询
- 使用pipeline可以进行批量操作,但是如果单批次操作超过100会导致明显的性能下降
- zset大部分命令是
的时间复杂度,当大小超过5kb以上,简单的zadd/zre操作也会导致慢查询 - 操作的单个value过大(应避免使用大key)
缓存穿透 缓存雪崩
缓存穿透:热点数据直接绕过查询,直接查询数据库
缓存雪崩:大量缓存同时过期
缓存穿透的危害
-
查询一个一定不存在的数据
这类请求的查询会传到数据库,如果这是系统bug或人为攻击,会导致db服务异常
-
缓存过期 高并发场景下,热key过期会有大量的请求击穿至数据库,会导致db服务异常
同一时间大量的key集中过期也是如此
减少缓存穿透
- 缓存空值 如果一个值在缓存和数据库中都不存在,则可以缓存为一个空值,下次查询直接返回空值
- 布隆过滤器 通过布隆过滤器存储合法的key
避免缓存雪崩
-
分散缓存时间
将缓存的失效时间分开,在原有的缓存时间上增加一个随机值 对于热点数据的过期时间要尽量长一些,冷数据可以相对短一些
-
使用缓存集群,避免单机宕机导致雪崩
本文作者:七つ一旋桜
本文链接:https://www.cnblogs.com/poifa/p/17716910.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步