08-leveldb性能优化(二)

在《02-leveldb入门》中,我们介绍了leveldb的参数,本节就主要讲如何通过调整leveldb的参数来进行性能优化。

levedb支持配置的参数如下:

const Comparator* comparator;比较函数,主要用于key的大小比较。如果传入NULL则使用默认字节序进行比较。
bool create_if_missing = false;如果数据库不存在,则创建。
bool error_if_exists = false;如果数据库存在,返回错误。
bool paranoid_checks = false;如果开启,则在读取数据时进行严格的检查,若发现数据损坏,则立即结束。
Env* env;用户定义环境,用于文件读写、后台线程等,默认Env::Default()。
Logger* info_log;日志对象指针,如果传入为空,则使用默认定义的日志对象。
size_t write_buffer_size = 4 * 1024 * 1024;写缓冲区的大小,对应于memtable的空间大小,会影响并发写入性能,原理部分会进行详细说明。
int max_open_files = 1000;最大打开文件数,也会关系到tablecache的大小.
Cache* block_cache = nullptr;data block缓存,如果为nullptr则数据块不进行缓存。
size_t block_size = 4 * 1024;数据块的大小,默认为4k,一般不需修改。
int block_restart_interval = 16;重启点的间隔,即每16个key进行前缀压缩。
size_t max_file_size = 2 * 1024 * 1024;文件最大大小,根据存储数据大小进行调整。
CompressionType compression = kSnappyCompression;是否对数进行压缩。
const FilterPolicy* filter_policy = nullptr;布隆过滤器,使用布隆过滤器有利于提高查询效率。

结合应用场景,通过调整上述参数来达到性能优化的目的:

01、数据校验paranoid_checks

在leveldb中,数据文件的每个block对应一个4字节的crc校验位。校验位的目的是在读取的时候对数据进行校验,检查其完整性,防止磁盘损坏等原因导致读取的块错误。crc校验的具体方法就是对block内的所有数据计算crc,并进行保存。读取的时候,同样对读出来的数据再次计算crc,比较与写入时候的crc是否一致。
当将paranoid_checks设置为true的时候,代表每次读取都需要对块进行crc校验,如果校验出错则及时抛出错误,不再进行后续的解析块的流程。如果开启了块校验,则会额外消耗CPU运算时间。但在大多数正常的环境下,读取出来的块都是符合校验的,因此也可以不开启校验。但面临的风险就是,万一有数据块损坏,而后续的解析又没有出错,导致读取出来的数据与原始写入的数据不一致。
在leveldb中,如果开启块校验,如果校验出错,则整个块被丢弃。但实际情况是,可能这个块只是损坏了某个数据的几个字节,对大部分数据其实是没有影响的。因此如果开启则会丢弃整个块的数据,而如果不开启校验,则直接进行块解析,对于这种情况,未损坏的数据还是可以解析出来,只会丢弃真正损坏的尽可能少的数据。
因此,paranoid_checks设置为false可以减少读取时的校验流程,从而提升读取性能。但是在数据完整性要求比较严格的情况下,建议开启这个参数。

02、写缓冲区大小write_buffer_size

write_buffer_size对应memtable和imm_memtable的大小。数据写入时会先写入memtable,因此如果write_buffer_size越大,就意味着写缓冲区越大。写缓冲区越大,就意味着写入性能会越高。但同时,如果进程重启,由于缓冲区中的数据丢失,需要从wal中进行恢复,缓冲区越大,意味着需要从wal日志中恢复的数据越多,从而导致启动时间变长。
因此,如果想提升性能,可以尝试将该参数调大。但也必须清楚,调大这个参数带来的影响是什么。

03、最大打开文件数max_open_files

max_open_files指的是leveldb可以打开的最大文件数量,这些打开的文件的meta信息(包括index block、filter block)会缓存起来。当下次需要查询到文件时,直接从缓存中进行快速的定位,以提升性能。如果文件未被缓存,则每次查询到该文件时,都需要重新打开文件,读取磁盘,性能显然是很低的。
因此,如果你的数据量非常大,且条件允许的情况下,可以将该值调大。当然,调大后相应占用的内存空间也会变大。

04、块缓存block_cache

leveldb读取数据是以块为单位的,如果查询某个数据时,在某个块中查询到了,则会将该块缓存在block cache中,以便于下次查询同样的数据可以快速在缓存中读取。这个就类似于缓存热点数据,将最近查询的数据缓存起来,以应对重复查询。
很明显,这个值设置的越大,对性能越有利。但也不尽如此,还是得根据业务场景来看。

05、块大小block_size

block是leveldb读写数据的基本单元,写入时当数据大小达到block_size时,会进行一次刷盘。读取数据时,也是一次读取block_size大小。
因此,这个值也需要根据实际应用场景来设置。如果你存储的key/value数据非常小,则该值可以相应减小。如果你的key/value数据比较大,却将block_size设置的很小则是不合理的,意味着查询一条数据可能需要读取多次磁盘。

