在很多软件中都会有持久化策略,像 redis ,rabbitmq 等。
其过程大多都是把内存中数据保存到内存中一块缓存中,顺便记录一份日志,缓存定期或定量的被另一个持久化线程写入到磁盘,期间机器宕机,再根据日志文件恢复数据。
对于这个过程,我有点疑问,写日志时保存也是在磁盘对吧,那干嘛多此一举把数据先放到内存的缓存,再放到磁盘,直接像日志那样直接保存到磁盘不行吗?

日志是顺序写入,性能高

内存写入速度和磁盘写入速度不是一个数量级的

你这种不就是 persistent memory 吗?直接买硬件不就好了?何必在这里瞎想。

还有 redis 这种项目最初就是内存 kv 存储。一开始和持久化没有什么关系。不过确实日志这个方案,很早 binlog 就是如此。就是性能,没有什么好奇怪的。

听君一席话,如听一席话

我是做前端的

内存读写快,磁盘读写慢

因为日志是顺序 IO ,速度快,而内存中数据可能涉及到修改操作,不是顺序 IO ,慢很多,所以先用日志记录,再持久化是这个意思吗

不是很懂这方面的东西。我猜这和数据库的事务一样,每次持久化都要保证数据完整性。因为磁盘读写比较慢,为了不阻塞对原数据的修改,所以先在内存中拷贝一块,然后慢慢往磁盘里写。这样整块数据都有统一的时间戳,同时也不影响对原数据的写入操作。

我理解缓存是放那些最常访问的数据,也就是说可能本来就已经持久化了。

我感觉即使日志不是顺序写入的,效率应该也要比直接修改数据库高。因为写入日志仅仅就是往磁盘追加一行文字就行了,而为了向数据库插入数据,我们则可能要更改数据库的多个地方,同时为了保证一致性,可能还需要加锁,同步,这效率显然要比写一行日志低很多

随着磁盘写入速度的提升, 主要还是磁头移动占主要的耗时
内存写入磁盘更多的是随机写入, 需要多次寻道, 而顺序写入寻道比较少时间短, 这个应该是根因

另外有些时候磁盘顺序写入甚至比内存还快(因为内存碎片的原因)

Redis 企业方案本来就是直接上 redis on flash / rocketdb 这种解决的。说其它的都是废话。

当年 Redis 内种内存型 KV 存储说白了,就是牺牲底层数据可靠性和组织度来提升性能。想要持久化什么都是后来用的太宽,很多不适合的场景也使用 Redis 这种导致的。架构反过来去适配代码。

举什么顺序 IO 、机械硬盘原理来理解这个问题本来就是误读。

需要日志的原因其实是和数据库用 binlog 是一样的,功能上就是为了还原到特定时间点。

github.com/dreamhead/patterns-of-distributed-systems/blob/master/content/write-ahead-log.md

这个名词叫做 Write-Ahead Log

就算是业界的 Redis 改造方案,比如携程的 Redis on rocksdb ,貌似不需要 Log 了。但是底层的 Rocksdb 自己还是实现顺序日志来提升一致性条件下的写入性能。

分布式存储的奠基者是 Google 的 GFS ,这个顺序日志写入就是 GFS 开始的,直到目前很难看到有分布式存储系统不使用顺序日志的,反倒是什么还原到时间点只是额外功能而已,并不是核心需求。

wallog 早就有了好吧,跟 gfs 有啥关系

不谈 WAL 的话,或者键值。日志这种持久化方案,从持久化这个概念提出不久就有了。几乎所有的持久化方案都有日志的,磁盘文件系统也很早,至少八十年代末九十年代初就有了。如果是传统数据库,应该更早一点。
说特定时间点还原可能有点问题。讲究一点的说法,应该是为了实现部分或者全部的 ACID ,所以用了日志。反过来说的话,我不知道这个判断标准对不对。我看 ACID 的实现 ,就是看系统能不能还原到任意时间点的。

我语气可能有点不太好。

因为 OP 这个问题相当于在问一个内存引擎的键值服务和一个消息服务的数据为什么不直接落盘。我觉得唯一的回答只能是因为内存不是硬盘了。

是的

看了一下这些回复,基本一半是牛头不对马嘴的无效回复,楼主问既然日志也要写磁盘,那为啥不直接把数据持久化到磁盘,然后一群回答说内存比磁盘快

一个是记日志是顺序写,不用磁盘寻址。二是,这里算是一次批量操作,减少寻址时间,不用每次写磁盘都寻址一次。不过现在使用 SSD 的话,应该差别不是很大。不过这种思想肯定是没错,可以借鉴的。
这个其实就是很多项目都在用的一个"技术"-WAL ,例如 Prometheus 、MySQL 等。
可以参考这里: time.geekbang.org/column/article/68633 ,是关于 MySQL 中的 WAL 。

首先,并不是所有磁盘写入都比内存慢,磁盘顺序写的性能非常高,并且反直觉的比内存都快[1]。

关于 Redis 为什么要放到内存缓存,那是因为 Redis 本来就是内存操作呀,查、写操作都是在内存。如果直接写到日志后怎么查出来数据呢?

www.zhihu.com/question/48794778

因为日志是顺序写,数据是随机的