来自:DBAplus社群

作者介绍

李猛(ynuosoft),Elastic-stack产品深度用户,ES认证工程师,2012年接触Elasticsearch,对Elastic-Stack开发、架构、运维等方面有深入体验,实践过多种Elasticsearch项目,最暴力的大数据分析应用,最复杂的业务系统应用;业余为企业提供Elastic-stack咨询培训以及调优实施。

序言

图示:MongoDB与Elasticsearch热度排名

本文内容涉及到MongoDB与Elasticsearch两大阵营,可能会引起口水之争,仅代表个人经验之谈,非阵营之说,围绕两个话题展开:

  • 为什么要从MongoDB迁移到Elasticsearch?

  • 如何从MongoDB迁移到Elasticsearch?

现状背景

MongoDB本身定位与关系型数据库竞争,但工作中几乎没有见到哪个项目会将核心业务系统的数据放在上面,依然选择传统的关系型数据库。

1、项目背景

项目背景

公司所在物流速运行业,业务系统复杂且庞大,用户操作者很多,每日有大量业务数据产生,同时业务数据会有很多次流转状态变化,为了便于记录追踪分析,系统操作日志记录项目应运而生,考虑到原有的日均数据量,操作日志数据基于MongoDB存储。

操作日志记录系统需要记录两种数据,如下说明:

1)变更主数据,什么人在什么时间在系统哪个模块做了什么操作,数据编号是什么,操作跟踪编号是什么。

{

"dataId": 1,

"traceId": "abc",

"moduleCode": "crm_01",

"operateTime": "2019-11-11 12:12:12",

"operationId": 100,

"operationName": "张三",

"departmentId": 1000,

"departmentName": "客户部",

"operationContent": "拜访客户。。。"

}

2)变更从数据,实际变更数据的变化前后,此类数据条数很多,一行数据多个字段变更就记录多条。

[

{

"dataId": 1,

"traceId": "abc",

"moduleCode": "crm_01",

"operateTime": "2019-11-11 12:12:12",

"operationId": 100,

"operationName": "张三",

"departmentId": 1000,

"departmentName": "客户部",

"operationContent": "拜访客户",

"beforeValue": "20",

"afterValue": "30",

"columnName": "customerType"

},

{

"dataId": 1,

"traceId": "abc",

"moduleCode": "crm_01",

"operateTime": "2019-11-11 12:12:12",

"operationId": 100,

"operationName": "张三",

"departmentId": 1000,

"departmentName": "客户部",

"operationContent": "拜访客户",

"beforeValue": "2019-11-02",

"afterValue": "2019-11-10",

"columnName": "lastVisitDate"

}

]

2、项目架构

项目背景

项目架构描述如下:

  • 业务系统新增或者编辑数据,产生操作日志记录发送到Kafka集群,基于dataid字段作为key;

  • 新增或编辑数据实际存储到MySQL数据库;

  • canal集群订阅MySQL集群,按照业务系统模块配置监控的数据库与表;

  • canal将监控到的变更业务数据发送到Kafka集群,基于dataid字段作为key;

  • 操作日志系统从Kafka获取主记录数据与从记录数据;

  • 操作日志系统写入数据到MongoDB,同时需要反查询。

图示:操作日志记录业务流程说明

3、MongoDB架构

项目背景

集群架构说明:

  • 服务器配置8c/32gb/500gb ssd;

  • Router路由服务器部署了3个节点;

  • Config配置服务器部署了3个节点;

  • Shard分片服务器部署了9个节点;

  • 主操作记录设计3个分片;

  • 从操作记录设计3个分片。

问题说明

MongoDB的信徒们可能怀疑我们没有使用好,或者我们的运维能力欠缺,或者认为我们有Elasticsearch的高手在。不是这样的,弃用MongoDB选择Elasticsearch其实并非技术偏见问题,而是我们的实际场景需求,原因如下:

1、搜索查询

