Redis

Redis 之持久化

持久化的意义在于缓存中的数据对于业务是否必要,如果数据损失是否可以通过其他数据存储方式恢复。如果需要通过 Redis 自己来恢复,这就是 Redis 持久化的意义。持久化的两种方式:快照日志

快照(RDB)

将缓存数据序列化成二进制放到磁盘中,开机时或者恢复时从磁盘中读取二进制数据反序列化即可。利用快照数据恢复时间快,但是快照的生成间隔较大时,可能丢失很多数据。

日志(AOF)

将 Redis 操作指令追加到日志文件中,数据恢复时要重新执行命令,恢复时间长。日志的级别:

每操作:没操作一次 Redis,就将操作日志刷新到日志文件中,这样做就可以报最高程度的保证操作日志的完整性,最多是写当前日志时故障,最多丢失一条操作日志。

每秒钟:将操作日志先写到系统缓冲池中,每秒钟在写到磁盘上。这种情况下最多损失一秒内一个缓冲池的日志数据。(当缓冲池满了之后系统也会自己写到磁盘上)。默认级别。

缓冲池大小:当日志缓冲池满了之后操作系统将数据写到磁盘中,这种情况下也是最多损失一个缓冲池大小数据,但是由于少了每秒钟限制,将损失扩大了。

使用

早期 Redis 版本中,默认使用 RDB 做持久化,可以自己开启 AOF,但是开启 AOF 后,RDB 就失效了。优化后将两种方式混合使用,在 AOF 文件当中包含历史的 RDB,然后从当前时间再开始追加日志。这样在恢复时就是 RDB 加少量操作日志,可以快速恢复又最大保证了数据的完整性。这些配置可以在 Redis 启动的配置文件中开启。还可以在客户端使用 BGREWRITEAOF 指令重写日志文件,将日志文件压缩,消除重复的无用指令只保留最后的有效指令,例如:对同一个 key 的重复写或者读操作,只保留最后一条日志即可。如果使用了混合方式,使用该指令时就会在日志文件中生成快照,记录当前缓存的二进制数据。

Redis 的可用性

单点故障

如果是单机器,机器故障后业务就要瘫痪,利用主从或者主备模式来解决。主从复制两种模式比较:

强一致性

主机接收到指令后先执行操作然后通知从机执行,从机执行成功后会送主机,主机通知客户端成功。这种情况下如果主从之间的通信错误导致执行失败。对于客户端导致服务不可用,这种情况下主机是可用的只是从机的同步出现错误。这种强一致性会破坏可用性。

弱一致性

主机操作指令成功后返回给客户端同时异步通知从机。这种情况下就有可能会导致从机指令丢失,丢失数据。Redis 的主从复制默认运行在这种模式下。

压力、扩展性

单实例机器无法达到业务性能需求,需要扩展,利用分片集群模式来扩展服务能力。进行业务拆分,利用 AKF 划分原则,通过主备保证数据恢复,将数据按照业务分开降低数据在机器上的耦合(业务上对于热点数据和冷数据的处理和性能要求可能也是不同的),同类数据分片存储提高热点数据访问对于服务器的性能要求。

分片

一般情况下为了避免这两种情况,首先会搭建一个 Redis 的分片集群,然后集群中的 Redis 实例以主从形式搭建。如果是分片集群,客户端在命令发送时就需要有一个算法来讲不同的命令分配到不同的分片上。分片算法的三种实现:

客户端实现

客户端维护分片集群的实例,通过自定义算法(取模等)将指令分配到不同的分片上。这种方式耦合度太高,如果集群分片增加,算法也需要修改。

代理

客户端链接代理,将数据发送到代理,代理将数据发送到分片集群,分配算法由代理层实现,实现了解藕。但是分片集群更新时,代理层还是需要优化。

一致性哈希

抽象出一个 m 区间的哈希环,然后利用已有的机器节点将这个环分割,机器负载落在某个分割环的一个区间,不再是直接对应到机器上。这样当某个机器故障后,只需要将这一部分数据迁移到他的临近机器上,不需要全部数据迁移。参考文章:一致性哈希

Redis 锁