ESDB论文重点整理

目录

基本概念

ESDB用途 - 交易数据查询

ES基本概念

ESDB创新点

ESDB架构

3.1 应用层

3.2 控制层

3.3 执行层

ESDB负载均衡

哈希、双重哈希

动态二次哈希

ESDB数据复制优化

总结


基本概念

ESDB用途 - 交易数据查询

        交易数据库中,交易日志包括结构化数据(如交易ID、卖家ID、创建时间和交易状态)和全文数据(如拍卖标题、卖家和买家的昵称)以及各种商品的信息,允许用户为商品添加自定义属性(如尺寸、衣服的材质、食物的重量),这导致了数据模式的多样化(即不同的交易日志有不同的属性)。
        例如:书店卖家通过拍卖标题中的关键词搜索图书交易的交易状态

        一般使用 JSON 格式存储数据,属于文档存储。

        分布式多租户数据库,来自多个租户的数据被分配到共享同一组计算和存储资源,但是不同租户使用量/使用频率不同

ES基本概念

  1. 分片:一个大的索引会被分成多个分片来进行存储数据,使用分布式的架构对分片进行并行搜索(基于倒排)。
  2. 倒排索引:对文本进行分词处理,记录单词,词频,文本id等信息,搜索时基于内容(根据单词和词频词向量等来计算评分)来找文本id
  3. 段:分片下分为段,索引文件被拆分为多个子文件,则每个子文件叫作段

索引太大-使用多个分片处理

索引更改频繁-降低文件粒度,使用多个段存储

ES和关系数据库对比:

  1. 索引库相当于关系数据库中的表,一个索引库存储相同类型的文档
  2. document和field与关系数据库的概念的类比:

文档(Document)----------------行记录

字段(Field)-------------------Columns 列

ESDB创新点

  1. 动态二级哈希,解决工作负载的高度不均衡所造成的性能下降问题。这种机制能够实现实时的工作负载均衡,以允许在不同的实例上实现平衡的写吞吐量。不同于双重哈希,需要读取几乎所有实例获取结果,它避免了分布式查询带来的额外压力。
  2. 多列查询的高RT(响应时间)和索引计算的高成本:如采用查询优化器、物理复制、基于频率的索引。这些优化使ESDB能够结合面向文档的数据库的特点(例如,高可扩展性和对全文检索的强大支持),同时为临时查询提供低RT(响应时间)。

ESDB架构

ESDB论文重点整理_第1张图片

ESDB论文重点整理_第2张图片

 

        ES服务层的每个节点即使协调者又是worker(上面有多个分片shard)

3.1 应用层

        应用层由ESDB的写客户端和查询客户端组成,对外提供RestfullAPI

        写客户端在ESDB的负载均衡器的配合下,ESDB的写客户端使用以下技术来加速写和缓解热点问题。

  1. 单跳路由。Elasticsearch最初的写客户端不知道工作负载的目的地。客户端以轮流的方式将工作负载路由到协调者,这导致了两跳路由(写客户端→协调者→worker)。在ESDB中,我们允许客户端了解路由策略。通过这种方式,我们实现了一跳路由(写客户端→worker),从而加速了写入。
  2. 热点隔离。在写客户端中,workloads会先在队列中缓存,之后成批的发送给worker。一旦一个worker过载(可能是由不均衡的写工作负载和慢查询操作造成的),队列将被阻塞,写延迟将上升。为了解决这个问题,ESDB实现了热点隔离,将热点的工作负载隔离到另一个队列中,这样就不会对其他工作负载产生负面影响
  3. 工作负载批处理。当一个写客户端检测到一个行(由其行ID识别)将在短时间内被频繁修改时,它将通过把这些修改聚合在一起并只实现该行的最终状态来批处理工作负载。通过采用工作负载批处理,写客户端避免了对同一行的重复写入,从而提高了写入吞吐量。

分析:

  1. 的确能加速,需要把这个保存到一个地方,具体文中未说明
  2. 多个队列,热点的放一起,普通的放一起,避免拖后腿的。如何判断热点未说明,还是有慢的就开启一个新的
  3. 在客户端就进行聚合,但是会进一步提升延时

        查询客户端。ESDB从Elasticsearch继承了RESTful API和查询语言ES-DSL。Xdriver4ES采用了一个智能翻译器,可以从SQL查询中生成具有成本效益的ES-DSL查询,优化点:CNF/DNF转换、谓词合并。

