Redis数据安全性分析

64 阅读11分钟

Redis数据持久化机制详解

Redis提供了很多跟数据持久化相关的配置,⼤体上,可以组成以下⼏种策略:

⽆持久化:完全关闭数据持久化,不保证数据安全。相当于将Redis完全当做缓存来⽤

RDB(RedisDatabase):按照⼀定的时间间隔缓存Redis所有数据快照。

AOF(Append Only File):记录Redis收到的每⼀次写操作。这样可以通过操作重演的方式恢复Redis的数据

RDB+AOF:同时保存Redis的数据和操作。

两种⽅式的优缺点

图片.png 整体使⽤建议:

1、如果你只是把Redis当做⼀个缓存来⽤,可以直接关闭持久化。

2、如果你更关注数据安全性,并且可以接受服务异常宕机时的⼩部分数据损失,那么可以简单的使用RDB策略。这样性能是⽐较⾼的。

3、不建议单独使⽤AOF。RDB配合AOF,可以让数据恢复的过程更快。

RDB详解

RDB可以在指定的时间间隔,备份当前时间点的内存中的全部数据集,并保存到餐盘⽂件当中。通常是dump.rdb⽂件。在恢复时,再将磁盘中的快照文件直接都会到内存⾥。

由于RDB存的是全量数据,你甚⾄可以直接⽤RDB来传递数据。例如如果需要从⼀个Redis服务中将数据同步到另⼀个Redis服务(最好是同版本),就可以直接复制最近的RDB⽂件。

图片.png

何时会触发RDB备份

1> 到达配置⽂件中默认的快照配置时,会⾃动触发RDB快照

2>⼿动执⾏save或者bgsave指令时,会触发RDB快照。 其中save⽅法会在备份期间阻塞主线程。bgsve则不会阻塞主线程。但是他会fork⼀个⼦线程进⾏持久化,这个过程中会要将数据复制⼀份,因此会占⽤更多内存和CPU。

3> 主从复制时会触发RDB备份。

LASTSAVE指令查看最后⼀次成功执⾏快照的时间。时间是⼀个代表毫秒的LONG数字,在linux中可以使⽤date -d @{timestamp} 快速格式化。

AOF详解

1、AOF能⼲什么

以⽇志的形式记录每个写操作(读操作不记录)。只允许追加⽂件⽽不允许改写⽂件。

2、相关重要配置

1> appendonly 是否开启aof。 默认是不开启的。

2> appendfilename ⽂件名称。

图片.png Redis7中,对⽂件名称做了调整。原本只是⼀个⽂件,现在换成了三个⽂件。base.rdb⽂件即⼆进制的数据⽂件。incr.aof是增量的操作⽇志。manifest则是记录⽂件信息的元⽂件。其实在Redis7之前的版本中,aof⽂件也会包含⼆进制的RDB部分和⽂本的AOF部分。在Redis7中,将这两部分分成了单独的⽂件,这样,即可以分别⽤来恢复⽂件,也便于控制AOF⽂件的⼤⼩。

图片.png 从这⼏个⽂件中能够看到, 现在的AOF已经具备了RDB+AOF的功能。并且,拆分增量⽂件的⽅式,也能够进⼀步控制aof⽂件的⼤⼩。

3> appendfsync 同步⽅式。默认everysecond 每秒记录⼀次。no 不记录(交由操作系统进⾏内存刷盘)。 always 记录每次操作,数据更安全,但性能较低。

4> appenddirname AOF⽂件⽬录。新增参数,指定aof⽇志的⽂件⽬录。 实际⽬录是 {dir}+{appenddirname}

5> auto-aof-rewrite-percentage, auto-aof-rewrite-min-size ⽂件重写触发策略。默认每个⽂件64M, 写到100%,进⾏⼀次重写。

图片.png AOF⽇志恢复

如果Redis服务出现⼀些意外情况,就会造成AOF⽇志中指令记录不完整。例如,⼿动编辑appendonly.aof.1.incr.aof⽇志⽂件,在最后随便输⼊⼀段⽂字,就可以模拟指令记录不完整的情况。这时,将Redis服务重启,就会发现重启失败。⽇志⽂件中会有如下错误⽇志:

图片.png

图片.png

混合持久化策略

图片.png

Redis集群Cluster机制详解

图片.png ⼀句话总结:将多组Redis Replica主从集群整合到⼀起,像⼀个Redis服务⼀样对外提供服务。

所以Redis Cluster的核⼼依然是Replica复制集。

