探索ES高可用:滴滴自研跨数据中心复制技术详解

Elasticsearch 是一个基于Lucene构建的开源、分布式、RESTful接口的全文搜索引擎,其每个字段均可被索引,且能够横向扩展至数以百计的服务器存储以及处理TB级的数据,其可以在极短的时间内存储、搜索和分析大量的数据。

滴滴ES发展至今,承接了公司绝大部分端上检索和日志场景,包括地图POI检索、订单检索、客服、内搜及把脉ELK场景等。

近几年围绕稳定性、成本、效率和数据安全这几个方向持续探索:

  • 滴滴ES有很多在线P0级检索场景,为了提升集群稳定性,我们自研了跨数据中心复制能力,实现多机房数据写入强一致性,并配合管控平台让ES支持多活能力;

  • 为了提升查询性能和解决查询毛刺问题,我们在7.6版本上原地升级支持JDK 17;

  • ES日志场景每天写入量在5PB-10PB量级,写入压力和业务成本压力大,为了提升ES的写入性能,我们让ES支持ZSTD压缩算法;

  • 由于ES索引里包含很多敏感数据,我们又完善了ES的安全认证能力。

基于以上探索,我们总结了一定的经验,现分成4篇文章详细介绍。本篇文章介绍滴滴ES如何实现索引的跨数据中心复制从而保证索引的高可用。

滴滴跨数据中心复制能力 - Didi Cross Datacenter Replication,由滴滴自研,简称DCDR,它能够将数据从一个 Elasticsearch 集群原生复制到另一个 Elasticsearch 集群。如图所示,DCDR工作在索引模板或索引层面,采用主从索引设计模型,由Leader索引主动将数据push到Follower索引,从而保证了主从索引数据的强一致性。

8da089a311ba863c4f3e832e64e465cc.png

DCDR跨数据中心复制能力图

DCDR在滴滴内部的主要生产应用如下:

  • 灾难恢复(DR)/高可用性(HA):如果主集群发生故障,能够通过切换主从集群快速恢复,从而实现异地多活

  • 索引迁移:索引可以在不同集群间迁移,保证集群间的数据均衡,同时实现索引在集群级别的分级保障

  • 主从查询隔离:由于主从索引的强一致性保证,配合自研ES Admin管控平台,不同业务方可以查询不同的集群,避免相互之间的查询影响         

背景及目标

原生的Elasticsearch提供了集群内部的高可用,能够保证集群内部的数据可靠性。但这种高可用无法满足对可靠性有进一步需求的用户。原生Elasticsearch主要有以下痛点:

  • 对于数据中心级别故障无法实现快速恢复

  • 数据在集群间搬迁成本很高,需借助外部工具来完成多个复杂操作

最初,滴滴内部应对跨数据中心的高可用,借助了外部同步平台将数据双写到不同集群来实现。该方式依赖较重,不支持历史数据同步,并且无法保证主从索引数据的强一致性。随着外部平台的收敛,双写的方式已经无法使用。ES 官方在6.7.0版本提供了跨集群数据复制功能,该功能需付费且只能保证主从索引数据的最终一致性。滴滴内部核心业务,如POI检索(滴滴APP上下车地点检索服务)、订单检索业务,都要求主从索引数据强一致性。

为解决上述问题,满足业务方诉求,滴滴ES团队决定自研跨数据中心复制能力,即上文的DCDR。

DCDR在设计时主要有以下几个目标:

  • 保证主从数据的强一致性

  • 保证高可用性,快速实现灾难恢复

  • 实现不停机跨集群索引迁移

  • 可靠的版本升级(Elasticsearch的Rolling upgrades和Full cluster restart upgrade方案都无法做到升级后回滚)

技术基础

DCDR功能支持将远程集群中的索引复制到本地集群,在复制过程中需要考虑两个重点:实时数据的同步、历史数据的同步。实时数据同步依赖ES写入机制,数据同步依赖ES副本恢复机制。因此,在介绍DCDR的方案设计以及实现细节之前,对这两个流程简单概述:

基本写入机制

ES写入是先写主分片,主分片写完后再将请求并行转发到副本,副本处理完再由主分片返回写入结果,具体流程如下:(注:本文中Si代表ES具体分片,P代表主分片,R代表副本)       

708b6187ae72aea147657b5b0ffb738f.png

副本恢复流程