3.2 控制层

        控制层由一个主节点Master、协调者节点Coordinator和一个收集工作负载均衡指标的监视器Monitor组成。
        协调器节点Coordinator

  1. 读/写操作路由到相应的工作节点
  2. 查询结果聚合器,负责行ID的收集,并执行聚合操作(例如全局排序、总和、平均);在执行查询语句期间,协调器首先从所有参与的分片中收集所选行的行ID,然后获取相应的原始数据(由检索的行ID列表表示)
  3. 路由规则生成器,根据Monitor的信息,生成路由规则,同步给master(Load Balancer模块)

        主节点Master

        又分为以下3个模块

  1. 集群管理,如管理元数据、分片分配和rebalance,以及跟踪和监控节点。
  2. 负载均衡器Load Balancer。ESDB的负载均衡器是为了生成和提交指示读/写路由器的路由规则而开发的。
    由于它是通过动态二次哈希实现,所以路由规则也被称为二次哈希规则。
    一旦监测器检测到热点,协调器将生成新的路由规则,这些规则基本上是分割和扩展承载当前热点的分片。通过利用新的路由规则,ESDB将大租户的工作负载分配给更多的分片,从而减轻了过重的节点负担。一旦它从协调者那里收到新的路由规则,主节点就会负责提交这些规则。通过这种方式,负载均衡器确保了整个集群中工作负载路由的一致性。我们在第4节中介绍了负载均衡器的更多设计细节。
  3. 基于频率的索引(索引增删)。为了减轻维护 "属性 "列的子属性索引的成本(见第2.1节),我们采用了基于频率的索引(即只为最经常被查询的子属性建立索引)。这个想法来自于对子属性的读/写频率是不均衡的观察。例如,一些通用的子属性,如 "活动",表示卖家的哪些电子商务活动频繁使用并可能被查询。在实践中,基于频率的索引在查询延迟方面有明显的改善,代价是存储开销略有增加。

        只为最经常被查询的子属性建立索引,因为有的子属性的确超级高,有的的确超级低

3.3 执行层

        Worker在其本地SSD中维护分片和副本,并执行读/写工作负载。每个worker维护自己的存储,与其他worker无关。

  1. 写执行和数据复制。近实时搜索,在内存buffer的是不能被搜索到的,刷入到文件缓存即可(此时尚未持久化到磁盘)
    1. Elasticsearch采用了一种逻辑复制方案:一个主分片一旦在本地执行了一个写操作,就会把他转发给它的所有副本。换句话说,相同的写操作分别由副本执行,这给集群带来了n倍的计算开销(n是副本的数量)。在ESDB中,写操作仍然被实时转发并添加到副本上的Translogs,但从未被副本执行。相反,它实现了segment文件的物理复制。
    2. 原始数据和索引会先写入内存buffer之后定期刷入到磁盘的segment文件,之后可用于搜索之前。为了解决持久化问题,避免数据丢失,ESDB采用了与磁盘有关的Translog。每一个写的工作负载一旦成功提交,就会被添加到Translog中。这样,如果ESDB遇到进程崩溃或硬件故障,未被刷新到磁盘的数据可以从Translogs中安全恢复。
    3. 段合并是另一个重要的机制,它将较小的段合并到一个大段。花费了计算资源,有效地提高了查询效率。
  2. 查询优化器Query Optimizer。对于查询工作负载,ESDB使用一个基于规则的优化器建立优化的查询计划。ESDB没有对所有的列使用索引扫描,而是提供了更多的操作,如复合索引扫描和顺序扫描。通过利用不同操作的组合,ESDB大大降低了查询延迟。优化的细节将在第5节介绍。
  3. Query Executor

ESDB负载均衡

哈希、双重哈希

        哈希即使用哈希算法对K计算得到一数值,之后Mod 总数N。

        双重哈希: 引入一对独立的二级哈希函数,以便在第一个哈希函数引起碰撞时产生偏移。

        p=(h1(k)+ih2(k)) mod N,其中i随着碰撞序列的增长而增加,N是哈希表的大小。

ES中的双哈希策略

        使用两个独立的哈希函数,两个属性k1和k2以及一个全局静态变量s

        p=(h1(k1) + h2(k2)mod s) mod N --> h1(k1) mod N + (h2(k2)mod s) mod N
        k1是负载均衡的主要属性(如租户ID),k2是为每个交易唯一生成的密钥(如交易ID),1≤s≤N,s∈Z。

        对于ES,即为 h1(k1) mod N + 偏移量,于是分片便从原来的单个分片变成了一个范围,对于给定的K1,K2通过该公式能唯一确定具体分片。只是K1的范围变大了。

        当s=1时(任何整数求余1为0),双哈希退化为哈希 --> 单个分片。

        当s=N时,双哈希将记录路由到所有分布式分片。它使所有租户的工作负载完全平衡,但需要查询执行从所有分布式分片中搜索和汇总查询结果,从而导致低查询吞吐量。一旦数据以分布式方式存储,如sort和topK,会更加耗时。

