故障恢复
数据库运行过程中可能会发生故障,这个时候某些事务可能执行到一半但没有提交,当系统重启时,需要能够恢复到一致的状态,即要么提交这个事务,要么回滚。数据库系统以及其他的分布式存储系统统一采用操作日志,有时称为提交日志,即Commit Log技术来实现故障恢复。操作日志可分为回滚日志(UNDO Log)、重做日志(REDO Log)以及UNDO/REDO日志。如果记录事务修改钱的状态,则为回滚日志;相应地,如果记录事务修改后的状态,则为重做日志
操作日志
为了保证数据库的一致性,数据库操作需要持久化到磁盘,如果每次操作都随机更新磁盘的某个数据块,系统性能将会很差。通过操作日志顺序记录每个数据库操作并在内存中执行这些操作,内存中的数据定期刷新到磁盘,实现将随机写请求转化为顺序写请求
关系数据库系统一般采用UNDO/REDO日志。
重做日志
存储系统如果采用REDO日志,其它操作流程如下:
1. 将REDO日志以追加的方式写入磁盘的日志文件
2. 将RED日志的修改操作应用到内存中
3. 返回操作成功或失败
为什么需要先写操作日志在修改内存中的数据呢?假如先修改内存中的数据,那么用户就能立刻读到修改后的结果,一旦在完成内存修改与写入日志之间发生故障,那么最近的修改操作无法恢复。然而,之前的用户可能已经读取了修改后的结果,这就会产生不一致的情况
优化手段
成组提交
存储系统要求先将REDO日志刷入磁盘才可以更新内容中的数据,如果每个事务都要求将日志立即刷入磁盘,系统的吞吐量将会很差。因此,存储系统往往有一个是否立即刷如磁盘额选项,对于一致性要求很高的应用,可以设置为立即刷入;相应地,对于一致性要求不太高的应用,可以设置为不要求立即刷入,首先将REDO日志缓存到操作系统或者存储系统的内存缓存区中,定期刷入磁盘。这种做法有一个问题,如果存储系统意外故障,可能丢失最后一部分更新操作
成组提交(Group Commit)技术是一种有效的优化手段。REDO日志首先写入到存储系统的日志缓冲区中
1. 日志缓冲区中的数据量超过一定大小,比如512KB;
2. 距离上次刷入磁盘超过一定时间,比如10ms
当满足以上两个条件中的某一个时,将日志缓存区中的多个事务操作一次性刷入磁盘,接着一次性将多个事务的修改操作应用到内存中并逐个返回客户端操作结果。与定期刷入磁盘不同的是,成组提交技术保证REDO日志成功刷入磁盘后才返回写操作成功。这种做法可能会牺牲写事务的延时,但大大提高了系统的吞吐量
检查点
所有的数据保存在内存中,会出现两个问题:
1. 销量较低
2. 内存不足
将内存中的数据定期转储(Dump)到磁盘,这种技术称为checkpoint(检查点)技术。系统定期将内存中的操作以某种易于加载的形式(checkpoint文件)转储到磁盘中,并记录checkpoint时刻的日志回放点,以后故障恢复只需要回放checkpoint时刻的日志回放点之后的REDO日志
由于将内存数据转储到磁盘需要很长时间,而这段时间还可能有新的更新操作,checkpoint必须找到一个一致的状态。
Checkpoint流程如下:
1. 日志文件中记录“START CKPT”
2. 将内存中的数据以某种易于加载的组织方式转储到磁盘中,形成checkpoint文件。Checkpoint文件中往往记录“START CKPT”日志回放点,用于故障恢复。
3. 日志文件中记录“END CKPT”
Checkpoint文件中的数据一定不能包含“START CKPT”与“END CKPT”之间的非幂等操作(如:追加、加法操作)。为此两种处理方法:
1. checkpoint过程中停止写服务
2. 内存数据结构支持快照,执行checkpoint操作时首先对内存数据结构做一次快照,接着将快照中的数据转储到磁盘生成checkpoint文件,并记录此时对应的REDO日志回放点。生成checkpoint文件的过程运行写操作,但checkpoint文件中的快照数据不包含这些操作结果
数据压缩
数据压缩分为有损压缩与无损压缩两种,有损压缩算法压缩比率高,但数据可能失真,一般用于压缩图片、音频、视频;而无压缩算法能够完全还原原始数据
早期的数据压缩技术就是基于编码上的优化技术,其中以Huffman编码最为有名,它通过统计字符出现的频率计算最优前缀编码。此后顺序数据压缩的一种通有算法,LZ系列压缩算法几乎垄断了通用无损压缩领域。
设计压缩算法时不仅要考虑压缩比,还要考虑压缩算法的执行效率。
压缩算法的核心是找重复数据,列式存储技术通过把相同列的数据组织一起,不仅减少了大数据分析需要查询的数据量,还大大提高了数据的压缩比。传统的OLAP数据库,如HBase等分布式表格系统都实现了列式存储。
列式存储
传统的行式数据库将一个完整的数据行存储到数据页中。如果处理查询时需要用的大部分的数据列,这种方式在磁盘IO上是比较高效的。一般来说,OLTP(Online Transcation Processing 联机事务处理)应用适合采用这种方式
OLAP类型的查询可能需要访问几百万甚至几十亿个数据行,且该查询往往只关心少数几个数据列。
列式数据库是将同一个数据列的各个值存放在一起,插入某个数据行时,该行的各个数据列的值也会存放到不同的地方。列式数据库大大地提高了OLAP大数据量查询的效率。当然,列式数据库不是万能的,每次读取某个数据行时,需要分别从不同的地方读取各个数据列的值,然后合并在一起形成数据行。因此,如果再次查询涉及的数据量较小或者大部分查询都需要整行数据,列式数据库并不使用
很多列式数据库还支持列组,即将多个经常一起访问的数据列的各个值存放在一起。如果读取的数据列属于相同的列组,列式数据库可以从相同的地方一次性读取多个数据列的值,避免了多个数据列的合并。列组是一种行列混合存储模式,这种模式能够同时满足OLTP和OLAP的查询需求
转载请注明:学时网 » 大规模分布式存储系统原理与架构(三)