方式1:直接清理Redis缓存,重新查询数据库即可~!(这样做治标不治本)
方式2:我们的MySQL和Redis实现数据同步不可能是强一致性(在分布式系统当中不可能有强一致性),我们只有通过一些最终一致性的解决方案,就是短暂数据延迟、不一致是允许的,但是最终数据一定要保持一致,直接使用MQ异步订阅MySQL的bin log日志文件(insert/delete/update),然后增量的同步到Redis中(实现增量同步) => 最终一致性的方案。
方式3:使用Alibaba的canal框架:它的底层就是采用MQ订阅bin log,可以简单的把canal理解为就是一个用来同步增量数据的一个工具。
提到分布式架构就一定绕不开 "一致性" 问题,而"一致性"其实又包含了数据一致性和事务一致性两种情况,本文主要讨论数据一致性(事务一致性指ACID)。
复制是导致出现数据一致性问题的唯一原因。
如果只用一台数据库来处理所有的写入和读取请求,就一定不存在数据一致性的问题,但是在中大型项目中,我们却经常需要将一份数据存储在超过一台数据库中(即复制),原因有三:
- 即使一部分数据库出现故障,系统也能正常工作(高可用)
- 使数据与用户在地理上接近(降低延迟)
- 扩展可以处理读请求的机器数量(可扩展性,提高读取吞吐量)
其实只有两类数据一致性,强一致性与弱一致性。
强一致性也叫做线性一致性,除此以外,所有的其它一致性都是弱一致性的特殊情况。
强一致性、弱一致性和最终一致性是分布式系统中不同的一致性模型,用于描述系统重数据副本之间的一致性状态。
- 强一致性(Strong Consistency):在强一致性模型下,系统保证在任何时间节点都可以看到一个全局一致的数据副本,这意味无论客户端读取或写入数据,都会得到最新、最准确的结果,并且写操作完成后,所有的副本都会立即生效。
- 弱一致性(Weak Consistency):在弱一致性模型下,系统中的数据副本之间可以出现一段时间的不一致,这意味着在写操作后,不同的数据副本可能会有不同的数据状态,并且读取操作可能无法读到最新的写入结果,弱一致性模型允许一定的数据延迟和冲突,但要求最终达到一致状态。
- 最终一致性(Eventual Consistency):最终一致性模型是弱一致性模型的一种特例,在最终一致性模型下,随着时间的推移,系统中的数据副本会在经过一段时间后最终达到一致状态。最终一致性模型兼顾了性能和可用性,广泛应用于分布式系统中。
需要根据具体的场景和需求来选择合适的一致性模型,强一致性模型适用于对数据一致性要求非常高的场景,而弱一致性和最终一致性模型则适用于需要高性能和高可用的分布式系统。
Redis因为出现某种原因的情况下发生宕机之后,数据是不会丢失的,原理就是Redis当中的持久化机制~!
持久化就是把内存中的数据持久化到本地磁盘,防止服务器宕机所导致的内存数据丢失。
EHCAHE:属于一级缓存,是JVM内置缓存!
大部分的缓存框架都会有基本功能:淘汰策略、持久化机制(唯独Memcached很奇葩,Memcached就是一个单纯的缓存框架,它里面就没有持久化机制)...
多级缓存使用到了一个装饰设计模式:相当于我不影响我之前缓存本身的代码,但是我可以对我的缓存去做增强,因此多级缓存就是采用装饰模式去实现的~!
多级缓存可以采用装饰模式去重构~!
Redis当中的持久化机制:Redis当中提供了持久化机制,它会把内存当中的数据备份在磁盘当中!磁盘当中的文件当你出现断电、宕机之后,在你重启Redis时,它会把磁盘当中的文件再加载到内存当中,从而保证你的数据可以不丢失!
持久化机制可以保证即使Redis进程在写入数据时崩溃,数据也不会丢失~!
Redis提供了两种持久化机制:RDB(默认)和 AOF机制。
Redis的持久化机制有两种方案:RDB(默认)和AOF!
Redis默认采用RDB方式来实现数据的持久化!
全量同步和增量同步都是分布式系统中常用的数据同步的方法。
全量同步
- 全量同步(Full Synchronization):定时同步,就是每天定时(避开高峰期)或者是采用一种周期的实现将数据拷贝到另外一个地方,比如900s以内,如果对我们的Redis做了10次写的操作,那么就将所有数据持久化的写入到硬盘当中,或者是从源节点将所有数据都发送传输到目标节点,以确保目标节点和源节点上的数据完全一致。
- 全量同步通常用于备份、重构或初始化整个分布式系统的场景。
- 在进行全量同步时,会将整个数据库当中的数据复制到目标位置,无论是否已经存在相同的数据记录,所以由于全量同步需要传输所有的数据,因此如果在数据量比较大的情况下,会耗时较长,占用大量的网络带宽和系统资源,虽然全量同步频率不是很大,但是可能会造成数据的丢失。
增量同步
- 增量同步(Incremental Synchronization):采用对行为进行记录的操作来实现数据的同步,也就是源节点和目标节点之间只传输发生变化的数据,从而来确保目标节点和源节点之间的数据保持同步。
- 由于增量同步是基于之前的同步状态和标记,只将变更部分,也就是只有变化的数据才会被记录传输到目标位置,已经存在的数据记录不会被重复复制,因此增量同步的开销相对较小,但是增量同步的过程比较频繁,频率会非常高,频率如果非常高,对我们的Redis整个服务器同步的压力也是比较大的,但是能够保证数据不丢失。
全量同步与增量同步的比较:
- 增量同步会比全量同步更加消耗服务器的内存,但是能够更加的保证数据的同步。
在Redis中,主从复制就是一个典型的增量同步的场景,Redis的主节点可以持久化数据到磁盘,并通过将数据变化的命令的发送给从节点来实现增量同步,从节点接受到命令之后,按照发送顺序依次执行以保证数据的一致性。
- RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照,是Redis默认的持久化方式。
- RDB采用定时持久化机制,所以RDB采用全量同步的持久化方案,按照一定的时间将内存中的数据以快照的形式保存到硬盘中,对应产生的数据文件为dump,rdb,但是服务器因为某种原因宕机后可能数据会丢失。
- 简单来说就是把/将Redis内存当中的所有数据以二进制、快照的形式都记录/保存到磁盘当中,当Redis实例发生故障重启后,此时会从磁盘读取快照文件并加载到内存当中,从而来恢复数据。
- Disk:磁盘 DB loaded from disk
- RDB备份文件:dump.rdb => 二进制文件,保存的都是二进制格式的数据
- 快照文件称为RDB文件,保存了最后一次生成快照时Redis当中的所有数据,默认是保存在当前运行目录!
- Redis已经帮助我们默认开启了RDB存储~!
RDB持久化在四种情况下会执行:被动操作(一二三) + 主动操作(四)
4. 触发RDB条件时:在Redis内部有触发RDB的机制,可以在redis.conf文件中找到,格式如下:
通过配置文件中的save参数来定义快照的周期 - Redis服务器dump-备份快照的频率:
# 900秒内,如果至少有1个key被修改,则执行bgsave命令来指定RDB备份操作 如果是save "" 则表示禁用RDB
save 900 1 如果900s(15分钟)内有一个Key发生变化被修改,就触发一次RDB
save 300 10 如果300s(5分钟)内有十个Key发生变化,就触发一次RDB
save 60 10000 如果60s(1分钟)内有一万个Key发生变化(代表60s内至少执行10000次修改责编触发RDB),就触发一次RDB
RDB的其它配置也可以在redis,conf文件中设置:
# 是否对RDB备份文件做压缩处理,降低RDB文件的体积
# 建议不开启,压缩也会消耗cpu,影响Redis的性能磁盘的话不值钱
rdbcompression yes
# RDB文件名称
dbfilename dump.rdb
# RDB文件保存的路径目录 ./表示当前目录
dir ./
优点:
- 只有一个文件dump.rdb,方便持久化;
- 性能最大化,fork子进程来进行持久化写操作,让主进程继续处理命令
- 相当于数据集大时,比AOF的启动效率更高
缺点:
- 如果发生断电,则RDB会存在丢失数据的风险:因为RDB是间隔一段时间进行持久化,假设上一次触发了RDB,但下一次还没来得及触发突然发生断电了,两次RDB之间写入数据就会有数据丢失的风险;
- RDB它是将内存当中的数据以及快照直接保存在磁盘当中, 写RDB文件比较耗时,耗费性能~!前提是你的内存当中存储的数据量比较大!
容灾性是指系统在面对硬件故障、软件错误或其他不可预测的异常情况时,仍能保持部分或全部功能可用的能力。
RDB全量同步用的比较少,一般都会用AOF增量同步~!
AOF是基于数据日志操作实现的持久化,所以AOF采用增量同步的持久化方案~!
AOF默认是关闭的,需要修改redis.windows.conf配置文件来开启AOF:
# 是否开启AOF持久化功能,默认是no,是关闭的,如果需要开启AOF持久化,则需要将no改为yes
appendonly yes
# AOF文件的名称
appendfilename "appendonly.aof"
AOF的命令记录的频率也可以通过redis.windows.conf文件来配:AOF的三种同步策略
# 表示每执行一次写命令,就立即记录到AOF文件(写一次,保存一次),能够实时的保证数据的安全性,保证数据不丢失,但是效率非常低
appendfsync always
# sec是second-秒的简写,写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案,该方案是AOF的缺省策略。
appendfsync everysec
# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no
建议使用everysec,既能够保证数据的同步,效率也还可以,但是它也有缺点:最多丢失1秒内的数据,但是效率非常高~!
优点:
- 数据安全,AOF持久化可以配置appendfsync属性,有always,每进行一些写命令操作就记录到aof文件中一次;
- 通过append模式写文件,即使中途服务器宕机,可以通过redis-check-aof工具解决数据一致性问题。
缺点:
- AOF文件比RDB文件大,且恢复速度慢
- 数据集大的时候,比rdb启动效率低
# AOF文件比上次文件 增长超过多少百分比则触发重写
auto-aof-rewrite-percentage 100
# AOF文件体积最小多大以上才触发重写
auto-aof-rewrite-min-size 64mb
需要注意的是:AOF文件重写是一个耗时且消耗CPU资源的操作,可能会对Redis服务器产生负载,因此在生成环境中需要谨慎使用。
维度 | RDB | AOF |
---|---|---|
持久化方式 | 定时对整个内存做快照 | 记录每一次执行的写命令 |
数据完整性 | 不完整,两次备份之间会丢失 | 相对完整,取决于刷盘策略 |
文件大小 | 会有压缩,文件体积小 | 记录命令,文件体积很大 |
宕机恢复速度 | 很快 | 慢 |
数据恢复优先级 | 低,因为数据完整性不如aof | 高,因为数据完整性更高 |
系统资源占用 | 高,大量cpu和内存消耗 | 低,主要是磁盘io资源,但aof重写时会占用大量cpu和内存资源 |
使用场景 | 可以容忍数分钟的数据丢失,追求更快的启动速度 | 对数据安全性要求较高常见 |
RDB和AOF各有自己的优缺点,可以选择同时启用RDB和AOF持久化,这样在Redis重启时可以使用RDB文件加载数据,通过重放AOF文件中的命令来实现数据的完整性和一致性~!