动态二次哈希

概念

        固定的最大偏移量s被替换为L(K1)。1≤L(K1)≤N,L(K1)∈Z,L(K1)为租户K1实时工作负载和当前存储容量
        原公式:p=(h1(k1) + h2(k2)mod s) mod N --> p=(h1(k1) + h2(k2)mod L(k1)) mod N

        在实践中,二次哈希的最大偏移量s=L(K1)依赖于两个指标:

  1. 当前存储量。假设具有较大存储比例的租户更有可能具有较大的即将到来的工作负载。对大多数存储比例较小的租户设置s=1。
  2. 实时工作负载。根据工作负载监控器定期报告的实时写吞吐量比例,负载均衡器将为被认为是热点的租户扩大最大偏移量s。这种对s的调整发生在ESDB的运行期间。
  3. s为2的指数(例如,1,2,4),以限制二级哈希规则的数量,并加速规则列表中的搜索

三种哈希方式对比

        哈希法:只能根据分区密钥(如租户ID)的1级哈希来路由工作负载,因此当它需要平衡多租户的工作负载时,就会出现问题。每次都是固定的一个

        普通的双重哈希:能够根据两个键(即租户ID和记录ID)的2级哈希将租户的工作负载路由到一组固定的连续分片,但不能管理动态工作负载。每次都是固定的范围

        动态二级哈希:也将工作负载路由到连续的分片,当工作负载增加时,它能够扩展到连续的分片(例如,图4中L(K1)从8增加到16)。可以动态扩展分片范围。

ESDB论文重点整理_第3张图片

读写一致性 Read-your-writes Consistency

        二级哈希偏移的变化会给读写一致性带来风险,因为使用的分片范围变化导致写入的范围变化,对应查询的范围也需要变化。

        ESDB的初始化和负载均衡运行时维护二级哈希规则列表R。每个二次哈希规则被维护为一个元组(t, s, k_list),其中t代表规则生效的时间,s是二次哈希的最大偏移量,k_list记录在二次哈希中采用s的租户ID。

用哈希规则进行负载均衡

         在初始化阶段(第5-10行),负载均衡器从每个租户的当前存储中建立二级哈希规则。

        在运行阶段(第11-21行),负载均衡器根据实时工作负载的波动,更新二级哈希规则列表R,主要是为热点数据的租户进行更新。

        写操作(如INSERT、UPDATE、DELETE)(通过租户ID k1、记录ID k2和记录创建时间t_c(create)标识),到达协调器节点,协调器负责从R中选择一个匹配的二级哈希规则。该规则(t, s, k_list)必须满足以下三个条件:

  1. t必须是早于记录的创建时间t_c。
  2. k1在k_list中。
  3. s是所有满足前两个条件的规则中最大的一个。

        读操作(SELECT)到达时,ESDB查询客户端使用k1的匹配二级哈希规则(t, s, k_list)来决定查询应该在哪个连续的分片上执行,即从分片h1(k1) mod N到分片(h1(k1) + s-1) mod N。

共识

        在ESDB中,每个节点都是一个协调者,负责将工作负载路由到匹配的分片。因此,一旦任何节点上产生了新的规则,整个系统必须对二级哈希规则列表R达成共识,以确保严格的一致性。

        因为R是一个append only的列表,每个规则都与有效时间有关,不需要决定规则的排序(因为它们是按有效时间排序的),因为可以简化为决定是承诺还是中止。在ESDB中,我们提出了一个2PC的变体协议,其灵感来自于Spanner的提交等待机制,以解决工作负载阻塞的问题。图5显示了这个协议的概况。

