Redis知识结构图
一、Redis简介
官方介绍
Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区。
Redis优势
性能极高:Redis能读的速度是110000次/s,写的速度是81000次/s 。
数据类型丰富:Redis支持二进制案例的 String, List, Hash, Set 及 Ordered Set 数据类型操作。
原子性:Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
丰富特性:支持 publish/subscribe, 通知, key 过期等等特性。
常用五种基本数据类型
字符串(string)
特点: 存储string类型或者数字类型,数字类型可通过命令进行+1,-1
使用场景:如标识位,微博粉丝数,预先生成的分析统计报表等
哈希表(hash)
特点: string类型的key-value映射表,适合存储对象
使用场景:如存储需要缓存的对象数据
列表(list)
特点:字符串列表,最大长度为int最大值,可以添加一个元素到列表的头部或尾部
使用场景:可以存储如粉丝列表,关注列表
无序集合(set)
特点:hash表实现,元素不能重复,可以查交集,去重
使用场景:如两个页面被哪个相同的用户访问了
有序集合(sorted set)
特点: string类型元素集合,不能重复,每个元素关联一个分数,按分数自小到大排序
使用场景:如各种排行榜,游戏榜
二、Redis使用
1. 将数据持久化到磁盘
RDB方式
持久化实现: redis的默认持久化方式,周期性的将一阶段的数据写入硬盘,文件以.rdb形式结尾
优点:
- 每一个时间段都会生成一个数据文件,易备份,易恢复
- 对Redis性能影响较小,通过子进程周期持久化备份,数据恢复速度快
缺点:
- 快照文件,默认5分钟甚至更久才会生成一次,容易丢失近期数据
- RDB生成快照文件,文件如果很大会造成客户端暂停,可能会影响系统使用
AOF方式
持久化实现: 以append-only只追加的方式将所有客户端执行的写命令记录到日志文件中
参数配置:
开启 AOF 同步 appendonly yes
每秒同步一次 appendfsync everysec
AOF优点
配置 appendfsync everysec 则一秒执行一次,间隔时间短,不会造成大范围数据丢失,最多丢失一秒
以append-only只追加的方式写入数据,减少了磁盘寻址的开销,写入性能高
AOF日志以非常可读的方式写入, 便于数据误删除的紧急恢复
AOF缺点
数据恢复相比RDB更慢
相同数据,AOF文件要比RDB更大
写的QPS相比RDB有所降低(但依然很强)
注:两种方式全部开启的话,Redis重启时会默认使用AOF的方式重新构建数据
那么如何选取Redis持久化的方式呢?
建议两种一起使用,可以使用AOF减少数据丢失,使用RDB做快速数据恢复,同时辅以AOF做数据补充
2. 使用Redis实现分布式锁
详见博客:实现Redis分布式锁
3. 过期键的删除策略
被动删除
访问key时,发现key已过期,那么会将key删除
主动删除
定时清理key,每次清理会依次遍历所有DB,从中取出20个设有过期时间的key,如果有5个key过期,则继续对这个DB进行清理,直至过期key不超过25%
三、Redis集群
主从模式
特点: 主从复制,读写分离,主写从读
优点
数据备份:主从复制实现了数据热备份
负载均衡:主节点增删改查,从节点读,写少读多的场景可极大提高Redis吞吐量
高可用基础:主节点挂掉,从节点可升为主节点,恢复服务
缺点
主节点挂掉后,从节点不能马上提供服务,需要手动拉起,不能达到高可用
Redis如何主从同步?
主节点负责读写,数据变化后,将数据同步给从节点,从节点只能从主节点同步数据,只有读的功能
Redis主从复制的原理?
一个从节点启动后会发送一个PSYNC命令给主节点,如果从节点是初次连接到主节点,会触发一次全量复制,此时主节点会启用一个后台线程生成一份RDB快照文件,同时还会将从客户端新收到的写命令缓存到内存中。RDB文件生成完毕后会发送给从节点,从节点先保存到本地磁盘,之后加载到内存中。接着主节点会将从客户端新收到的所有写命令同步给从节点,从节点同步这些数据。如果从节点和主节点之间发生了网络故障,连接断开,会自动连接,连接之后,主节点仅会将部分缺失的数据同步给从节点。
哨兵模式
特点: 通过Sentinel对Redis节点的监控,通知及故障转移实现高可用,Sentinel自己也可采用集群模式
心跳检测及故障转移
Sentinel会给Redis节点发送心跳,监控节点状态,当与master节点心跳丢失,就会判断主观下线
当存在半数以上节点判断主观下线后即判断为客观下线
sentinel节点中会选举出一个sentinel leader来执行redis主节点的故障转移。
优点
可通过Sentinel自动进行故障转移实现高可用
缺点
集群所能存储的数据是由单台服务器所决定的,海量数据依旧受限,同时主从复制同步不精准
cluster模式
特点: 采用无中心化设计,每个节点都包含一个主节点及多个从节点
存储模式
每个节点各存储一部分数据,通过16384个插槽均匀分配 (Redis 会根据 crc16的算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽)
优点
每个节点有一个主节点及多个从节点,主节点挂掉,从节点即成为主节点,实现高可用
多个节点可同时进行读与写
通过插槽热点数据大致均匀的分布在各节点上,分压,不需要数据同步,保证了CP
扩展容易,插槽分配,增加节点,只需移动分配插槽对应的数据
四、常见生产问题
缓存穿透
1. 什么是缓存穿透?
访问数据库中不存在的数据,造成数据库压力
2. 如何解决缓存穿透?
数据库中不存在的数据返回一个null值填充到缓存中,下次访问直接返回null
3. 如果每次穿透不同的key怎么办?
可以使用布隆过滤器,判断数据库中key存在,再行访问,不然直接返回
4. 布隆过滤器存在大量hash冲突怎么办?
可以考虑多设几个hash函数,几个全部冲突的概率会大大降低
缓存雪崩
1. 什么是缓存雪崩?
大批量热点数据集中失效
2. 如何解决缓存雪崩?
热点数据分散过期时间,如范围内随机数过期
缓存击穿
1. 什么是缓存击穿?
大量并发访问同一失效的热点数据
2. 如何解决缓存击穿?
数据库查不到返回null值填充到缓存中,同时加锁,控制同一时刻只能有一个访问数据库
Redis缓存淘汰策略
Redis缓存淘汰策略有哪些?
1. volatile-ttl: 在设置了过期时间的数据集里,淘汰离过期时间最近的 key;
2. volatile-random: 在设置了过期时间的数据集里,淘汰任意一个 key;
3. volatile-lru: 在设置了过期时间的数据集里,淘汰最近最不常使用的 key;
4. allkeys-random: 在所有数据集里,淘汰任意一个 key;
5. allkeys-lru: 在所有数据集里,淘汰最近最不常使用的 key;
6. noeviction: 返回报错。
注:建议使用 ttl 和 lru ,如random有很多不确定性,很可能淘汰你需要的数据,当然具体还是要结合业务场景而定.
Redis使用场景
1. 列举一下Redis的使用场景?
缓存热点数据,减轻数据库压力
很多幂等可以通过Redis的setnx实现
可以通过Redis实现分布式锁
可以通过Redis实现简单的消息队列
可以通过Redis进行游戏排行等
可以通过Redis实现计数器
限速器,比如限制用户访问某个接口的频率(如快速点击)
Redis常见问题
1. Redis与其他key-value存储有什么不同?
数据结构更为复杂且提供原子性操作
内存中操作数据效率更高且数据可以持久化到磁盘
2. Redis是否是单线程?
从网络IO和键值对读写方面来讲,Redis是单线程的
从整体来讲,Redis是多线程的,如它会派生子线程去处理数据持久化
注:Redis4.0推出了子线程异步处理耗时操作,6.0推出了多线程,可在高并发场景下利用COU多核多线程读写客户端数据
3. 为什么Redis这么快?
Redis的大部分操作在内存中完成
有高效的数据结构,如hash表由hash桶和跳表实现
Redis采用了多路复用机制,在网络IO中能并发处理大量的客户端请求
注: IO多路复用即在一个线程内可以处理多个socket的io请求,即同时处理多个IO请求
4.如何保证Redis和mysql的数据一致性?
延迟双删 + 缓存超时设置(删除缓存=》写数据库=》休眠=》再次删除缓存)
异步更新缓存(如利用MySQL binlog及消息队列进行增量订阅消费)
转自:https://www.cnblogs.com/liunaixu/p/17211511.html