Redis 的使用
Redis 的使用
数据从单表到分库分表,mysql 从单机到集群,都说明了目前数据量在不断地增长以及对于数据地读写压力不断增加,为了我们可以更快地访问数据,我们可以对数据进行冷热分隔,将热数据存储到内存当中
Note: 热数据:指我们需要经常访问地数据
Redis 的基本工作原理
- 将数据将从内存中读取和写入
- 数据可以保存在磁盘上,以防重启时数据的丢失
- 增量的数据将保存到AOF文件中
- 全量的数据RDB文件
- 所有的命令将在单线程中进行操作
Redis 应用场景
连续签到
有时候我们在某个论坛或者一些网站中会显示我们连续签到的天数,用户每天可以签到一次,如果断签,连续签到计数将进行归零
我们可以使用 String 来达到我们的目的,在 Redis中是 sdshdr
- 可以存储字符串 数字 以及二进制数据
- 一般搭配 expire 控制过期的时间
- 主要用于 存储计数以及 session 会话中
消息通知
有时候我们可能在某一个视频网站订阅了某一个博主,这样我们就可以及时收到关于博主的各种动态包括视频的发布,或者是博主文章进行更新,我们就可以在 Redis 中使用 List
Redis 中的 List 是QuickList由双向链表和listpack实现
Listpack的数据结构
计数
如果我们对数据需要进行多项的记录,我们可以使用 Hash 数据结构来进行存储
Hash 数据结构 Dict
- Rehash 当我们的数据增大时,为了降低在一条链上的查询时间,会对链进行扩充,增加槽位,达到我们快速访问数据的目的,所以可能就会发生数据的迁移,在数据量小的场景下,数据的拷贝时比较快的,但是数据增加时,进行数据的拷贝,我增大我们系统资源的开销,由于是单线程,势必会阻塞这时对资源的请求,我们访问数据的速度就会减慢,甚至无法响应
- 为了避免出现上述情况,我们通常会采用渐进式的 Rehash 方案 - 在用户进行数据的访问时我们只会迁移少量的数据,将整个迁移的过程平摊到所有的访问不请求中
排行榜
当我们要对用户的某项数据进行数据的排名显示时,我们可以通过数据库中的 group by 进行数据的排列,在数据访问量以及数据库的数据量较少时,可以采用这种方案,但是当我们的各个数据量上来时,就会给数据库增大压力,甚至无法进行数据的响应,而我们这时就可以通过 Redis 的 zset 进行替换
Redis 的 zset 的数据结构是一个跳跃表但结合了 dict 实现通过 key 操作跳表的功能,达到我们对于数据的快速访问
SkipList
有时候我们的网站为了防止一些恶意访问,我们会针对某个请求的访问量进行限制,我们就可以在 redis 中设置某个key调用 incr 设定某个值,当达到设定值时禁止访问
在分布式中,要求一次只能有一个协程执行,当前协程执行完成之后,其他的协程才能运行,我们可以使用 redis的 setnx 进行进行数据的限制,我们只要利用了 redis 的两个特性
- Redis 是单线程执行命令的
- setnx 只有未设置才能执行成功
Redis 在使用中需要注意的事项
大key 热 key
对于大 Key 的定义
-
string 类型 value > 10KB
-
Hash Set Zset list 元素的个数或者value的字节数 > 10MB
大 Key 的危害
- 读取成本高
- 容易导致慢查询(过期 删除)
- 主从复制异常 服务阻塞
- 无法正常响应请求
在业务侧使用大 Key 时,可能会造成请求 Redis 超时报错
消除大 key 的方法
- 将大 key 拆分成小key
- 将value压缩后写入 redis 读取时再进行使用,通常情况下一个压缩算法的压缩率高的话,需要解压的时间耗时就长
- 集合类结构可以进行拆分,使用hash取余 位掩码的方式决定存储的key
- 区分冷热数据,像榜单数据只缓存前几页数据,后面的数据再db中存储
用户访问一个 key 的 QPS 比较高的话,可能会导致 server cpu 负载突增或者不均的情况
- 我们可以设置 Localcache,降低访问 redis 的 QPS。LocalCache 中缓存过期或者未命中,则会从 redis 中更新数据到 LocalCache
- 我们可以将对应 key 的 value 复制多份,分散到不同 key 上,但是更新时需要更新多个 key ,在一定时间内可能存在数据不一致的情况