leveldb 使用场景

  最近有个业务写远远大于读,读也集中在最近写入,这不很适合采用leveldb存储么。

  ssdb 是leveldb的redis兼容协议封装,并且实现了主从同步,源码不多易读;主要对redis命令封装,get/set 不说,leveldb 是有序的,相比redis通过scan遍历的命令,利用有序性 list、hset也通过key+fileld/seq - val 方式存储,ttl 会单独存储一个hset 保存过期时间,由一个单独线程定时轮询删除。

测试场景

机器:两台R720XD E5-2620 2.1G (6核12线程)*2/内存128GB/300GB机械硬盘

数据: key: key 10位顺序数字 value: 50字节

并发: 默认情况100连接并发

客户端: 使用erlang erdis模块get/set

配置:

leveldb:

cache_size: 500

block_size: 1

write_buffer_size: 64

compression: no

max_open_files: 1000

数据量:2kw

- 文件大小:1.3GB

- 写速度:7w/s  CPU 250%  mem:30M

- 随机读: 5.5w/s  CPU  100%  mem:1GB

- 并发读写1:10: 读 5k/s 写:5w/s,CPU 250%

总结:总体性能和github相近,leveldb数据存放十分紧凑,几乎没有额外磁盘消耗,即使全量缓存到内存,内存消耗也会比redis 少很多

数据量:1.5亿

- 文件大小:9.6GB

- 写速度:7w/s  CPU 250%  mem:70M

- 随机读:  1.6w/s cpu:100% mem:70M

-并发读写:1: 10: 4k/s 读  5w/s 写 250%

总结:读太随机的LRU cache 无法生效,请求都要操作文件系统,性能下降;写保持不变

数据量:10亿

- 文件大小:66GB

- 写速度:7w/s 250% mem:80M

- 随机读:  1.6w/s cpu:180% mem:80M

-并发读写:1: 10: 4k/s 读  5w/s 写 280%

总结:和1.5亿级别效果保持一致

page cache

leveldb默认缓存meta data、和8M的block;本次测试使用了500M block_cache,从测试效果看,因为随机读,cache只在2k数据级别上起到作用,且带来很高性能提升。

1.5亿、10亿时,完全依赖kernel 对文件系统的page cache,机器有128GB内存,leveldb 没有使用direct io,文件都缓存,实际运行中不会有磁盘IO。

那么使用脚本清理:

while true;  do echo 1 > /proc/sys/vm/drop_caches;echo clean cache ok; sleep 1; done

- 随机读 约160/s  cpu: 5%  mem: 120m  iostat 95%util

- 1并发随机读,100并发写:90/s 读, 1500/s 写,随机读取影响写入速度

总结:

随机IO在机械硬盘上是完全无解了,只能靠cache扛,相比page cache,block_cache 更有效,应该更加需求增加bock_cache。

相比增加内存,使用ssd硬盘成本更低。

读取系统调用:

open("./var/data/006090.ldb", O_RDONLY) = 27

stat("./var/data/006090.ldb", {st_mode=S_IFREG|0644, st_size=34349641, ...}) = 0

mmap(NULL, 34349641, PROT_READ, MAP_SHARED, 27, 0) = 0x7f0334f76000

madvise(0x7f040457e000, 737280, MADV_DONTNEED) = 0

munmap(0x7f03dc2ab000, 34349599)        = 0

close(27)                               = 0

多线程

ssdb 是多线程的,但上面测试效果看有明显多核利用率很低问题,从源码看可以知道:

- 1个主线程,负责网络io

- 10个读线程,负责像scan复杂操作读

- 1个写线程,负责写操作磁盘io

- 1个leveldb 的compact线程

也就是写set 一个主线程负责网络,一个写线程负责leveldb操作;而读get 只有主线程在工作。

ssdb相关都没有配置,简单修改源码重新编译:

- 10个线程处理读:2.5/s  CPU 450%

60%消耗在sys,高并发读文件对内核瓶颈

- 减小至3个线程处理读:3.2w/s 280%

看起来比较合适的并发度

- 使用cahce 在1kw区间随机读  7w/s ,200%CPU

最佳实战

1. 写性能

测试中,写入速度一直维持7w/s, 可满足到多需求, leveldb 写入可以到40w/s, 这里受限于ssdb 线程模型无法利用更多的核心。需要的话通过pipline、网卡中断平衡、提高网络、leveldb写线程数 来提高写入性能。

2. 读性能

一般业务都存在数据热点,可调整cache_size, block_size 提高缓存命中率,block_size 为缓存块大小1K~4M视具体业务value而定。

如果业务热点度不高,那只能上ssd硬盘了。

注意使用了page cache,不小心清空会让性能急剧下降,还是尽量配置足够大的cache_size。还有就是启动有个预热过程。

3. compaction

本次使用的顺序key写入,因为业务上key 都是顺序的,然后一段时间从后往前顺序删除。compaction影响会很小,如果业务大量随机key写入、修改、删除会增加compaction量,需要注意。

