Redis

数据类型
- String:最大512M,内容过大可以存入MonoDB或CDN缓存。序列化操作。
- 应用:缓存,计数器
- Hash,单个value过大可以拆分,使用multiGet获取。可以部分更新。
- 应用:代替String,优化存储。对象的各种属性不设置单独的key,而是存储到散列表中。
- set:集合
- 去重
- zset:有序的集合,跳表,时间复杂度O(logN)
- 排行榜
- List:队列
- 社区应用
- HyperLogLog:基数统计,比如UV统计。
- Geo:存储地理位置信息。
常见命令
- keys:查询指定模式的key列表(会阻塞线程)
- scan:无阻塞,在客户端去重,整体花费的时间较长
- setnx:设置
- experie:设置过期时间(秒)
- persist:永久有效
高可用
- 哨兵:监控:检查主服务器是否运行正常;提醒:发送故障通知;自动故障迁移:主从切换。脑裂:配置从机数量与延迟时间。
- 集群:数据分散存储。
- 一致性Hash算法(沿着hash环顺时针定位到服务器)解决节点的动态增减导致数据缓存大量减少问题,虚拟节点解决数据倾斜问题。
- hash槽:redis cluster集群中,key通过CRC16校验对16384(集群的最大节点个数)取模来决定放置在哪个槽。master节点写入数据,slave节点同步数据。master节点挂掉,slave节点会通过选举机制选出新的master节点。
持久化策略
-
RDB持久化:保存某个时间点的全量数据快照。
- 优点:fork子进程完成写操作,主进程继续处理命令,保证了redis的高性能。
- 缺点:安全性低,持久化期间redis故障数据会丢失。
-
AOF持久化:保存除了查询以外更新数据库状态的指令。
-
优点:
- 数据安全,AOF持久化配置appendfsync为always,每进行一次命令操作就记录到AOF文件中一次。
- 通过append写文件,中途服务器宕机,也可以通过redis-check-aof工具解决数据一致性问题。
- AOF的rewrite模式。AOF没有被rewrite之前,可以删除其中的某些指令。
-
-
缺点:
- 文件大,恢复慢,数据集较大时启动效率低。
同步策略
- 主从同步:初始化阶段全量同步,初始化之后增量同步(可以随时发起全量同步);
- 快照同步:将内存数据映射到硬盘,恢复较快。
过期策略
- 定时删除:创建定时器
- 惰性删除:获取键时检查键是否过期,过期则删除。
- 定期删除:每隔一段时间定期检查,删除过期键。
淘汰机制
- volatile-lru:从已设置过期时间的数据集中淘汰最近最少使用的数据。
- volatile-ttl:从已设置过期时间的数据集中淘汰即将过期的数据。
- volatile-random:从已经设置过期时间的数据集中随机淘汰数据。
- allkeys-lru:从数据集中选择最近最少使用的数据淘汰。
- allkeys-random:从数据集中随机淘汰数据。
- no-enviction:禁止驱逐数据,永不回收。
- 使用策略的规则:
- 如果数据呈现幂律分布(部分数据访问频率高),使用allkeys-lru
- 如果数据呈现平等分布,使用allkeys-random
PipeLine的好处
- 如果pipeline执行的指令之间没有因果相关性,可以将多次IO往返的时间缩短为1次。
多路IO复用
- 基于react设计模式监听IO事件。
Redis是单线程还是多线程的
- 文件事件处理器=多个套接字+IO复用程序+文件事件分派器(单线程)+事件处理器
- Redis的瓶颈不在CPU,而在于内存和网络,通过搭建多个Redis实例解决。
- Redis 6.0在网络IO的处理方面上了多线程,核心的模块还是单线程的。
Redis为什么快
- 完全基于内存,查找数据的时间复杂度是O(1)
- 数据结构简单
- 单线程,避免线程上下文切换,锁的竞争,死锁
- 多路复用IO,非阻塞IO
保证缓存与数据库双写的一致性
- Cache aside pattern:
读:先读缓存,再读数据库,更新缓存;写:先更新数据库,再删除缓存。 - 最初的缓存不一致问题:更新数据库,删除缓存(存在一致性问题)-->删除缓存,更新数据库(容易产生脏数据)。
- 高并发场景:一个队列对应一个工作线程,每个工作线程串行拿到对应的操作,然后一条一条的执行;完成数据库的修改之后更新缓存。
- 优化:可过滤多个在一起的缓存更新操作;读操作等待时间过长,直接从数据库读取旧的值。
缓存穿透、缓存击穿、缓存雪崩
- 缓存穿透:缓存和数据库中都没有的数据;解决方案:key与空值放入,设置较短的失效时间。布隆过滤器,多个无偏Hash函数得到位置。
- 缓存雪崩:缓存服务挂掉;解决方案:服务限流降级,多级缓存,预热。
- 缓存击穿:缓存中没有,数据库中有;解决方案:分布式锁,key不存在时进行set操作。
Redis做异步队列
- list结构作为队列,lpush生产消息,rpop消费消息。
- blpop,没有消息时阻塞直到消息到来。
- pub/sub主题订阅模式,通过subscribe和publish实现1:N的消息队列。消费者下线时,生产的消息会丢失,可以使用专业的消息队列。
- 实现延时队列:使用zset,时间戳作为score,消息内容作为key,zrangebyscore轮询时间戳在某个区间内的数据。
Redis做分布式锁
- setnx抢锁,抢锁之后expire给锁加过期时间防止锁忘记释放。
- 两者之间进程crash:通过setnx设置分布式锁时可以增加过期时间。
你知道的越多,你不知道的越多。

Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
浙公网安备 33010602011771号