Redis的介绍、事务、持久化、哨兵
介绍
Redis源码可以查看源码目录里面有各种语言,c#看这里。
是一个nosql的内存数据库,如果做缓存,优先选择redis。
Redis ,直接支持lua脚本(类似存储过程),lua脚本用标准C语言遍写并以源代码形式开放,lua脚本的代码,本身就具有原子性。
lua是c语言编写的,redis也是c语言编写,不存在编译过程。
事务
ACID
- A,原子性,保证执行多个指令的时候,要么都执行,要么都不执行,要么都成功,要么都没有成功。
- C,一致性。数据库中的数据应满足完整性约束。
- I,隔离性。事务之间互不影响。
- D,持久性。已提交的食物永久保存在数据库中。
注意:如果要使用redis的事务,最好使用Watch监听所有key。
持久化
策略机制
- 快照的方式(RDB)可以在指定的时间间隔内生成数据集的时间点快照。
每次都全量备份-- - 文件追加方式(AOF)持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。
- 同时使用AOF 持久化和 RDB 持久化。
RDB
save
一个同步保存操作,将当前 Redis 实例的所有数据快照(snapshot)以 RDB 文件的形式保存到硬盘。
Redis默认配置文件中提供了三种方式:
- save 900 1 表示 900秒(15分钟内又1个更改)
- save 300 10 表示 300秒(5分钟)内又10个更改
- save 60 10000 表示 60秒内有10000个更改
使用save命令,当数据量大的时候,会造成线程长时间阻塞,因为redis是一个单线程程序,耗时原因是因为fork操作,则当有其他客户端发送指令的时候,会卡主。
bgsave
单独的线程,后台异步一个线程去实现备份,根据我们的配置文件里策略然后去备份数据文件。
底层原理
一个定时器事件,计算数据阈值,每一次bgsave,触发dump操作,再把计数器dirty清0。
优势
备份缓慢,但是重启加载数据性能比较快。
AOF
手动触发
使用bgrewriteAOF指令,调用fork子线程船坚辛的AOF文件。
自动触发
通过修改配置文件redis.conf,持久化需要修改节点 appendonly yes 开启
日志追加:基本都是顺序读写,本身要比我们操作关系型数据库要快。
优点是:文件可读行高,每次都是追加修改的东西,备份比较快,但是当服务重启的时候,加载数据的时候比较慢
RDB、AOF优缺点
类型 | 备份 | 启动 |
---|---|---|
RDB | 慢 | 快 |
AOF | 快 | 慢 |
RDB、AOF混合
如果RDB和AOF都开启了,则默认首先加载AOF文件,为了保证数据的尽可能完整性。默认的情况下,只要开启了AOF,混合默认自动打开。
AOF重写问题:当数据文件到达一个阈值的时候,会继续重写。
Redis.4X 版本之后支持混合模式。
混合模式的好处
备份,启动快,因为这样的备份,可以通过AOF备份,通过RDB还原,可以设计为异步,进行AOF文件转化成RDB文件。
持久化选择
- 如果希望Redis的性能非常高,尽量不要用持久化
- 如果希望保证数据的完整性,可根据业务选择不同的持久化策略,一般情况使用混合模式
Redis主从同步
主从是实现读写分离,主节点可以把数据同步到从节点里面,一般情况下,使用主从的时候,防止数据不一致,从节点只能读,默认从节点不会进行写操作。 所以当主节点宕机了,我们需要改代码,收到去修改redis的配置。
为了实现高可用。主节点宕机了,从节点可以替换主节点。由于不是自动替换,需要程序员修改代码,改ip地址和端口,或者使用keeplive实现VIP高可用。主从是不会自动切换,如果要自动切换需要使用哨兵。
Redis 6.X 对多线程进行了优化,优化主要有两个方向:
- 提高网络 IO 性能,典型的实现像使用 DPDK 来替代内核网络栈的方式
- 使用多线程充分利用多核,典型的实现像 Memcached
哨兵(Sentinel)
至少三个节点,而且必须是奇数,否则容易选举不出来新的master。
什么是宕机
- 1.主观宕机:单独哨兵认为你宕机了,发现了故障。。
- 2.客观宕机:半数哨兵认为主节点宕机,发现了故障。
选举主节点的原则
1.哨兵定期通过ping确认master的响应时间。
2.从节点备份的完整性、数据备份偏移量。
3.从节点的启动时间周期,心跳检测
4.如果上面三个条件都相等,则根据节点启动时分配的run id来,如果runid越小,则最有可能选择为新的master。
选举成功后,原master宕机,新master替换原master,之后原master重新启动,原master变成从节点。
哨兵或者主从里面的数据问题
脑裂问题
master和slave之间因为网络原因,不能连接,虽然master还在运行,但有多数以上的slave认为master宕机,slave开启选举,并产生新的master。这时集群中会出现两个master。client可能还在连接旧的master,当旧master连接恢复时,会被作为一个slave,自己的数据会被清空并从新master复制数据。
异步复制数据丢失问题
由于master和slave是异步复制数据,如果主节点和从节点直接数据复制太慢,主节点宕机这个时候从节点替换主节点,会产生丢失数据。
由于没有办法保证数据百分之白不丢失,只能尽可能少量丢数据。
解决方案
修改配置文件:
1.min-slaves-to-write=0,最少能连接到几个从节点,意思是,当主节点和从节点之间互通的时候,发现从节点小于1的时候,则从节点不会再继续给客户端提供服务。 解决脑裂问题。
2.min-slaves-max-lag=10,主节点和从节点的ack时间差|响应,意思是,数据复制和同步延迟不能超过10秒,一旦所有slave的延迟偏移量超过了10秒,则master不在接收请求。
集群模式(Cluster)
由于哨兵模式写入操作都是在主节点,成为了性能瓶颈,Redis在3.0后加入了Cluster 模式,即多个节点提供服务,去中心节点方式。
根据官方推荐,集群部署至少要 3 台以上的master节点,最好使用 3 主 3 从六个节点的模式。
由于多节点都可以读写,所以产生了哈希槽,实现每一个节点只负责一部分的数据写的分片模式。
集群解决的问题
1.数据是否分配均匀
2.数据节点增删对数据分布影响不能太大
简单的hash
会导致增加机器或减少机器的时候,mod数变更,余数也变更,引起大量的缓存穿透,造成雪崩。
hash环
一致性哈希,通过哈希环的方式,来解决分布式缓存的问题。
先哈希,假设结果=1,则把数据存放在哈希环上面1-2直接的虚拟节点上面,假设1挂了影响的是1-2,并且数据会逐渐转移到2-3之间,依然可用。
一致性哈希算法对于容错性和扩展性有非常好的支持。但一致性哈希算法也有一个严重的问题,就是数据倾斜。即分片集群中,节点太少,分布不均。
hash槽
为了解决hash环的问题,Redis采用了哈希槽(slot)。
Redis一共有2^14(16384)个槽。根据CRC-16(key)%16384来判断属于哪个槽。
注意:槽位转移分配,需要人工配置,非自动。