06、文件大小max_file_size

max_file_size指的是单个sstable的最大大小。这个同样是和应用场景相关的,如果你的key/value数据很小,则该值也应该相应的调小;如果你的key/value非常大,也需要将该值调大。但是该值也会影响到读写的放大,如果单个文件很大,则在compact时候的读写放大也会加大。
这个具体调整多大,需结合原理、场景以及实际测试进行评估。

07、数据压缩compression

leveldb中支持将数据进行Snappy压缩,Snappy算法的优势是性能高,但压缩比并不一定是最优秀的。由于其性能高,因此比较适用于数据库的压缩。数据以block为单位进行压缩。
对于写磁盘来说,由于数据压缩,同样的数据量会占用更小的磁盘IO,同时也减少了磁盘空间的占用。对于查询来说,读取同样的数据需要更少的IO,但是读取后需要进行解压缩,才能得到最终的数据。这个是典型的用CPU时间换磁盘空间。
因此,对于数据量很大,对存储成本比较敏感的情况,建议开启压缩。而数据量较小,对存储成本不敏感的情况下,建议不采用压缩。

08、过滤器filter_policy

leveldb中提供了布隆过滤器。布隆过滤器用于快速识别一个块中不存在待查询数据的情况,以减少不必要的磁盘读取,提升查询效率。详细见《07-leveldb性能优化(一)》。

leveldb实现解析 淘宝-核心系统研发-存储 那岩 [email protected] 2011-12-13 目录 一、 代码目录结构 ....................................................................... 1 1. doc/ ............................................................................ 1 2. include/leveldb/ ................................................................. 1 3. db/ ............................................................................. 1 4. table/........................................................................... 1 5. port/ ........................................................................... 1 6. util/ ........................................................................... 1 7. helper/memenv/ ................................................................... 1 、 基本概念 .......................................................................... 1 1. Slice (include/leveldb/slice.h) .................................................. 1 2. Option (include/leveldb/option.h) .............................................. 2 3. Env (include/leveldb/env.h util/env_posix.h) .................................... 3 4. varint (util/coding.h) ........................................................... 3 5. ValueType (db/dbformat.h) ...................................................... 3 6. SequnceNnumber (db/dbformat.h) ................................................. 4 7. user key......................................................................... 4 8. ParsedInternalKey (db/dbformat.h) .............................................. 4 9. InternalKey (db/dbformat.h) ...................................................... 4 10. LookupKey (db/dbformat.h) ........................................................ 4 11. Comparator (include/leveldb/comparator.h util/comparator.cc) .................... 4 12. InternalKeyComparator (db/dbformat.h) ............................................ 5 13. WriteBatch (db/write_batch.cc) ................................................. 5 14. Memtable (db/memtable.cc db/skiplist.h) .......................................... 5 15. Sstable (table/table.cc) ......................................................... 5 16. FileMetaData (db/version_edit.h) ............................................... 5 17. block (table/block.cc) ........................................................... 6 18. BlockHandle(table/format.h) ...................................................... 6 19. FileNumber(db/dbformat.h) ...................................................... 6 20. filename (db/filename.cc) ........................................................ 6 21. level-n (db/version_set.h) ....................................................... 7 22. Compact (db/db_impl.cc db/version_set.cc) ........................................ 7 23. Compaction(db/version_set.cc) .................................................... 7 24. Version (db/version_set.cc) ...................................................... 8 25. VersionSet (db/version_set.cc) ................................................. 9 26. VersionEdit(db/version_edit.cc) ................................................. 10 27. VersionSet::Builder (db/version_set.cc) ......................................... 11 28. Manifest(descriptor)(db/version_set.cc)...................................... 12 29. TableBuilder/BlockBuilder(table/table_builder.cc table/block_builder.cc) ......... 12 30. Iterator (include/leveldb/iterator.h) ........................................... 12 三、 存储结构的格式定义与操作 .......................................................... 12 1. memtable (db/skiplist.h db/memtable) ............................................ 12 2. block of sstable (table/block_builder.cc table/block.cc) ......................... 14 3. sstable (table/table_bulder.cc/table.cc) ........................................ 16 4. block of log (db/log_format.h db/log_writer.cc db/log_reader.cc) .............. 18 5. log (db/log_format.h db/log_writer.cc db/log_reader.cc) ........................ 18 6. cache(util/cache.cc) .......................................................... 19 7. Snapshot (include/leveldb/snapshot.h) ......................................... 19 8. Iterator (include/leveldb/iterator.h) ........................................... 19 四、 主要流程 ......................................................................... 24 1. open ........................................................................... 24 2. put ............................................................................ 25 3. get ............................................................................ 25 4. delete.......................................................................... 26 5. snapshot........................................................................ 26 6. NewIterator ..................................................................... 26 7. compact......................................................................... 26 五、 总结 ............................................................................. 30 1. 设计/实现中的优化 ............................................................... 30 2. 可以做的优化 .................................................................... 31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值