项目背景

  • MongoDB内部采用B-Tree作为索引结构,此索引基于最左优先原则,且必须保证查询顺序与索引字段的顺序一致才有效,这个即是优点,但在现在复杂业务场景也是致命的;

  • 业务系统查询操作日志记录会有很多过滤条件,且查询条件是任意组合的,现有MongoDB是不支持的,或者说所有关系型数据库都不支持,如果要支持,得创建好多组合的B+数索引,想法很不理智,这个我们已经在《DB与ES混合之应用系统场景分析探讨》文中探讨过,详细可以阅读;

  • 同时主记录与从记录中有很多字符类的数据,这些数据查询即要支持精确查询,也要支持全文检索,这几个方面MongoDB功能很单一,性能也很糟糕,业务系统查询时经常超时,反倒是Elasticsearch非常合适。

2、技术栈成熟度

项目背景

  • 分片与副本实现问题,MongoDB集合数据在设计时是需要绑定到具体的机器实例的,哪些分片分布在哪些节点上,哪些副本分布在哪些节点上,这些都需要在配置集群时就要绑定死,跟传统的关系型数据库做分库分表本质上没有什么两样,其实现在很多数据产品的集群还是这种模式偏多,比如Redis-cluster,ClickHouse等。而Elasticsearc的集群与分片和副本没有直接的绑定关系,可以任意的平衡调整,且节点的性能配置也可以很容易差异化;

  • 操作日志数据量增加很快,单日写入超过千万条,不用多久,运维人员就需要对服务器进行扩容,且相对Elasticsearch复杂很多;

  • MongoDB单集合数据量超过10亿条,此情况下即使简单条件查询性能也不理想,不如Elasticsearch倒排索引快;

  • 公司对于ES与MongoDB技术栈的经验积累不同,Elasticsearc在很多项目中运用,非常核心的项目也是大量运用,对于其技术与运维经验更丰富,而MongoDB如果除去核心业务场景,几乎找不到合适的切入口,实际没有人敢在核心项目中使用MongoDB,这就很尴尬。

3、文档格式相同

项目背景

MongoDB与Elasticsearch都属于文档型数据库 ,Bson类同与Json,_objectid与_id原理一样,所以主数据与从数据迁移到Elasticsearch平台,数据模型几乎无需变化。

迁移方案

异构数据系统迁移,主要围绕这两大块内容展开:

  • 上层应用系统迁移,原来是针对MongoDB的语法规则,现在要修改为面向Elasticsearch语法规则;

  • 下层MongoDB数据迁移到Elasticsearch。

1、Elastic容量评估

项目背景

原有MongoDB集群采用了15台服务器,其中9台是数据服务器,迁移到Elastic集群需要多少台服务器?我们采取简单推算办法,如假设生产环境上某个MongoDB集合的数据有10亿条数据, 我们先在测试环境上从MongoDB到ES上同步100万条数据,假设这100万条数据占用磁盘10G,那生产上环境上需要1个T磁盘空间,然后根据业务预期增加量扩展一定冗余。根据初步评估,Elastic集群设置3台服务器, 配置8c/16g内存/2T机械磁盘。服务器数量一下从15台缩减到3台,且配置也降低不少。

2、Elastic索引规则

项目背景

系统操作日志是时序性数据,写完整后基本上无需再次修改。操作日志记录查询主要是当月的居多,后续的历史性数据查询频率很低,根据评估,核心数据索引按月创建生成, 业务查询时候必须带上操作时间范围,后端根据时间反推需要查询哪些索引,Elastic-Api支持多索引匹配查询,完美利用Elastic的特性解决跨多个月份的查询合并。对于非核心数据索引,按年创建索引生成足以。

图示:Elastic操作日志索引创建规则

3、核心实现逻辑设计

项目背景

Elasticsearch不是关系型数据库,不具备事务的机制。操作日志系统的数据来源都是Kafka,消费数据是有顺序机制的,有2种场景特别注意,如下:

  • 主数据先到操作日志系统,从数据后到,从数据写的时候先拼凑主数据记录和Binlog字段数据;

  • 从数据先到操作日志系统,主数据后到,主数据更新从索引的相关的索引字段。

Elasticsearch索引数据更新是近实时的刷新机制,数据提交后不能马上通过Search-Api查询到,主记录的数据如何更新到从记录呢?而且业务部门不规范的使用,多条主记录的dataId和tracId可能一样。

由于主数据与从数据关联字段是dataId和traceId。如果主数据与从数据在同时达到操作日志系统,基于update_by_query 命令肯定失效不 准确, 主从数据也可能是多对多的关联关系,dataId 和traceId不能唯一决定一条记录。

