数据写入方式
1. update-in-place原地更新
2. append-only btree/copy on write tree顺序文件末尾追加
数据被按照特定方式放置,提升读性能,但写性能下降,对b+树和hash更新时需要随机读写:
1. 二分查找,将文件数据有序保存,使用二分查找来完成指定key的查找
2. 哈希,用哈希将数据分割为不同的bucket
3. B+树,减少外部文件的读取
4. 外部文件,将数据保存为日志,并创建一个hash或者查找树映射相应的文件
存储结构(磁盘因为寻道等因素,顺序读取比随机读取块N个数量级):
将整个磁盘就看做事一个日志,在日志中存放永久性数据及其索引,每次都添加到日志末尾;
通过将很多小文件的存储转换为连续的大批量传输,是的对于文件系统的大多数存取都是顺序性的,从而提高磁盘宽带利用率,故障恢复速度快。
简单来说分为一部分常驻内存,可以为任何方便键值查找的数据结构,另一个常驻硬盘,与B-Tree类似,这部分经常访问的节点也会被缓存在内存中
首先将日志文件写入插入操作日志。然后写入内存部分。当内存接近阈值则滚动合并到硬盘。
将数据添加到文件,因为完全顺序,所以写操作性能优秀,但从日志文件读一些数据将比写操作消耗更多的时间,需要倒序扫描,知道找到所需内容。
日志适用的场景:
- 数据是被整体访问,WAL(write-ahead-log)
- 知道明确的offset,kafka
Log-Structured Merge-Tree,LSM-tree
将之前使用的一个大的查找结构变换为将写操作顺序的保存到一些相似的有序文件(sstable)中。每个文件包含了短时间段内的一些改动,因为文件有序,后续查找也会很快。文件不可修改,永远不会更新,新操作只会写到新文件中,读写检查所有文件,通过周期性的合并来减少文件的个数。保持了日志文件的写性能,让操作顺序化,不断追加而不是修改,延迟更新,批量写入硬盘,适合于大量插入环境
写操作被分批处理,只写到顺序块上,周期性合并会影响IO,都操作有可能访问大量的文件(散乱的读)
- 更新操作-》内存缓存(memtable)中使用树结构来保持key有序-》WAL写磁盘防丢/恢复/-》达到一定规模刷到磁盘上一个新文件里,这里简单生成新文件没有编辑,所以是顺序写,速度快
越多的数据到存储系统中,就会有越多的不可修改的顺序sstable文件被创建,他们代表了小的,按时间顺序的修改,系统周期性发起compaction,合并文件删除重复冗余,减少文件个数,保证都操作的性能,因为sstable是有序结构,所以合并非常高效
- 读操作-》先检查内存数据(memtable)-》没有这个key-》逆序一个个检查sstable直到找到。
因为需要遍历所有sstable,当数量过多性能就会下降,一方面系统周期性合并sstable,用cache等技术,另一方面使用bloom来避免大量的读文件操作。
周期合并(按层/按文件大小):为了保证LSM读取速度,所以需要维护并减少sstable文件个数