为了保证数据副本的一致性,副本的数据需要恢复到和主分片一致才能正常对外提供服务。ES的副本恢复是分片级别的,分为主分片恢复流程和副分片恢复流程。由于ES的副本恢复流程极为复杂,并且DCDR的数据恢复过程中仅与副分片恢复流程相关,因此这里只简单地介绍下副分片恢复流程。

副本recovery的目标是要将本地数据恢复到和主分片一致,主流程分为两个阶段:

  • 阶段一是主分片给副本发送segment文件(存储的是已经落盘并解析后的具体数据)

  • 阶段二是主分片向副本发送translog日志(未落盘的数据,类似mysql 的WAL Log),两阶段结束后副本的恢复流程就结束了

具体流程如下图:     

77f9e737727dec837fd75d4411a34513.png

方案设计

设计思想

DCDR的核心思想是将从索引对应分片看做主索引对应分片的一个远程副本来处理。如下图,从索引的shard0主分片,会被当做主索引shard0主分片的一个远程副本。            

8ca24d513773ac806377202ac697774a.png

为了让大家更好地理解这个思路,简单介绍下远程副本:远程副本是由ES数据副本模型延伸而来,由主索引的主分片保存远程副本相关元数据,在实现上借鉴了微软的PacificA算法。该设计思想符合ES数据副本模型,能够极大程度地复用ES副本逻辑,降低开发难度,减少对开源ES内核的侵入。

以下是该算法的部分核心术语和ES数据副本模型的对应关系:

30cd7e3142744fb39c14ef17a9a7473e.png

具体方案设计

DCDR是跨集群数据复制能力,实现该功能的第一步就是需要明确哪些索引模板或者索引需要进行数据的跨集群复制,也就是需要建立起DCDR链路。其次,DCDR的从索引作为一个远程副本,需要恢复到和主索引的数据一致才能正常提供服务,即历史数据恢复。从索引的数据恢复到和主索引一致,当主索引新增数据时,数据该如何写入从索引,即实时数据同步。经过以上环节,从索引就能够正常提供服务,那么如何保证数据的可靠性呢?这就涉及到了主从索引数据质量校验。

基于以上思考,整个DCDR的方案设计上分为四个主流程:

c1d9eda23935eec9d70bcc48127a544e.png

1、DCDR链路构建

ES集群是基于集群状态驱动的,因此DCDR链路构建的本质就是改变集群状态,并在对应机器上应用新的集群状态。滴滴内部的ES使用方式是索引模板形式(一组拥有相同前缀的索引集合),因此在链路设计上需要支持模板链路和索引链路。DCDR链路集群元信息通过ES cluster state自定义metaData实现,链路拥有统一的命名规则,并且区分模板和索引,主要信息展示如下:

模板链路:
{
   "templates": {
       "templateA_to_ClusterA": {
           "name": "IndexA_to_ClusterA", // dcdr模板链路名
           "template": "templateA",               // 索引模板名
           "replica_cluster": "ClusterA"    // 从集群名称
       }
   }
}
索引链路:
{
   "Index_202206/Index_202206(ClusterA)": {
       "primary_index": "Index_202206", // 主索引名称
       "replica_index": "Index_202206", // 从索引名称
       "replica_cluster": "ClusterA", // 从集群名称
       "replication_state": true            // 链路状态
   }
}

ES集群对外提供了DCDR链路创建API,通过API将链路元信息更新到集群状态中,DCDR相关模块通过订阅集群状态变更事件,从而进入数据同步流程。如下图:         

dc8e8a265c09ed6c27bff93dae579249.png

有个设计细节需要注意:

Q:主从索引名是一致的,那么主从索引的唯一标识UUID(集群建索引后自动生成的随机字符串)要怎么处理呢?

  • 综合考虑开发难度和源码侵入问题,主从索引的索引名和UUID都保持一致

  • 在从索引创建时透传主索引的UUID到从集群,从索引在创建索引时不再自动生成UUID,解决从索引创建UUID不一致问题

  • 由于ES墓地会暂时保存被删除的索引,因此在从索引创建时扫描ES墓地并删除UUID相同的索引,解决从索引删除后无法重建问题

2、历史数据恢复

历史数据恢复方案在设计上借鉴了ES副本恢复策略。DCDR从索引的副本恢复同样是分片级别的,也需要进行segement和translog的复制环节。历史数据恢复发生的条件:

  • 新建DCDR链路,从索引需要根据主索引进行历史数据恢复

  • 从索引分片数据写入失败,主索引定时任务重建DCDR链路       