Elasticsearch其实也是一个NoSQL数据库, 可以做key-value缓存。这时新建一个Elastic索引作为中间缓存, 原则是主数据与从数据谁先到缓存谁,索引的 _id=(dataId+traceId) , 通过这个中间索引可以找到主数据记录的Id或者从记录Id, 索引数据模型多如下,detailId为从索引的_id的数组记录。

{

"dataId": 1,

"traceId": "abc",

"moduleCode": "crm_01",

"operationId": 100,

"operationName": "张三",

"departmentId": 1000,

"departmentName": "客户部",

"operationContent": "拜访客户",

"detailId": [

1,

2,

3,

4,

5,

6

]

}

前面我们讲过主记录和从记录都是一个Kafka的分区上,我们拉一批数据的时候,操作ES用的用到的核心API:

#批量获取从索引的记录

_mget

#批量插入

bulk

#批量删除中间临时索引

_delete_by_query

迁移过程

1、数据迁移

项目背景

选择DataX作为数据同步工具由以下几个因素:

  • 历史型数据。操作日志记录数据属于历史性的数据,记录产生之后几乎无需二次修改,等同于离线数据;

  • 非持续性迁移。项目全部完工之后,原有的MongoDB集群会全部销毁,不会有二次迁移需求;

  • 数据量问题。原有MongoDB操作日志数据量有几十亿条,迁移过程不能太快也不能太慢,速度太快,MongoDB集群会出现性能问题,速度太慢,项目周期太长,增加运维的成本与复杂度。否则可以选择Hadoop作为中转平台的迁移;

  • DataX源码特定场景改造。如日期类型的转换、索引主键_id的生成、索引主键_id映射,支持重复同步;

  • 多实例多线程并行。主数据同步部署多个实例,从数据同步也部署多个实例,单实例中配置多个Channel。

图示:DataX同步数据示意图

2、迁移索引设置

项目背景

临时修改索引的一些设置,当数据同步完之后再修改回来,如下:

"index.number_of_replicas": 0,

"index.refresh_interval": "30s",

"index.translog.flush_threshold_size": "1024M"

"index.translog.durability": "async",

"index.translog.sync_interval": "5s"

3、应用迁移

项目背景

操作日志项目采用Springboot构建,增加了自定义配置项,如下:

#应用写入mongodb标识

writeflag.mongodb: true

#应用写入elasticsearch标识

writeflag.elasticsearch: true

项目改造说明:

  • 第一次上线的时候,先将2个写入标识设置为true,双写MongoDB和ES;

  • 对于读,提供2个不同接口,前端自由的切换;

  • 等数据迁移完,没有差异的时候,重新更改flag的值。

图示:应用平衡迁移

结语

1、迁移效果

项目背景

弃用MongoDB使用ElasticSearch作为存储数据库,服务器从原来的15台MongoDB,变成了3台ElasticSearch,每月为公司节约了一大笔费用。同时查询性能提高了10倍以上,而且更好的支持了各种查询,得到了业务部门的使用者,运维团队和领导的一致赞赏。

2、经验总结

项目背景

整个项目前后历经几个月,多位同事参与,设计、研发,数据迁移、测试、数据验证、压测等各个环节。技术方案不是一步到位,中间也踩了很多坑,最终上线了。ES的技术优秀特点很多,灵活的使用,才能发挥最大的威力。


特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:长按订阅更多精彩▼如有收获,点个在看,诚挚感谢