ESDB论文重点整理_第4张图片

        准备阶段。每当协调者节点建立了一个二级哈希规则,它就会将新的规则发送给ESDB集群的Master。Master决定规则生效的有效时间t(使用本地时间),人工配置的时间间隔T,t = timer.now() + T.Next ,主节点将有效时间作为建议广播给所有参与者节点(应该是所有协调者)。当一个参与者收到建议时,它检查其所有记录是否在有效时间之前被创建如果这个条件得到满足,参与者会阻止所有创建时间晚于有效时间的工作负载,并向主节点回复一个接受信息。否则,参与方会向主节点报告错误。如果主节点收到任何错误信息或检测到任何超时(参与者在T/2内没有回应),这个二级哈希规则将被终止。否则,提交阶段开始。

        提交阶段。主节点向所有参与的协调者广播提交消息以及二级哈希规则。由于所有节点在上一阶段达成了共识,它们将接受提交消息并将该规则添加到它们的本地二级哈希规则列表中。一旦提交阶段完成,各节点将删除工作负载的执行块(即继续处理创建时间大于有效时间的工作负载)。

        选择时间间隔。时间间隔T为系统提供一个缓冲期,以便就二级哈希规则达成共识。T应远远大于广播的往返延迟(如100ms)和整个集群的本地时钟偏差的最大值(在ESDB中不超过1s),以确保严格的一致性。同时,T应短于我们预期的负载均衡时间(如60s),以保证有效性。只要T大于集群达成共识的时间,ESDB的共识协议就能实现工作负载处理的无阻塞。

        容错性。尽管ESDB的共识协议保证了R的严格一致性,但在提交阶段,它仍然会受到网络分区和节点故障的影响。ESDB采用了一种自动容错的解决方案。然而,它依赖于对网络分区和节点故障的检测,也就是说,它需要区分暂时没有响应的节点和故障节点。一个典型的解决方案是使用一个预先定义的超时;在ESDB中,我们手动验证一个提出的警报(一个节点变得无响应),以明确决定是否发生了节点故障或网络分区。

ESDB数据复制优化

        不要求副本执行相同的写入工作负载(即逻辑复制),而是直接复制段文件。当主分片刷新一个新的段文件时,它初始化一个复制过程,在此期间,副本计算段差(即位于两个分片上的段文件之间的差异),并从远程分片上请求缺少的段。

        ESDB采用了物理复制,目的是减少复制过程中产生的CPU开销。具体来说,我们设计它是为了克服以往工作中看到的两个缺点。1)冗长的单体复制过程,很容易被新一轮的复制过程打断;2)复制大型合并段所造成的较长的可见性延迟(即一个段在主分片和复制段上变得可见的时间戳之间的间隔)。ESDB的物理复制框架(如图9所示)由三种复制机制组成。

  1. Real-time synchronization of Translog。Translog的实时同步。由于Translog是ESDB的持久性保证,我们要求它应该在主分片和副本之间进行实时同步。一旦写工作负载被成功执行,主分片就会将其转发到复制区。然后,复制区将收到的写工作负载添加到其本地Translog中。通过这种方式,ESDB确保所有副本能够在副本失败或主/副本切换的情况下在本地恢复数据。
  2. Quick incremental replication of refreshed segments。ESDB进一步采用了快速增量复制机制,以避免长时间的复制过程,因为这很容易被打断。图9描述了快速增量复制的六个步骤。
    1. 主分片建立一个当前本地段的快照,并在每次刷新操作完成后将其添加到快照列表中(显示为黄色框)。
    2. 最新的快照(即本例中的快照3)被选为当前主状态。
    3. 主分片锁定当前快照中的段(即段A和段B),并将其发送到副本中。
    4. 复制器根据其本地快照和从主分片收到的快照计算段差。基于段差,副本要么请求段(即段B),要么删除已经被主分片删除的段。
    5. 主分片发送由副本请求的段。
    6. 复制完成后,副本通知主碎片解锁当前快照中的分段。

当刷新间隔较短时,上述机制稳定了物理复制过程,并保证了最新片段的复制。

  1. 合并段的预复制。由于合并的段通常很大,用快速增量复制合并的段会导致复制刷新的段的延迟。例如,如果图9中的快照3包含段C,复制将请求段B和段C一起。为了解决这个问题,我们进一步引入了对合并段的预复制。当一个合并段产生时,主分片立即开始将其复制到副本中。这种预复制是与快速增量复制一起独立运行的。通过这种方式,合并段永远不会出现在段差中,因此对刷新段的复制的影响有限。

ESDB论文重点整理_第5张图片

总结

这篇论文对于不搞ES的大概比较有启发性的有以下几点:

  1. 如果你的多租户场景是,实际上大家使用相同的分片,那么这种方式可以参考。例如hbase根据key哈希映射到相同的region,这样会导致热点,后面业务侧通过多个不同的表和随机的key实现了让其均衡。
  2. 4.2节对于2PC的修改的提交机制,不过这个需要看场景
  3. 数据应用,先放到文件缓存中,之后在慢慢应用到磁盘
  4. 副本间数据同步 5.2节

你可能感兴趣的:(分布式存储,分布式存储,elasticsearch)