时间: 2024-10-05 06:49:35

leveldb 使用场景的相关文章

(转)NoSQL系列:选择合适的数据库

内容目录: 为什么使用NoSQL数据库? 键值数据库 文档数据库 列族数据库 图数据库 附思维导图 参考 NoSQL系列:选择合适的数据库 为什么使用NoSQL数据库? 阻抗失衡 关系模型和内存中的数据结构不匹配 采用更为方便的数据交互方式提升开发效率 待处理的数据量很大 数据量超过关系型数据库的承载能力 大集群的出现 在成本方面,集群中应用关系数据库,许可费用是一笔很大的支出: 横向扩展和纵向扩展:关系数据库一般只能是纵向扩展,通过对单机服务器的性能换代增强而实现:而对于扩展到多个服务器, D

LevelDB场景分析1--整体结构分析

基本用法 数据结构 class DBImpl : public DB { private: struct CompactionState; struct Writer;// Information kept for every waiting writer Env* const env_; // 文件,目录,日志,Schedule线程 const InternalKeyComparator internal_comparator_; const InternalFilterPolicy inte

LevelDB场景分析2--Open

1.源码 1 Status DB::Open(const Options& options, const std::string& dbname, 2                 DB** dbptr) { 3   *dbptr = NULL; 4  5   DBImpl* impl = new DBImpl(options, dbname); 6   impl->mutex_.Lock(); 7   VersionEdit edit; 8   Status s = impl-&

LevelDB场景分析4--BackgroundCompaction

DBImpl::Open 1 Status DB::Open(const Options& options, const std::string& dbname, 2                 DB** dbptr) { 3   *dbptr = NULL; 4  5   DBImpl* impl = new DBImpl(options, dbname); 6   impl->mutex_.Lock(); 7   VersionEdit edit; 8   Status s 

LevelDB Cache实现机制分析

几天前淘宝量子恒道在博客上分析了HBase的Cache机制,本篇文章,结合LevelDB 1.7.0版本的源码,分析下LevelDB的Cache机制. 概述 LevelDB是Google开源的持久化KV单机存储引擎,据称是HBase的鼻祖Bigtable的重要组件tablet的开源实现.针对存储面对的普遍随机IO问题,LevelDB采用merge-dump的方式,将逻辑场景的随机写请求转换成顺序写log和写memtable的操作,由后台线程根据策略将memtable持久化成分层的sstable.

levelDB数据库使用及实例 - 高性能nosql存储数据库

LevelDB是google公司开发出来的一款 超高性能kv存储引擎,以其惊人的读性能和更加惊人的写性能在轻量级nosql数据库中鹤立鸡群. 此开源项目目前是支持处理十亿级别规模Key-Value型数据持久性存储的C++ 程序库.在优秀的表现下对于内存的占用也非常小,他的大量数据都直接存储在磁盘上.可以理解为以空间换取时间. 任何东西都不是十全十美的,LevelDB也有它的局限性: LevelDB 只是一个 C/C++ 编程语言的库, 不包含网络服务封装, 所以无法像一般意义的存储服务器(如 M

leveldb源码分析--Memtable

本节讲述内存中LevelDB的数据结构Memtable,Memtable义如其名即为内存中的KV Table,即LSM-Tree中的C0 Tree.我们知道在LSM-Tree中刚插入的的KV数据都是存储在内存中,当内存中存储的数据超过一定量以后再写到磁盘中.而对于leveldb来说这个过程演变为内存中的数据都是插入到MemTable中,当MemTable中的数据超过一定量(Options.write_buffer_size)以后MemTable就转化为Immutable Memtable等待du

[leveldb]0.源码编译及使用

一.LevelDB简介 LevelDB是Google开源的持久化KV单机数据库,具有很高的随机写,顺序读/写性能,但是随机读的性能很一般,也就是说,LevelDB很适合应用在查询较少,而写很多的场景.LevelDB应用了LSM (Log Structured Merge) 策略,lsm_tree对索引变更进行延迟及批量处理,并通过一种类似于归并排序的方式高效地将更新迁移到磁盘,降低索引插入开销,关于LSM,本文在后面也会简单提及. 根据Leveldb官方网站的描述,LevelDB的特点和限制如下

HBase、Redis、MongoDB、Couchbase、LevelDB主流 NoSQL 数据库的对比

HBase.Redis.MongoDB.Couchbase.LevelDB主流 NoSQL 数据库的对比 最近小组准备启动一个 node 开源项目,从前端亲和力.大数据下的IO性能.可扩展性几点入手挑选了 NoSql 数据库,但具体使用哪一款产品还需要做一次选型. 我们最终把选项范围缩窄在 HBase.Redis.MongoDB.Couchbase.LevelDB 五款较主流的数据库产品中,本文将主要对它们进行分析对比. 鉴于缺乏项目中的实战经验沉淀,本文内容和观点主要还是从各平台资料搜罗汇总,