计算机领域有很多思想被渗透在编程语言中与软件产品中
一、写入时复制(CopyOnWrite)
写入时复制是计算机程序设计领域中的一种优化策略。其核心思想是,如果有多个调用者(Callers)同时要求相同的资源(如内存或者是磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者视图修改资源内容时,系统才会真正复制一份专用副本(private copy)给该调用者,而其他调用者所见到的最初的资源仍然保持不变。这过程对其他的调用者都是透明的(transparently)。此做法主要的优点是如果调用者没有修改资源,就不会有副本(private copy)被创建,因此多个调用者只是读取操作时可以共享同一份资源。
CopyOnWriteArrayList :在写入数据时就是采用该思想,由于写入时复制,所以在读写并存的时候,他们操作的是不同的集合,也就是CopyOnWriteArrayList 只能保证数据的最终一致性,由于复制所以会占用更多内存,所以会增加GC次数。适用于读多写少的场景。
二、预写日志 (Write-Ahead Logging )
在计算机科学中,预写式日志是数据存储系统在持久化数据时,为提高系统的处理效率常采用的技术。对于非内存数据库而言,磁盘I/O操作是数据库效率的一大瓶颈。在相同的数据量下,采用WAL日志的数据库系统在事务提交时,磁盘写操作只有传统的回滚日志的一半左右,大大提高了数据库磁盘I/O操作的效率,从而提高了数据库的性能。
WAL机制的原理:修改并不直接写入到数据库文件中,而是写入到另外一个称为 WAL 的文件中;如果事务失败,WAL 中的记录会被忽略,撤销修改;如果事务成功,它将在随后的某个时间被写回到数据库文件中,提交修改。
WAL与checkpoint
使用 WAL 的数据库系统不会再每新增一条 WAL 日志就将其刷入数据库文件中,一般积累一定的量然后批量写入,通常使用「页」为单位,这是磁盘的写入单位。 同步 WAL 文件和数据库文件的行为被称为 checkpoint(检查点),一般在 WAL 文件积累到一定页数修改的时候;当然,有些系统也可以手动执行 checkpoint。执行 checkpoint 之后,WAL 文件可以被清空,这样可以保证 WAL 文件不会因为太大而性能下降。有些数据库系统读取请求也可以使用 WAL,通过读取 WAL 最新日志就可以获取到数据的最新状态。
- Mysql:关系数据库系统中用于提供原子性和持久性(ACID 属性中的两个)的一系列技术。mysql 通过 redo、undo 日志实现 WAL。redo log 称为重做日志,每当有操作时,在数据变更之前将操作写入 redo log,这样当发生掉电之类的情况时系统可以在重启后继续操作。undo log 称为撤销日志,当一些变更执行到一半无法完成时,可以根据撤销日志恢复到变更之间的状态。mysql 中用 redo log 来在系统 Crash 重启之类的情况时修复数据(事务的持久性),而 undo log 来保证事务的原子性。
- Hbase:hbase 的 RegionServer 会将数据保存在内存中(MemStore),直到满足一定条件,将其 flush 到磁盘上。这样可以避免创建很多小文件。内存存储是不稳定的,HBase 也是使用 WAL 来解决这个问题:每次更新操作都会写日志,并且写日志和更新操作在一个事务中。
- elasticsearch:elasticsearch使用translog来记录所有的操作,我们新增了一条记录时,es会把数据写到translog和in-memory buffer(内存缓存区)中,默认是每 30 分钟,执行flush 操作(Lucene 提交) 或者是在 translog 过大时(默认 512MB)。translog每5秒钟会同步到磁盘。