Redis
Redis基础
1. 为什么要用Redis:高性能、高并发、高可用
- 高性能:redis将数据存放在内存,不需要从磁盘中加载到内存,数据读写速度快。因此一般使用redis作为缓存层,存放热数据
- 高并发:redis因为它自身的几个特性,所以能够承受的并发量比后端数据库大,支持大量的并发读写操作,适合应付高并发场景。
- 高可用:redis支持主从复制、哨兵模式和集群部署
2. 为什么redis这么快:基于内存、数据结构简单、单线程、io多路复用
- 基于内存读写,不需要从磁盘中加载数据
- 单线程架构,避免了多线程的切换和竞争,不会发生阻塞
- 数据结构简单,kv键值对形式
- io多路复用模型,IO多路复用器同时监听多个连接,文件事件处理器从队列中读取事件进行分发。
3. IO多路复用模型
- 通过IO多路复用器同时监听多个socket连接,有连接,将事件存入队列,文件事件分发器从队列中读取事件,根据不同的事件类型分发到对应的处理器
- 如果是连接请求,关联到连接应答处理器
- 如果是写请求,关联到命令请求处理器
- 如果是读请求,关联到命令回复处理器
Redis数据结构
1. 五种数据结构:String、List、Set、Hash、ZSet
- String:kv键值对形式,可以存放任意数据类型,value最大512MB
- get、set、incr、decr
- 缓存、分布式session、计数器
- Hash:key kv键值对形式
- hget、hset
- List:有序可重复,一个key对应多个value,最多2的32次方-1个
- Lpush、Lpop、Rpush、Rpop、Bpush、Bpop
- 栈、队列、消息队列
- Set:无序无重复,一个key对应多个element,最多2的32次方-1个
- sadd、srem
- 存标签
- ZSet:有序无重复,一个key对应多个value,为value分配一个分数作为排序的标准
- zset、zscore、zrank、zrange
- 排行榜:zrange key start end [withsocre]
2. Zset底层是跳表、为什么不能用红黑树
- 跳表,是一种可以使用二分查找的有序链表,使用二分查找进行搜索,找到目标值所在区间就进入下一层继续搜索,直到找到目标值
- 红黑树和跳表的查询时间复杂度都是Ologn,但是红黑树的增删改需要通过旋转来维持树的平衡,开销大,并且红黑树的空间开销也比跳表大
Redis持久化
- RDB:默认的持久化方式,保存数据到dump.rdb
- 两种方式
- save:阻塞redis服务器,先完成保存然后才能继续读写,可能造成长时间阻塞,线上环境不建议使用
- bgsave:非阻塞,fork一个子进程进行保存,阻塞时间短
- 优缺点
- 优:RDB文件恢复速度快
- 缺:RDB文件数据完整性不高
- 同步方式:从机发送sync请求,主机将rdb文件回应给从机,从机将数据写入
- 两种方式
- AOF:在配置文件中手动开启,保存数据到appendonly.aof,先将数据写入到内存的aof缓冲区,然后再同步到磁盘的aof文件
- 三种模式
- always:每次触发都会将aof缓冲区的所有数据同步到aof文件
- seconds:每秒将aof缓冲区的数据同步到aof文件
- no:由系统自行决定什么时候同步
- 优缺点
- 优:aof文件数据完整性高
- 缺:aof文件大,恢复速度慢
- aof文件重写:合并重复的命令
- 三种模式
- 同时开启RDB和AOF,使用AOF保证数据的完整性,使用RDB做冷备份,实现快速恢复
Redis集群
- 主从复制:读写分离,主服务器负责写,从服务器负责读,因为一般都是读多写少,使用从服务器分担读的压力,主从服务器之间数据同步
- 可以通过配置文件或者是命令行配置:slaveof 主机ip 主机端口
- 优缺点
- 优:读写分离,并发高
- 缺:主机一旦宕机,整个集群就没有可以写的节点
- 复制方式:全量复制和增量复制,发送sync阻塞报文请求同步
- 哨兵模式:解决主从复制主机宕机后没有可写节点的问题,主机宕机后,哨兵之间通过投票选取一个从机作为主机继续写,原来的主机重连后只能作为从机进行读
- sentinel.conf配置:sentinel 主机名 主机ip 主机port 切换所需的哨兵数量
- 优:自动故障迁移,保证高可用
- 任务
- 监视:监视redis集群的服务器,如果有多个哨兵,哨兵之间也会相互监视
- 记录和报告:当redis服务器出现异常时,将异常信息记录到日志文件
- 自动故障迁移:主机宕机后,哨兵之间通过投票选取一个从机作为主机,原来的主机重连后只能作为从机
- 集群模式:多个主从复制+哨兵模式组合而成,集群通过hash槽进行数据分片存放实现数据的同步,一共16384个hash槽
Redis其他
1. key过期策略:定时删除、惰性删除、定期删除
- 定时删除:为key设置过期时,设置一个定时器,key过期后,定时器执行删除key
- 优:内存占用少,及时删除过期key
- 缺:如果有大量的过期key需要删除,CPU占用高
- 惰性删除:当访问key时才检测key是否过期
- 优:不需要及时删除过期key,CPU占用低
- 缺:内存占用高,存在大量的过期key未删除
- 定期删除:每隔一段时间检查一部分的key,key过期就删除
- 优:通过自定义检测周期实现CPU占用和内存占用达到一种相对的平衡
- 缺:检查周期难以制定,如果检测周期太短,频繁触发检测,导致CPU占用高。如果检测周期太长,存入大量的过期key无法及时删除,内存占用高
- Redis使用惰性删除和定期删除,每100ms检测一部分key
2. 内存淘汰机制:当内存达到上限时通过删除key来释放内存
- noevication:不淘汰key
- allkeys-random:随机删除key
- allkeys-lru:删除所有key中最少被使用的
- volatile-lru:删除设置了过期时间中最少被使用的
- volatile-random:设置了过期时间中随机删除
- volatile-lfu:删除设置了过期时间中一段时间内最少被使用的
- volatile-tll:删除剩余时间最少的
3. 缓存击穿、缓存穿透、缓存雪崩
- 缓存击穿:热点key突然过期,大量请求打入数据库
- 使用布隆过滤器:先将数据库的数据预存到布隆过滤器中,如果请求从缓存中获取的数据为null时,先查询布隆过滤器,如果布隆过滤器中没有,则数据库中必定没有,如果布隆过滤器中有,也不能确定一定有,还需要查询数据库,如果数据库中确实有,回填数据到缓存,返回结果
- 缓存穿透:恶意请求,缓存和数据库中都没有,但是每次都会请求到数据库
- 可以使用布隆过滤器
- 缓存雪崩:大量的key同时失效
- 为key设置随机的过期时间,避免大量key同时失效
- key不设置过期时间,但是内存开销大
4. 布隆过滤器:数据结构、如何存储、如何查找
- 数据结构:bit数组
- 存储:定义多个hash函数,对数据进行hash计算,得到index位置,将table[index]设置为1。
- 查找:对数据进行hash计算,得到多个index,如果table[index]结果集存在0,说明该数据一定不存在。如果table[index]结果集全为1,也不能确定一定存在,因为可能发生hash冲突,还需要进一步确认