Redis Cluster通过对复制集进⾏合理整合后,核⼼是要解决三个问题:

1》 客户端需要频繁切换master的问题。

2》服务端数据量太⼤后,单个复制集难以承担的问题。

3》master节点挂了之后,主动将slave切换成master,保证服务稳定

Cluster的核⼼配置

Cluster的基础搭建⼯作在基础版中已经给⼤家逐⼀演示,这⾥同样不再赘述。接下来还是以单机快速模拟三主三从的Redis集群服务,带⼤家深⼊理解集群的原理。

构建Redis集群的核⼼配置是要在redis.conf中开启集群模式。并且指定⼀个给集群进⾏修改的配置⽂件。

图片.png

图片.png 接下来依次创建6381,6382,6383,6384,6385,6386六个端⼝的Redis配置⽂件,并启动服务。

接下来就可以构建Redis集群。将多个独⽴的Redis服务整合成⼀个统⼀的集群。

图片.png 其中 --cluster create表示创建集群。 --cluster-replicas 表示为每个master创建⼀个slave节点。接下来,Redis会⾃动分配主从关系,形成Redis集群。

集群启动完成后,可以使⽤客户端连接上其中任意⼀个服务端,验证集群。

图片.png

详解Slot槽位

Redis集群设置16384个哈希槽。每个key会通过CRC16校验后,对16384取模,来决定放到哪个槽。集群的每个节点负责⼀部分的hash槽。

图片.png

问题1、Slot如何分配

Redis集群中内置16384个槽位。在建⽴集群时,Redis会根据集群节点数量,将这些槽位尽量平均的分配到各个节点上。并且,如果集群中的节点数量发生了变化。(增加了节点或者减少了节点)。就需要触发⼀次reshard,重新分配槽位。⽽槽位中对应的key,也会随着进⾏数据迁移。

图片.png

reshard操作会从三个旧节点当中分配⼀部分新的槽位给新的节点。在这个过程中,Redis也就并不需要移动所有的数据,只需要移动那⼀部分槽位对应的数据。

除了这种⾃动调整槽位的机制,Redis也提供了⼿动调整槽位的指令。可以使⽤cluster help查看相关调整指令。

图片.png

问题2、如何确定key与slot的对应关系?

Redis集群中,对于每⼀个要写⼊的key,都会寻找所属的槽位。计算的⽅式是 CRC16(key) mod16384。

⾸先,这意味着在集群当中,那些批量操作的复合指令(如mset,mhset)⽀持会不太好。如果他们分属不同的槽位,就⽆法保证他们能够在⼀个服务上进⾏原⼦性操作。

图片.png 在⼤型Redis集群中,经常会出现数据倾斜的问题。也就是⼤量的数据被集中存储到了集群中某⼀个热点Redis节点上。从⽽造成这⼀个节点的负载明显⼤于其他节点。这种数据倾斜问题就容易造成集群的资源浪费。

调整数据倾斜的问题,常⻅的思路就是分两步。第⼀步,调整key的结构,尤其是那些访问频繁的热点key,让数据能够尽量平均的分配到各个slot上。第⼆步,调整slot的分布,将那些数据量多,访问频繁的热点slot进⾏重新调配,让他们尽量平均的分配到不同的Redis节点上。

Redis集群选举原理-了解

1、gossip协议

Redis集群之间通过gossip协议进⾏频繁的通信,⽤于传递消息和更新节点状态。

主要作⽤有:

  • 节点间发送⼼跳和确认其他节点的存在。
  • 通知其他节点新节点的加⼊或已经下线的节点。
  • 通过反馈机制更新节点的状态,如权重、过期时间等

gossip协议包含多种消息,包括ping,pong,meet,fail等等。

  • meet:某个节点发送meet给新加⼊的节点,让新节点加⼊集群中,然后新节点就会开始与其他节点进⾏通信;
  • ping:每个节点都会频繁给其他节点发送ping,其中包含⾃⼰的状态还有⾃⼰维护的集群元数据,互相通过 ping交换元数据(类似⾃⼰感知到的集群节点增加和移除,hash slot信息等);
  • pong: 对ping和meet消息的返回,包含⾃⼰的状态和其他信息,也可以⽤于信息⼴播和更新;
  • fail: 某个节点判断另⼀个节点fail之后,就发送fail给其他节点,通知其他节点,指定的节点宕机了。

