本文涉及MongoDB和Elasticsearch两大阵营,可能引起口水之争。仅代表个人经历,不代表阵营。图片来自Pexels。我将重点关注以下两个主题:为什么要从MongoDB迁移到Elasticsearch?如何从MongoDB迁移到Elasticsearch?MongoDB与Elasticsearch热度排名现状背景MongoDB本身的定位是与关系型数据库竞争,但在工作中几乎看不到有哪个项目将核心业务系统的数据放在上面,依然选择传统的关系型数据库。项目背景公司属于物流快递行业,业务系统复杂庞大,用户运营商众多,每天都会产生大量的业务数据,业务数据在流转状态上会有很多变化。为了便于记录跟踪和分析,系统运行日志记录项目应运而生。考虑到原有日均数据量,操作日志数据基于MongoDB存储。操作日志记录系统需要记录两种数据,如下:①变更主数据,谁在什么时候在系统的哪个模块做了什么操作,数据号是多少,操作跟踪号是多少。{"dataId":1,"traceId":"abc","moduleCode":"crm_01","operateTime":"2019-11-1112:12:12","operationId":100,"operationName":"张三","departmentId":1000,"departmentName":"客户部","operationContent":"拜访客户..."}②改从数据,实际改数据前后,这样的数据项很多,如果一行数据的多个字段发生变化,就会记录多条记录。[{"dataId":1,"traceId":"abc","moduleCode":"crm_01","operateTime":"2019-11-1112: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-1112:12:12","operationId":100,"operationName":"张三","departmentId":1000,"departmentName":"客户部","operationContent":"拜访客户","beforeValue":"2019-11-02","afterValue":"2019-11-10","columnName":"lastVisitDate"}]项目结构项目架构描述如下:业务系统新增或编辑数据,生成操作日志记录发送至Kafka集群,并以dataid字段为key,将新增或编辑的数据实际存储到MySQL数据库中.Canal集群订阅MySQL集群,根据业务系统模块配置监控的数据库和表。Canal将监控到的变更业务数据发送到Kafka集群,以dataid字段为key。操作日志系统从Kafka获取主记录数据和从记录数据。运行日志系统向MongoDB写入数据,同时需要反向查询。操作日志业务流程描述MongoDB架构集群架构描述:服务器配置8c/32gb/500gbssd。Router路由服务器部署了3个节点。Config配置服务器部署了3个节点。Shard服务器部署了9个节点。主操作记录设计了三个分片。从操作记录中设计3个分片。问题解释:MongoDB的信徒可能会怀疑我们没有用好它,或者我们的运维能力不够,或者我们有Elasticsearch的高手。不,选择Elasticsearch而不是MongoDB不是技术上的偏见,而是我们的实际场景需求。原因如下:①搜索查询项目背景:MongoDB内部使用B-Tree作为索引结构。该索引基于最左优先的原则。并且必须保证查询顺序与索引字段的顺序一致才能生效。这是优势,但在如今复杂的业务场景下也是致命的。业务系统中查询操作日志记录的过滤条件会有很多,查询条件可以任意组合。现有的MongoDB不支持,或者所有的关系型数据库都不支持。如果要支持,就必须创建很多B+数索引的组合,这种想法很不合理。同时,主记录和从记录中有大量的字符数据。这些数据查询必须支持精确查询和全文搜索。在这些方面,MongoDB功能单一,性能较差。业务系统查询经常超时。相反,Elasticsearch是一个不错的选择。②技术栈成熟度项目背景:分片和副本实现问题,MongoDB集合数据在设计时需要绑定到具体的机器实例,哪些分片分布在哪些节点上,哪些副本分布在哪些节点上。这些都需要在配置集群的时候绑定。分库分表,本质上和传统的关系型数据库是一样的。其实很多数据产品集群还是采用这种模式,比如Redis-cluster、ClickHouse。等待。相比之下,Elasticsearch集群不直接绑定分片和副本,可以任意平衡和调整,节点的性能配置也很容易区分。操作日志数据量快速增长,单日写入量超过千万。运维人员扩容服务器用不了多久,比Elasticsearch复杂多了。单个MongoDB集合中的数据量超过10亿。在这种情况下,即使是简单的条件查询性能也不理想,还不如Elasticsearch倒排索引快。该公司在ES和MongoDB技术栈方面的经验是不同的。Elasticsearch在很多项目中都有使用,非常核心的项目也被广泛使用。MongoDB凭借丰富的技术和运维经验,如果除去核心业务场景,几乎不可能找到合适的切入点。事实上,没有人敢在核心项目中使用MongoDB,非常尴尬。③文件格式相同。MongoDB和Elasticsearch都是文档型数据库。Bson和Json类似,_objectid和_id的原理是一样的。因此,将主数据和从数据迁移到Elasticsearch平台时,几乎不需要改变数据模型。迁移计划异构数据系统的迁移主要围绕两大方面进行:上层应用系统的迁移原本是针对MongoDB的语法规则,现在需要修改为面向Elasticsearch的语法规则。底层MongoDB数据迁移到Elasticsearch。①弹性容量评估原来的MongoDB集群使用了15台服务器,其中9台是数据服务器。迁移到Elastic集群需要多少台服务器?我们采用一种简单的计算方法,比如假设生产环境中的一个MongoDB集合中有10亿条数据,我们先将100万条数据从MongoDB同步到测试环境中的ES中。假设100万条数据占用10G的磁盘,生产环境需要1T的磁盘空间,然后根据业务的预期增长扩展一定的冗余。根据初步评估,Elastic集群有3台服务器配置8c/16g内存/2T机械盘。服务器数量一下子从15台减少到3台,配置也降低了不少。②Elastic索引规则系统的运行日志是时序数据,写入后基本不需要修改。操作日志记录查询主要针对当月,后续历史数据查询频率很低。根据评估,核心数据指标按月创建和生成。业务查询中必须包含操作时间范围,后台根据时间计算需要查询哪一个。指数。Elastic-Api支持多索引匹配查询,完美利用Elastic的特性解决跨月的查询合并。对于非核心数据索引,每年生成一次索引就足够了。Elastic运行日志索引创建规则③核心实现逻辑设计Elasticsearch不是关系型数据库,没有事务机制。操作日志系统的数据源为Kafka,消费数据具有时序机制。有两种场景需要特别注意,如下:主数据先到达操作日志系统,然后数据到达。写入数据时,首先组装主数据记录。和Binlog字段数据。从数据先到达操作日志系统,主数据后到达。主数据更新从索引的相关索引字段。Elasticsearch索引数据的更新是一种近乎实时的刷新机制。数据提交后,无法立即通过Search-Api进行查询。如何将主记录的数据更新到从记录?而且业务部门使用不规范,多条主记录的dataId和tracId很可能是一样的。由于主数据和从数据的关联字段是dataId和traceId。如果主数据和从数据同时到达操作日志系统,那么update_by_query命令一定是无效的,不准确的。主从数据也可能是多对多的关系,dataId和traceId不能唯一确定一条记录。Elasticsearch其实是一个NoSQL数据库,可以做key-value缓存。这个时候新建一个Elasticindex作为中间缓存。原理是主数据和从数据先到达缓存,索引的_id=(dataId+traceId)。通过这个中间索引,可以找到主数据记录的Id或者从记录的Id。索引数据模型大体如下,detailId是从索引的_id的数组记录。{"dataId":1,"traceId":"abc","moduleCode":"crm_01","operationId":100,"operationName":"张三","departmentId":1000,"departmentName":"CustomerDepartment","operationContent":"Visitingcustomers","detailId":[1,2,3,4,5,6]}我们前面说过,主记录和从记录都在一个Kafka分区上。下面来拉一个批处理数据时,操作ES的核心API:#batches_mget中的索引获取记录#批量insertbulk#batches_delete_by_query中删除中间临时索引迁移过程①选择DataX作为数据迁移的数据同步工具,如下因素:历史数据。操作日志记录数据为历史数据,记录生成后几乎不需要二次修改,相当于离线数据。非持续迁移。项目全部完成后,原有的MongoDB集群将被彻底销毁,无需二次迁移。数据量问题。原始的MongoDB操作日志有数十亿条数据。迁移过程不应太快或太慢。如果速度太快,MongoDB集群就会出现性能问题。速度太慢,项目周期太长,会增加运维的成本和复杂度。花费。否则可选择Hadoop作为迁移的过渡平台。针对特定场景的DataX源码改造。比如日期类型转换,索引主键_id生成,索引主键_id映射,支持重复同步。多实例多线程并行。主数据同步部署多实例,从数据同步也部署多实例,单实例配置多个Channel。DataX同步数据图②迁移索引设置临时修改索引的一些设置,待数据同步后再修改回来,如下:"index.number_of_replicas":0,"index.refresh_interval":"30s","index.translog.flush_threshold_size":"1024M""index.translog.durability":"async","index.translog.sync_interval":"5s"③应用迁移操作日志项目使用SpringBoot构建,添加自定义配置项,如如下:#ApplicationWritemongodbflagwriteflag.mongodb:true#Applicationwriteselasticsearchflagwriteflag.elasticsearch:true项目修改说明:第一次上线时,先将两个writeflag设置为true,双写MongoDB和ES。阅读方面,提供了2个不同的接口,前端可以自由切换。当数据迁移完成,没有差异时,再次更改标志的值。应用均衡迁移结论①迁移效果放弃MongoDB,存储数据库采用ElasticSearch。服务器从15个MongoDB改为3个ElasticSearch,每个月为公司节省大量资金。同时,查询性能提升10倍以上,更好地支持各种查询,得到了业务部用户、运维团队和领导的一致好评。②经验总结整个项目前后历时数月,设计、研发、数据迁移、测试、数据验证、压测等环节参与了众多同事。技术方案一步不到位,中间坑了很多,最后还是上马了。ES有很多优秀的技术特性,只有灵活运用才能发挥出最大的威力。作者:李萌简介:Elastic-stack产品深度用户,ES认证工程师,2012年接触Elasticsearch,在Elastic-Stack开发、架构、运维等方面有深入的经验,有实践经验多种Elasticsearch项目,最暴力的大数据分析应用,最复杂的业务系统应用;业余为企业提供Elastic-stack咨询培训和调优实施。编辑:陶佳龙来源:转自微信公众号DBAplus社区(ID:dbaplus)
