Table of Contents |
---|
背景
在新分布式的架构中,SG 是用户建模时的逻辑概念(类似于 database),VSG database),DataRegion 是可以不让用户感知到的物理概念(拥有一套 TSM)。
...
在当前的分区设计中,不同的 sg 拥有不同的设备组,每个设备组的不同时间分区均会按照一定的策略被分配到对应的 VSG DataRegion 共识组中去。
从 VSG DataRegion 共识组的角度来看,其会管理若干设备组在不同时间分区的数据。那么,一个 VSG DataRegion 共识组是否可以管理不同 sg 的设备组呢?如果可以,整个集群的 VSG DataRegion 共识组数便不会随着 sg 的增加而增加,这会进而影响分布式架构在负载均衡,资源管理等方面的设计。
由于只存在一个 sg 时讨论该问题没有意义,因而以下部分会假设用户存在多个 sg。
本文将就在多 sg 场景下,一个 VSG DataRegion 共识组只能管理一个 sg 的设备组的优劣势进行讨论并给出一些其他系统的选择。
对比
本小节将简单列举一个 VSG DataRegion 共识组只能管理一个 sg 数据的优劣势。
优势
- 写入理论延时更低:原因在于逻辑分片的粒度更细。
- 对于类似于 Ratis/Sofa-jraft 的共识算法库,其默认用一个异步 apply 线程去往状态机按序 apply 日志,然而在单机引擎内不同 sg 的写入原本可以并行。
- 如果不做并行 apply 的优化,可以预见写入延时会很高;
- 如果做并行 的写入原本可以并行。如果不做并行 apply 的优化,可以预见写入延时会很高;如果做并行 apply 的优化,则需要在 raft 库的 apply 线程中再进行一次异步调度,同时还需要支持 apply 返回异步 future 的 raft 库才方便做这样的优化,集成成本和维护成本会更高。
- 查询理论延时更低:原因在于逻辑分片的粒度更细。
- 对于类似于 Ratis/Sofa-jraft 的共识算法库,其默认的读接口是线性一致性读,即需要等到 applyIndex 达到 leader 的 commitIndex 之后再去状态机读,这样的机制主要是为了防止出现脏读。当不同 sg 的数据存在于一个 raft 组中时,即使某一个 sg 没有写入,在查询该 sg 的数据时可能也要等待该共识组其他 sg 数据的并发写入被 apply 之后才可以去状态机读,这会进而增大查询延时。
- 做时间分区,多级存储和 TTL 时开发成本更低,效率更高:原因在于只有拥有相同属性的设备会被存在同一个 tsfile 中,便于以文件粒度进行处理。
- 对于时间分区和多级存储,当一个 VSG DataRegion 共识组只能管理一个 sg 的数据时,其整体的流程基本都可以按照文件的粒度去生成和迁移,开发成本较低。
- 对于 TTL,当一个 VSG DataRegion 共识组只能管理一个 sg 的数据时, 一个 tsfile 所有设备的 ttl 均相同,过期删除实现方便,查询也不需要做额外的过滤。
- 做数据备份的开发成本更低,性能更好:原因在于只有拥有相同属性的设备会被存在同一个 tsfile 中,便于以文件粒度进行处理。
- 对于做单 sg 的数据备份,显然此方案开发成本更低,性能(往往只需要硬链接,不需要重新去 build)都会更好。
- 调度灵活性更强:原因在于逻辑分片的个数更多。
- 对于多 sg 场景,由于集群的总共识组个数相比另一种方案更多,对共识组的副本组做调度即成员变更时的成本会更低。
- 更容易做到资源隔离:
- 对于多 sg 场景,此方案更容易支持不同 sg 的资源隔离(挂载不同磁盘,分配不同数量的线程资源),另一个方案写入一套 TSM 后就很难再去做资源隔离了。
- 与现有逻辑保持一致:
- 在当前单机的 VSG DataRegion 实现中,一个 tsfile 只会拥有单个 sg 的数据。目前还不确定在 tsfile 写入不同 sg 的数据时读写流程是否还需要改动。
劣势
- 当用户创建大量的 sg 且写入少量数据时,可能导致产生大量的 raft 组,对集群的 CPU 资源产生浪费,这对存储引擎的线程模型提出了一定的挑战。
- 可能的解决方案(可以都做):
- 方案 1:目前单机版推荐用户的存储组数 * VSG DataRegion 个数 = 总核数,在新分布式架构中,可以为 sg 指定 vsg 的参数,默认为集群总核数DataRegion 的个数,默认为集群总核数/副本数。这样一方面方便单 sg 用户去充分利用集群所有的存算资源,也能给为多 sg 用户做细粒度的资源分配提出方案。
- 方案 2:在存储上,此方案更便于做到 IO 的隔离。在计算上,参照 TiDB,CockroachDB 等数据库去做 multi-raft 的优化,包括但不限于心跳合并,线程池合并等。可以抽象出一些复用的线程池并对计算做一些管理。其实就跟操作系统对不同进程提供的保证一样,在我看来,没必要去限制进程个数不多于核数。尽管当进程过多时进程切换会带来一定的性能损耗,但其扩展性一定是更强的,而且聪明的程序员一定能从自己的应用场景寻找到避免频繁进程切换的解决方案。的优化,包括但不限于心跳合并,线程池合并等。不论是单机还是分布式都应该尽可能将数据结构(LSM,Raft)和计算(线程资源)进行解耦。可以抽象出一些复用的线程池并对计算做一些管理。
- 其实就跟操作系统对不同进程提供的保证一样,在我看来,没必要去限制进程个数不多于核数。尽管当进程过多时进程切换会带来一定的性能损耗,但其扩展性一定是更强的,而且聪明的程序员一定能从自己的应用场景寻找到避免频繁进程切换的解决方案。
- 可能的解决方案(可以都做):
调研
TDengine
tdengine 允许通过配置参数的方式
...
去限制最大 vnode
...
的个数,其一个 vnode 只能管理一个 database
...
的数据。其对于该问题的解决方案本质上与一个 DataRegion 共识组不被 sg 复用类似
...
TiDB
在 TiDB 的架构中,TiKV 可以被理解为一个无限大的有序 map,不同 database 的表会按照对应的编码规则组成 key 写入到 TiKV 中去。其每个一个 region 是一个 raft 组,其 region 个数既不与 database 个数有关,也不是静态不变(总核数 / 副本数)的,而是与数据的总大小有关,默认 128M 会组成一个 raft 组。
尽管 TiDB 不同 database 的数据在编码后理论上可能存在于一个 region 中,但大部分情况下同一个 region 的数据均是同一个 database 同一张表的数据。
总结
本文简单介绍了一个 VSG DataRegion 共识组只能管理一个 sg 的设备组的优劣势并分别就原因和解决方案进行了讨论。由于作者水平有限,以上观点不一定绝对正确,欢迎大家补充修正。
...