hash存储引擎-应用困境
哈希引擎的应用困境
经过了这段时间对哈希引擎的深入研究,以及与前任核心开发人员的交流(已活水转组),我越来越深刻的理解哈希引擎的应用场景。
简而言之:应用面狭隘,优势不明显。
集中在这几个方面
- 性能
- 成本
如何理解哈希引擎的成本?假如用一种最普遍的哈希引擎架构而言,其索引完全放内存,假如全key都要放索引中,那内存是存储容量的瓶颈,即使学习aerospike将哈希值放索引,依然最少是64byte一个key,内存依旧是瓶颈。
大内存意味着高成本,以aerospike为例,10亿个key,单副本内存需要60G。
那何种情况下哈希引擎的成本是可以接受的呢?
- 大value
- 可混部ssd存储应用
可混部不多解释,即将多的ssd部份给其他存储引擎使用,用来充分利用单机。
大value是我们重点讨论的问题,假如是小value,比如几十byte(对于redis转kv其实非常常见),那么key和value几乎一样大,ssd中要存key和value两个值,但ssd可以block压缩。导致一个现象:即内存和ssd占用几乎没差别。
这就导致了一个问题,既然内存占用和ssd都差不多,我为何不上纯内存的数据库呢?比如redis,我何必要redis转kv存储到哈希存储引擎呢?直接用redis存,10亿个普通小string的kv,估计都不需要60G,性能还远比你哈希引擎优异,更别说复杂数据结构了,若要转成kv的表达,还需要在key上追加约20字节的元数据,得不偿失。
那如果是非常大的value呢?举个例子,M级别的value。这种大value真的用哈希引擎更好吗?答案当然是否定的,姑且不论哈希引擎的设计本身就难以支持大value(如aerospike最多设置wblock为8M,即value最大8M)。做gc的时候,产生的迁移都是非常浪费资源的。这种情况不如直接用对象存储,比如快手的对象存储底层就是hdfs,直接把kv当对象存进去性能更好,成本也低得多。
所以结论产生了,哈希引擎只适合kb级别的value,比如现在快手哈希引擎支持的图数据库,约4kb的value。
当然以上的讨论都基于常规哈希引擎的定义方式,即key放内存,其实aerospike这种商业数据库早想到了这个问题,他们提供了索引落盘的方式,每次查索引都从ssd中直接查,他们对ssd极致的使用方式做到了这一切。如果索引落盘,所有数据都在ssd中,内存导致的成本问题得以解决。
再往外看看,其实facebook早提供了类似的实现,如blobdb,他基于rocksdb,做了kv分离,使得大value放在独立的blob文件存储,并自己实现了一套gc机制。其key存在lsm中,lsm的value只存了实际value的位置信息。
blobdb这种仔细思考,会发现就是哈希引擎的一种实现(成本优化版),如果他的key都放内存,不就是哈希引擎了吗?所以进一步论证了哈希引擎的应用场景的狭隘。