gossip集群是去中心化的,各个节点彼此之间通过gossip协议互相通信,保证集群内部各个节点最终能够达成统一。gossip协议更新元数据并不是同时在集群内部同步,⽽是陆陆续续请求到所有节点上。因此gossip协议的数据统⼀是有⼀定的延迟的。

gossip协议最⼤的好处在于,即使集群节点的数量增加,每个节点的负载也不会增加很多,⼏乎是恒定的。因此在Redis集群中,哪怕构建⾮常多的节点,也不会对服务性能造成很⼤的影响。但是gossip协议的数据同步是有延迟的,如果集群节点太多,数据同步的延迟时间也会增加。这对于Redis是不合适的。因此,通常不建议构建太⼤的Redis集群。

需要注意下的是,Redis集群中,每个节点都有⼀个专⻔⽤于节点之间进⾏gossip通信的端⼝,就是⾃⼰提供服务的端⼝+10000.因此,在部署Redis集群时,要注意防⽕墙配置,不要把这个端⼝屏蔽了。

2、Redis集群选举流程

当slave发现⾃⼰的master变为FAIL状态时,便尝试进⾏Failover,以期成为新的master。由于挂掉的master 可能会有多个slave,从⽽存在多个slave竞争成为master节点的过程, 其过程如下:

1》slave发现⾃⼰的master变为FAIL

2》将⾃⼰记录的集群currentEpoch加1,并⼴播FAILOVER_AUTH_REQUEST信息(currentEpoch可以理解为选举周期,通过cluster info指令可以看到)

3》其他节点收到该信息,只有master响应,判断请求者的合法性,并发送FAILOVER_AUTH_ACK,对每⼀个 epoch只发送⼀次ack

4》尝试failover的slave收集master返回的FAILOVER_AUTH_ACK

5》slave收到超过半数master的ack后变成新Master(这⾥解释了集群为什么⾄少需要三个主节点,如果只有两 个,当其中⼀个挂了,只剩⼀个主节点是不能选举成功的)

6》slave⼴播Pong消息通知其他集群节点从节点并不是在主节点⼀进⼊ FAIL 状态就⻢上尝试发起选举,⽽是有⼀定延迟,⼀定的延迟确保我们等待 FAIL状态在集群中传播,slave如果⽴即尝试选举,其它masters或许尚未意识到FAIL状态,可能会拒绝投票迟计算公式: DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms SLAVE_RANK表示此slave已经从master复制数据的总量的rank。Rank越⼩代表已复制的数据越新。这种⽅ 式下,持有最新数据的slave将会⾸先发起选举(理论上)。

Redis集群能不能保证数据安全?

⾸先,在Redis集群相对⽐较稳定的时候,Redis集群是能够保证数据安全的。 因为Redis集群中每个master都是可以配置slave从节点的。这些slave节点会即时备份master的数据。在master宕机时,slave会自动切换成master。继续提供服务。

在Redis的配置⽂件中,有两个参数⽤来保证每个master必须有健康的slave进⾏备份。

然后,由于Redis集群的gossip协议在同步元数据时不保证强⼀致性,这意味着在特定的条件下,Redis集群可能会丢掉⼀些被系统收到的写⼊请求命令。

这些特定条件通常都⽐较苛刻,概率⽐较⼩。⽐如⽹络抖动产⽣的脑裂问题。

在企业中,有良好运维支持,通常可以认为Redis集群的数据是安全的。

Redis数据安全性⽅案总结

对于任何数据存储系统来说,数据安全都是重中之重。Redis也不例外。从数据安全性的⻆度来梳理Redis从单机到集群的各种部署架构,可以看到⽤Redis保存数据基本上还是⾮常靠谱的。甚⾄Redis的数据保存策略,在很多场景下,都是⼀种教科书级别的解决⽅案。另外,之前介绍过,Redis现在推出了企业版本。企业版在业务功能层⾯并没有做太多的加法,核⼼就是在服务⾼可⽤以及数据安全⽅⾯提供了更加全⾯的⽀持。有兴趣的朋友可以⾃⾏去了解补充。

但是,基于内存和硬盘的成本对⽐,Redis通常还是不建议作为独⽴的数据库使⽤。⼤部分情况下,还是发挥Redis⾼性能的优势,作为⼀个数据缓存来使⽤。其实,如果有⾮常靠谱的运维⽀撑,Redis作为数据库来使⽤完全是可以的。⽐如,Redis现在提供了基于云服务器的RedisCloud服务。其中就可以购买作为数据库使用的Redis实例。