a12c1179890c744dce1e1aa3a0fdc43b.png

从索引作为远程副本在历史数据恢复方面和ES的副本恢复流程基本是一致的,主要区别(图中绿色标记)在于第1步的数据恢复触发条件,以及第6步加入的副本组不同。同时要注意以下设计细节:

Q:怎么触发历史数据的恢复?

  • ES的副本恢复是由集群状态变更事件驱动的,从索引的恢复是跨集群的,因此只能依靠主集群的RPC调用触发从集群的DCDR历史数据恢复。

Q:ES分片恢复是个很耗时的阶段,如何提高从索引的分片恢复效率,使得从索引能够快速提供服务?

  • 从索引只需要恢复自身的主分片数据,之后DCDR从索引历史数据恢复结束,从索引就能正常接收主索引的写请求了。从索引自身的副本恢复依赖于从集群的ES副本机制即可。这样能够极大地降低DCDR链路历史数据恢复时间。

Q:从索引什么时候可以正常接收主索引的写请求呢?

  • ES副本会在主分片phase1结束,副本启动Engine后加入主分片副本组,开始接收主分片的写请求。从索引的恢复也是类似的,从索引的主分片作为主索引对应主分片的远程副本,也会在主索引主分片phase1结束后,自身Engine启动后,由主索引的对应主分片加入远程副本组,开始接收写请求。

  • 远程副本组的实现是在ES的ReplicationGroup类中增加一个远程的prepared list。

Q:DCDR历史数据恢复过程中,主索引的主分片能否迁移?

  • 分片搬迁是集群均衡的一种手段,由于DCDR的恢复是跨集群的,无法通过集群状态变更快速地感知到分片迁移并进行处理。因此,主分片不能迁移。在DCDR数据恢复过程中,会通过加锁的方式防止主分片迁移。

3、实时数据同步

实时数据同步指的是历史数据同步完成后,增量数据如何同步到从索引。根据前文的ES写入流程可知,ES写入是先写主分片,之后再将写请求同步转发到副本上。基于滴滴内部业务场景考虑,需要异地多活的业务数据写入量一般不大,远未达到ES的写入瓶颈,并且一些核心业务对数据一致性有强依赖。因此,DCDR在实时数据同步上采用主分片写入成功,将数据同步转发给副本以及远程副本这一方案。该方案牺牲一定的数据写入性能,从而保证了数据的强一致性。

1751af456f0c5760a3af7832289956d0.png

实时数据同步策略采用的是将写请求转发到远程副本实现的,仍然有许多细节需要考虑:

Q:远程副本写入失败怎么办?

  • ES副本写入失败的处理策略是将副本从同步副本组移除,并重新执行Recovery。远程副本写入失败的处理策略和ES副本写入失败处理策略类似,是将远程副本从主索引主分片的远程副本组中移除,主索引将不再转发写请求到从索引,由从索引的定时检查机制重新执行数据恢复流程。

Q:从索引的seq_num(每条请求递增的唯一ID,用来加快副本恢复流程的)如何保证主从一致?

  • 从索引的分片采用了自定义的Engine,该Engine能够直接接收主索引传过来的seq_num,不再生成seq_num值。

Q:主从mapping如何保证一致?要更新mapping时怎么处理?

  • 新建DCDR链路时会将主索引的mapping拷贝到从集群,并新建从索引,保证链路新建时主从索引的mapping是一致的。

  • DCDR的设计思想是远程副本策略,是将写请求直接转发给从索引。因此,后期如果出现需要更新mapping的字段,会由主从集群各自的master去执行master任务去更新mapping即可(主从master mapping更新处理策略一致)。

4、主从索引数据质量校验

数据质量校验环节是从索引数据可靠性的保障。它会定时检查集群状态中的DCDR元信息是否和当前链路运行状态一致,根据结果对链路进行相应的操作。当主从索引数据差距过大或链路异常时,主集群会主动断开链路,并通知从索引进行差量数据恢复。ES集群中,MasterNode负责管控集群元数据,因此在设计校验任务时,主要用于链路元数据创建及检查从索引是否存在;DataNode负责数据存储,因此用于判断主从分片是否需要进行数据恢复。   

3da2636d091ba6071cd673a612d8c978.png

5、其他

