昨天被问到Key value存储到底有什么优势,当然脑子也没太转过来。正好昨天学习了B树和LSM树的差别,并了解到LSM树底层是可以用sstable来实现的。sstable包含一个数据块列表和一个索引块,数据块存储有序键镇对,索引块存储所有数据块的范围。当时想当然的回答了一下LSM树更适合写优化的场景,而B树则更适合读优化的场景。
后来仔细想想,回答的完全偏了。参考对于“键值存储”的理解 一文,这里再记录一下吧,也给自己增加一些更深刻的概念。
首先,说一下传统的二维表结构,是由多个行和多个固定的列形成的一个二维矩阵。由于这个二维矩阵是固定的表格的形式,这意味着表格里面的每个值都需要给定一个内容,如果这个值没有,就需要赋值NULL。
如果我们业务模型是一个类似工业时序场景,数据并不是那种固定的二维表格形式,而是像下面这种方式入库,那么我们的表结构应该怎么设计呢?
如果我们设计为一张二维表格,那么如果这里的指标非常多,这张二维表格就会变得很宽,同时里面的数据会有很多的NULL值,这样会浪费大量的空间,因为存储时需要将没有数据的内容置为NULL(置为NULL也是需要消耗存储空间的)。当这样的数据量变的很大时,性能下降就会变的非常明显了。
那么key value存储是什么样的呢,我们以HBase为例(因为以为正好使用过HBase)。HBase的存储结构是这样的:
- 每一行有一个唯一的key值(即下图中的RowKeyN)。
- 每一行可以有多个Column Family(列族),每个Column Family下面又可以包含多个列。每个列由的数据由元数据(列名)、数据(列值)、时间戳(可能会有)组成。
那么这种key value的存储结构它的好处是什么呢?
- 模式灵活。 因为不像关系模型中的二维表格是固定的模式,它是一种弱结构化数据,非常的灵活。一方面节点了空间,另一方面可以满足快速增加字段的需求。想想如果是关系模型的话,表里面有很多数据,然后要增加一个字段,所有的行都需要增加这个字段并且赋予一个NULL值或默认值。
- 点查询性能高。 key value存储里面的数据一般都是按key有序存储的,因此如果按给定的key进行点查询,将是非常快,这就类似于关系模型中的索引的功能。我们一般把key value数据库里面的这种表称为聚集索引(主索引),在这个表基础上增加的索引称为二级索引。
- 易扩展性。 包括HBase、TiDB、CRDB等数据库底层存储都是采用key value存储,他们都是分布式的产品。key value存储的简单性,使得它更容易进行拆分,进行分布式的存储。最基本的,我们根据key的范围,把数据分散在不同的节点上,以Region为单位进行存放,进而实现分布式存储和计算。
- 高可用性。 目前,业务很多基于kv存储的分布式数据库,为了保证高可用,结合Raft或Paxos等一致性协议,在写key value分片数据的时候会同时写多份,使用多数派的概念,更容易实现高可用性。而传统的关系数据库如Oracle、MySQL等,都是通过redolog或binlog日志流复制的方式来实现高可用性。