从MongoDB迁移到ES后,我们减少了80%的服务器相关推荐

  1. 李猛:从MongoDB迁移到ES后,我们减少了80%的服务器

    李猛 DBAplus社群 读完需要 10 分钟 速读仅需 4 分钟 作者介绍 李猛(ynuosoft),Elastic-stack产品深度用户,ES认证工程师,2012年接触Elasticsearch ...

  2. php 库存自动减少,ECSHOP付款后自动减少库存功能

    ecshop默认只有下订单时和发货时,在用户拍了而没确认订单就减少库存,是不合理的机制,也不能满足各种客户需求.因此ECSHOP插件网提供付款后自动减少库存插件,在用户下单付款后自动减少商品库存,满足 ...

  3. MongoDB同步到ES

    MongoDB 同步,关键在于要有复制集,由复制集同步到ES ElasticSearch :版本6.3.2 Kibana:6.3.2(可以理解为ES的可视化管理工具) MongoDB: 版本6.0.2 ...

  4. ubuntu虚拟机迁移/移动/复制后无法上网

    我是把虚拟机完全从我的笔记本电脑复制到台式机了,发现一切都好,就是上不了网,据网上介绍,应该是复制后网卡不对了,按照如下步骤,我解决了我的问题,我也不知道为什么,反正就是解决了. 我修改了连接方式为N ...

  5. discuz迁移到虚拟空间后无法上传图片的问题

    discuz X3迁移到虚拟空间后无法上传图片,提示"附件无法保存": 解决方法: 1.看看虚拟空间的容量是不是满了. 2.登录管理员后台,工具->更新缓存.

  6. vlan后 出现 outlook 正在试图从服务器检索数据

    vlan后 出现 outlook 正在试图从服务器检索数据   cisco vlan outlook 正图试从Microsoft Exchange Server     检索数据. cisco 375 ...

  7. 购买弹性云服务器怎么部署网站,购买后怎么部署自己的云服务器

    购买后怎么部署自己的云服务器 内容精选 换一换 SSL证书对部署的服务器没有任何限制,无论是华为云或其他云厂商的服务器,还是线下云服务器.获取证书文件后,您可根据自己的需求将SSL证书部署到网站对应的 ...

  8. 复旦发布报告!70后度过中年危机?80后珍惜家庭?90后高压期来临?

    近日,复旦发展研究院传播与国家治理研究中心.复旦大学社会治理研究中心联合发布<中国网络社会心态报告(2018)>代际形象篇,形成了热点概念历时性的"网络镜像". 本篇是 ...

  9. 计算机更名无法登陆用友u8,用友T6软件修改了计算机名称后,系统管理提示不能连接服务器-用友T6...

    文章摘要:用友T6软件修改了计算机名称后,系统管理提示不能连接服务器修改了计算机名称后,系统管理提示不能连接服务器 修改了计算机名称后,系统管理提示不能连接服务器原因分析:配置问题,连接数据库的时候, ...

最新文章

  1. Asp.net 的网络打印 – Javascript 控制打印
  2. 更新CentOS Mysql到官方较新版本[以6.5为例]
  3. IDEA创建java文件失败,但是new选项中有java class选项,设置中file and Code Templates中有对应模板
  4. php从入门到精通+视频,PHP从入门到精通2015版(初级)
  5. 内存不能为读写的解决方法
  6. java 同步的方法_关于Java中的同步方法
  7. 网络服务器租赁费用_如何分析租赁季节性和趋势以节省租赁费用
  8. mysql事件创建_mysql 创建事件
  9. .net core下的dotnet全局工具
  10. Python并发编程之多进程(实战)
  11. 晶体管电路设计 上 铃木雅臣 学习体会
  12. ps第二次安装出错解决办法
  13. 用计算机求方差的教案,《用科学计算器计算方差》教案.doc
  14. 筒灯可以执行CAN/ULC-S101测试吗?与BS 476-21区别大吗?
  15. 如何控制舵机的速度?
  16. python判断手机号运营商_js判断手机号运营商的方法
  17. Google MapReduce论文中文版
  18. Linux内核设计与实现 第18章 调试
  19. HACKTHEBOX——Nibbles
  20. 安装VMware和安装Linux

热门文章

  1. python数据模型的意义_Python 数据模型
  2. gan 总结 数据增强_白话GAN及其解决小样本问题的探讨
  3. 0x05.基本算法 - 排序
  4. php制作标记图,PHP使用JPGRAPH制作圆柱图的方法详解
  5. 使用思维导图编写测试用例
  6. 银联配置 linux 路径,深圳银联POS支付系统安装手册(LinuxMySQL).doc
  7. 7 12次c语言上机作业,第十二次C语言上机实验参考答案
  8. controller如何保证当前只有一个线程执行_今天我们来聊一聊 Spring 中的线程安全性...
  9. 第 5 章 Nova - 025 - OpenStack 通用设计思路
  10. zabbix 源码编译安装