经过以上4个环节就能将数据从一个 Elasticsearch 集群原生复制到另一个 Elasticsearch 集群,搭配上主从切换策略,就能在保证数据强一致性的前提下实现跨集群高可用。对于不停机跨集群索引迁移这一目标,我们通过DCDR将数据同步到目的端集群,等待存量数据恢复完成,再进行一次主从切换。对于可靠的版本升级这一目标,我们通过DCDR复制待升级版本数据到备用集群,当版本升级异常时能够快速切换集群。

总结

目前滴滴ES共有6个DCDR从集群,建立的DCDR模板链路400+,DCDR索引链路2000+,涵盖了POI、dos_order、soda等滴滴核心业务。目前ES仍然存在查询毛刺、查询相互影响、分片恢复、写入性能等方面问题,后续我们会在这些方面重点发力,更好的助力业务发展。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/66355.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

element-ui 表格el-table的列内容溢出省略显示,鼠标移上显示全部和定制样式

1、在对应列加上省略显示show-overflow-tooltip属性&#xff0c;如果加上这属性&#xff0c;鼠标移上还是没效果&#xff0c;要考滤是不是层级的原因&#xff0c;被其他挡住了。 :deep(.el-tooltip){position: relative;z-index:9; } <el-table-column label"用款渠…

java静默打印PDF(可实现生产环境下服务器写入PDF模板,然后调用客户端打印机打印)

java静默打印PDF可实现生产环境下服务器写入PDF模板&#xff0c;然后调用客户端打印机打印 一、简需求实现步骤 二、代码实现0、打印模板1、服务器部分 &#xff08;端口&#xff1a;8090&#xff09;1.1、maven依赖1.2、实体1.2.1、接口返回类1.2.2、标签纸页面参数类1.2.3、P…

Spring集成Web

目录 1、简介 2、监听器 3、Spring提供的listener 3.1、xml 3.2、配置类 3.3、WebApplicationContextUtils 3.4、说明 4、自己复现的listener 4.1、ContextLoaderListener 4.2、WebApplicationContextUtils 4.3、Web调用 ⭐作者介绍&#xff1a;大二本科网络工程专业…

《Linux运维实战:Docker基础总结》

一、简介 1、docker的基本结构是什么&#xff0c;包含哪些组件&#xff1f; docker的基本机构是c/s模式&#xff0c;即客户端/服务端模式。 由docker客户端和docker守护进程组成。docker客户端通过命令行或其它工具使用docker sdk与docker守护进程通信&#xff0c;发送容器管理…

Add-in Express for Microsoft Office and Delphi Crack

Add-in Express for Microsoft Office and Delphi Crack 适用于Microsoft Office和Delphi VCL的Add-in Express使您能够在几次点击中为Microsoft Office开发专业插件。它生成基于COM的项目&#xff0c;这些项目包含Microsoft Office外接程序或智能标记的所有必要功能&#xff0…

React实现关键字高亮

先看效果&#xff1a; 实现很简单通过以下这个函数&#xff1a; highLight (text, keyword ) > {return text.split(keyword).flatMap(str > [<span style{{ color: red, fontWeight: bold }}>{keyword}</span>, str]).slice(1);}展示某段文本时调用该函数…

Matlab进阶绘图第25期—三维密度散点图

三维密度散点图本质上是一种特征渲染的三维散点图&#xff0c;其颜色表示某一点所在区域的密度信息。 除了作图&#xff0c;三维密度散点图绘制的关键还在于密度的计算。 当然&#xff0c;不管是作图还是密度的计算&#xff0c;这些在《Matlab论文插图绘制模板》和《Matlab点…

k8s资源管理方法详解(陈述式、声明式)

目录 一&#xff1a;陈述式资源管理方法 二&#xff1a; 基本信息查看 1、查看信息 2、创建 3、删除 4、service 的 type 类型 三&#xff1a;项目实例 1、创建 kubectl create命令 2、发布 kubectl expose命令 3、在 node 节点上操作&#xff0c;查看负载均衡端…

Celery嵌入工程的使用

文章目录 1.config 1.1 通过app.conf进行配置1.2 通过app.conf.update进行配置1.3 通过配置文件进行配置1.4 通过配置类的方式进行配置2.任务相关 2.1 任务基类(base)2.2 任务名称(name)2.3 任务请求(request)2.4 任务重试(retry) 2.4.1 指定最大重试次数2.4.2 设置重试间隔时间…

Mac终端利器:Homebrew + iTerm2 + Oh My Zsh 教程

