我们先来看这么一段面试场景——
面试官:你们项目缓存技术用到了什么缓存技术?
小帅:Redis
面试官:那么问一下,Redis缓存技术用到的持久化机制是哪一种机制?
小帅:AOF
面试官:好吧,回去等通知吧……
这个问题,不知道你在面试的时候有没有被别人问过,你是怎么回答的?
其实不管你怎么回答都是错的,为什么?请往下看。
大家都知道,Redis是我们互联网公司必用的架构技术,在我们业内称之为高性能缓存数据库,那么既然是缓存,我们的系统、服务器一断电或重启的时候,它的数据一定会丢失,所以,在丢失的这个过程中,在丢失之前,Redis做了一套持久化机制。
我们往Redis插数据的时候,这个数据会同步一份保存到磁盘,而保存到磁盘有两种方式,对应两种数据文件格式:AOF和RDB这两种文件,在Redis从断电到开机的瞬间都可以让我们的数据从磁盘恢复到Redis。那么问题来了,小帅要回答面试官讲的这个问题,其实是要搞明白AOF和RDB两者的区别。比如说现在的时间是下午14:00,Redis做了一次快照的备份,把这个数据备份到了RDB,那么这个RDB文件的数据就只停留在下午两点,下午两点以后的数据RDB是没有的,因为它相当于一个冷备,备份的时间只停留在下午两点钟这个时刻的快照。所以,你如果回答的是RDB,它的数据一定会有丢失。除了RDB,第二个方式就是刚才小帅回答的AOF,那AOF有什么问题呢?当我们往Redis里不断插入数据,它会以日志的方式追加(Append)到AOF文件里,也就是说AOF里面记录了很多这种原始的操作语句,比如说set、hset等等,当我们使用AOF恢复数据到Redis的时候,它会重新执行一遍我们之前操作的所有操作语句。以上三条语句都追加到了AOF文件里,很明显,此刻如果我们执行get name,Redis返回的是“佛波勒”,那么问题来了,AOF存了这么多过程化的数据,或者说是中间数据,它的意义在哪里?因为最终Redis恢复的时候最终的数据是“佛波勒”,哪怕Redis把前两条数据恢复了,在最后name被恢复的时候,也会被“佛波勒”覆盖,所以前两条数据是不可取的,浪费了我们的空间,那样咱们的AOF文件会越变越大。所以Redis是怎么做的呢,AOF里还有个技术叫Rewrite压缩重写,当我们的AOF文件不断变大的时候,比如我们设置的阀值是64M,当AOF文件第一次到达64M的时候,Redis会自动触发一次Rewrite操作,将AOF文件进行一次瘦身。在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。- 整个Redis数据库将只包含一个文件 dump.rdb,方便持久化
- 性能最大化,fork子进程来完成写操作,让主进程继续处理命令,所以是IO最大化,使用单独的子进程来进行持久化,主进程不会进行任何IO操作,保证了Redis的高性能
- 数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间redis 发生故障,会发生数据丢失,所以这种方式更适合用于数据要求不严谨的场景
- 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟
以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。- 数据安全,Redis中提供了3种同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失,而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中
- 通过append模式写文件,即使中途服务器宕机也不会破坏已经存在的内容,可以通过redis-check-aof工具解决数据一致性问题
- AOF机制的rewrite模式。定期对AOF文件进行重写,以达到压缩的目的
AOF文件比RDB更新频率高,优先使用AOF还原数据。说到底,面试官是在考察你对Redis的持久化机制的掌握程度,只要你了解了RDB与AOF的作用与优缺点,如何组织语言应对面试就再容易不过了。从架构演进的角度看,为了降低单个系统的复杂度,我们引入了分布式系统架构,这样一来,单个系统的复杂度就转移到了系统外部——各种中间件,Redis就是其中一个。技术/业务复杂度不会凭空产生,也不会凭空消失,只会从一个地方转移到另一个地方(就像物理学的能量守恒定律一样),我们称之为复杂度转移。
有道无术,术可成;有术无道,止于术
欢迎大家关注Java之道公众号
好文章,我在看❤️