引言 前段时间调整了一下 iTerm2 的环境&#xff0c;感觉比以前好看多了&#xff0c;并且更加高效&#xff0c;这里做一个记录&#xff0c;希望能给大家一些启发。 工具介绍 brew&#xff1a;Mac OS 下强大的包管理工具。iTerm2&#xff1a;iTerm2是 Mac OS 终端的替代品&am…

Detecting Everything in the Open World: Towards Universal Object Detection

1. 论文简介 论文题目《Detecting Everything in the Open World: Towards Universal Object Detection》发表情况&#xff0c;CVPR2023[论文地址][https://arxiv.org/pdf/2303.11749.pdf][代码地址][https://github.com/zhenyuw16/UniDetector] 2.背景与摘要 本文旨在解决通…

Crowd-Robot Interaction 论文阅读

论文信息 题目&#xff1a;Crowd-Robot Interaction:Crowd-aware Robot Navigation with Attention-based Deep Reinforcement Learning 作者&#xff1a;Changan Chen, Y uejiang Liu 代码地址&#xff1a;https://github.com/vita-epfl/CrowdNav 来源&#xff1a;arXiv 时间…

Spring集成Seata

Seata的集成方式有&#xff1a; 1. Seata-All 2. Seata-Spring-Boot-Starter 3. Spring-Cloud-Starter-Seata 本案例使用Seata-All演示&#xff1a; 第一步&#xff1a;下载Seata 第二步&#xff1a;为了更好看到效果&#xff0c;我们将Seata的数据存储改为db 将seata\sc…

【IMX6ULL驱动开发学习】04.应用程序和驱动程序数据传输和交互的4种方式:非阻塞、阻塞、POLL、异步通知

一、数据传输 1.1 APP和驱动 APP和驱动之间的数据访问是不能通过直接访问对方的内存地址来操作的&#xff0c;这里涉及Linux系统中的MMU&#xff08;内存管理单元&#xff09;。在驱动程序中通过这两个函数来获得APP和传给APP数据&#xff1a; copy_to_usercopy_from_user …

电脑自动关机是什么原因?1分钟弄懂!

“好奇怪啊&#xff0c;我在使用电脑时&#xff0c;电脑总是莫名其妙就会自动关机&#xff0c;有时候我文件都来不及保存。这是为什么呢&#xff1f;有什么解决方法吗&#xff1f;” 电脑自动关机是一个令人头疼的问题&#xff0c;可能会对我们的工作和生活带来影响。电脑自动关…

数组相关练习

数组练习 将数组转化成字符串数组拷贝求数组元素的平均值查找数组中指定元素(顺序查找)二分查找冒泡排序数组逆序 将数组转化成字符串 import java.util.Arrays;public class Text1 {public static void main(String[] args) {int[] arr {5, 6, 4, 2};System.out.println(Arr…

电商数据获取:网络爬虫还是付费数据接口?

随着电商行业的迅速发展&#xff0c;对电商数据的需求也越来越大。在获取电商数据时&#xff0c;常常面临一个选择&#xff1a;是自己编写网络爬虫进行数据爬取&#xff0c;还是使用现有的付费数据接口呢&#xff1f;本文将从成本、可靠性、数据质量等多个角度进行分析&#xf…

【果树农药喷洒机器人】Part1:研究现状分析以及技术路线介绍

本专栏介绍&#xff1a;付费专栏&#xff0c;持续更新机器人实战项目&#xff0c;欢迎各位订阅关注。 关注我&#xff0c;带你了解更多关于机器人、嵌入式、人工智能等方面的优质文章&#xff01; 文章目录 一、项目背景二、国内外研究现状2.1 国内研究现状2.2 国外研究现状 三…

C语言内嵌汇编

反编译&#xff08;二进制文件或者so库&#xff09; objdump --help objdump -M intel -j .text -ld -C -S out > out.txt #显示源代码同时显示行号, 代码段反汇编-M intel 英特尔语法-M x86-64-C:将C符号名逆向解析-S 反汇编的同时&#xff0c;将反汇编代码和源代码交替显…

Python自动化测试用例:如何优雅的完成Json格式数据断言

目录 前言 直接使用 优化 封装 小结 进阶 总结 资料获取方法 前言 记录Json断言在工作中的应用进阶。 直接使用 很早以前写过一篇博客&#xff0c;记录当时获取一个多级json中指定key的数据&#xff1a; #! /usr/bin/python # coding:utf-8 """ aut…