关于mongodb:行业案例-MongoDB在腾讯零售优码中的应用

本文次要分享腾讯智慧批发团队优码业务在MongoDB中的利用,采纳腾讯云MongoDB作为主存储服务给业务带来了较大收益,次要包含:高性能、快捷的DDL操作、低存储老本、超大存储容量等收益,极大的升高了业务存储老本,并进步了业务迭代开发效率。

一. 业务场景

腾讯优码从连贯消费者到连贯渠道终端,实现以货的数字化为根底的企业数字化降级,蕴含营销能力降级和动销能力降级。腾讯优码由副品通、门店通和会员通三个子产品组成。


腾讯优码整体视图

1.1 副品通

腾讯优码副品通提供防伪鉴真能力,实现一物一码全流程副品追溯,全链路数据存储至区块链,确保真实可信;更可中转品牌私域,实现流量进一步转化;同时副品通提供微信域内的品牌爱护能力,阻断品牌伪冒网站流传、帮忙消费者辨认混充商品。

产品次要蕴含如下外围个性:

1.2 门店通

腾讯优码门店通是服务品牌方、经销商、业代员以及终端门店四大批发链路外围角色实现基于终端销售门店的销售管理手段降级与销售额晋升。

产品次要蕴含如下外围个性:

1.3 会员通

腾讯优码会员通是面向批发品牌商提供的SaaS+定制化服务的产品,以扫码为切入点,连接线上线下场景。提供丰盛的扫码/互动流动模型、流动评估体系助力品牌连贯消费者。

产品次要蕴含如下外围个性:

二.码存储选型

腾讯智慧批发优码业务存储批发商品二维码信息,该信息为智慧批发最外围的数据信息,提供“从连贯消费者到连贯渠道终端,实现以货的数字化为根底的企业数字化降级”相干服务。因而码数据存储问题是我的项目最外围的问题。

2.1 需要和计划

要解决码存储问题,首先须要剖析码存储的特色。通过剖析码存储问题的次要特色是:

海量数据:腾讯优码做的商品二维码,随着越来越多的商品应用腾讯优码业务,二维码数据开始出现指数级增长。

关联存储:码与码之间存在1:1和1:N:N的关联关系,须要存储这种关系,并且提供相应的关联查问。

多维度查问:针对不同的利用场景须要提供不同维度的条件查问。

在获取到码存储特色之后,通过多方调研和排查之后,初步选取了2种存储计划:

  1. MySQL + ES:MySQL 分库分表存储码元数据,提供须要高性能的读写场景;而后依据需要将局部数据同步 ES 以应答各种简单的查问场景。
  2. MongoDB:MongoDB 是全球排名最高的分布式NoSQL数据库,其外围个性是 No Schema、高可用和分布式,非常适合分布式存储。

2.2 计划剖析

2.2.1 MySQL + ES计划剖析

MySQL + ES 是一个比拟常见的存储解决方案,并且在很多畛域内被广泛应用,如会员或商品信息贮存畛域。此计划的劣势是可能提供十分多的查问形式和不同的性能保障,能够应答各种各样简单的业务查问需要。

MySQL + ES 的常见架构是写操作间接作用于MySQL,而后通过 canal + Kafka 的形式将数据变更同步到ES,而后再依据不同的查问场景从MySQL或者ES查问数据。下图是在腾讯优码业务场景下可能的架构图:

从架构图能够看出,本计划存在几个问题:

数据同步和一致性问题:这个问题在数据量不大的状况下不会有影响。然而如果数据量百亿甚至千亿时就是一个十分重大的问题。

数据容量问题:个别状况下 MySql 的单表数据最好维持在百万级一下,如果单表数据量过大之后读写都是个问题。那么如果要存储千亿数据就要几千上万张表,如此多的分表须要业务本人保护时开发运维都是简直不可行的。

老本问题:数据冗余存储,会减少额定的存储老本。同时ES 为了保证数据可靠性和查问性能,须要更多的机器和内存。而且 ES 存在数据收缩问题,对于同样的数据,须要相当MySql来说更大的磁盘。

DDL运维问题:MySql 在分库散布之后,因为DDL语句须要操作大量的库表,因而十分耗时,同时也容易出错。依据咱们以前的我的项目教训来说,当有几百张表,单表几十万数据时,一个简略的减少字段的DDL语句也须要1小时甚至更久能力实现。

开发成本问题:此计划须要业务本人保护分库分表、数据同步和依据需要选取不同的查问引擎。不仅整个架构简单,同时在做业务需要时须要慎重考虑,稍不留神应用错的存储引擎就可能导致性能问题。

程度扩容问题:MySql 分库分表要扩容须要业务手动 rehash 搬迁数据,老本十分高,而且很难解决扩容过程中的数据读写问题。

2.2.2 MongoDB 计划剖析

MongoDB 是十分闻名的分布式存储引擎,具备 No Schema、高可用、分布式、数据压缩等多方面的劣势。尽管MongoDB 是NoSQL 存储引擎,然而其 Wired Tiger 存储引擎和innerdb 一样底层应用的是B+树,因而MongoDB 在提供分布式存储的前提下同时可能提供大部分MySql 反对的查问形式。因而,在应用 MongoDB 时,咱们不须要MySql冗余表或者 ES 来反对大部分的分布式查问。在腾讯优码的利用场景下,基于MongoDB 的存储架构如下图所示:

从图中能够看出,MongoDB能够防止冗余存储带来的数据同步和一致性问题、存储老本问题、资源/运维/开发成本。而且在进一步测试和剖析MongoDB的性能和性能之后,咱们发现MongoDB还具备如下劣势:

无DDL问题:因为MongoDB 是No Schema 的,因而能够防止MySql的DDL问题。

数据主动平均:MongoDB 有主动rebalance 性能,能够在数据分布不平均的时候,主动搬迁数据,保障各个分片间的负载平均。

更低的老本:MongoDB 自带数据压缩,在等同数据下,MongoDB 需要的磁盘更少。

更高的性能:MongoDB 最大化的利用了内存,在大部分场景下领有靠近内存数据库的性能。通过测试MongoDB的单分片读性能约为3万QPS。

更多的读写形式:尽管MongoDB没有ES的倒排索引,其反对的查问形式略逊于ES。然而,MongoDB在领有大部分ES的查问能力的同时,其性能远高与ES;而且绝对MySql 来说MongoDB 的字段类型反对内嵌对象和数组对象,因而能满足跟多的读写需要。

2.3 计划比照

通过后面的剖析,咱们初步判断MongoDB领有更好的体现。因而为了进一步确定MongoDB的劣势,咱们深刻比照了MySQL + ES 与MongoDB在各方面的体现。

2.3.1 存储老本比照

MongoDB 在存储上的劣势次要体现在两个方面:数据压缩和无冗余存储。

为了更加直观的看出磁盘应用状况,咱们模仿了在腾讯优码业务场景下,MySQL + ES和MongoDB下的理论存储状况。

一方面,在MySQL+ES的计划下,为了满足需要咱们须要将冗余一份ES数据和MySQL的冗余表。其中码的外围数据存储在MySQL中,其磁盘总量仅占总的38.1%。后面说过 MongoDB的计划是不须要冗余存储的,因而应用MongoDB能够缩小这61.9%的总数据容量。

另一方面,通过测试同样的码数据,MongoDB snappy压缩算法的压缩率约3倍,zlib 压缩算法的压缩率约6倍。因而,尽管业务为了保证系统的稳定性而抉择 snappy 压缩算法,但MongoDB 依然只须要 MySQL 三分之一的磁盘耗费。

2.3.2 开发运维老本

无数据同步链路:应用MongoDB不须要数据同步,因而就不须要保护canal服务和kafka队列,大大减少开发和运维难度。

人力老本收益:在MySQL+ES架构下每次对MySQL集群做增加字段变更,都需运维 肯定的人日投入,并且存在业务抖动危险,同时影响业务迭代公布进度,迭代公布耗时且危险大。

开发保护老本:MongoDB存储架构简略,一份存储,无数据一致性压力。

动静扩容:MongoDB 反对随时动静扩容,根本不存在容量下限问题,而MySQL在扩容时须要业务手动rehash变迁数据,并本人保证数据一致性和完整性。

2.3.3 性能比照

通过压测,同样的4C8G的机器配置下,MySQL和MongoDB在大数据量下写性能基本一致。MySQL的读性单分片约6000QPS左右,ES的性能只有800QPS左右。而 MongoDB 单分片地读性能在3万QPS左右,远高于MySQL和 ES 的性能。

2.3.4 总结

通过下面的剖析和比照之后,能够显著看出 MongoDB 在各方面都有劣势。为了更加直观的看出不同计划的差别,这里列出了从性能、性能、老本、可扩展性和可维护性等5个方面的比照数据:

综上所述,MongoDB 不仅能齐全满足业务需要,同时在性能、老本、可维护性等各方面都优于其它两种计划,因而腾讯优码最终选用的是MongoDB 作为业务外围数据码的存储计划。

三.MongoDB分片集群优化过程

批发优码业务对老本要求较高、数据量较大,线上实在读写流量不是太高(读3W QPS要求),因而采纳低规格4C8G规格(单节点规格)分片模式集群部署。

3.1 分片集群片建抉择+预分片

批发优码数据查问都是通过码id查问,因而抉择码id作为片建,这样能够最大化查问性能,索引查问都能够通过同一个分片获取数据。此外,为了防止分片间数据不平衡引起的moveChunk操作,因而抉择hashed分片形式,同时提前进行预分片,MongoDB默认反对hashed预分片,以优码详情表为例,预分片形式如下:

use db_code_xx  
sh.enableSharding("db_code_xx")  
//n为理论分片数  
sh.shardCollection("db_code_xx.t_code_xx", {"id": "hashed"}, false,{numInitialChunks:8192*n}) 

3.2 低峰期滑动窗口设置

因为MongoDB实例节点规格低(4C8G),当分片间chunks数据不平衡的状况下,会触发主动balance平衡,因为实例规格低,balance过程存在如下问题:

CPU耗费过高,迁徙过程甚至耗费90%左右CPU

业务拜访抖动,耗时减少

慢日志减少

异样告警增多

以上问题都是因为balance过程进行moveChunk数据搬迁过程引起,为了疾速实现数据从一个分片迁徙到另一个分片,MongoDB外部会不停的把数据从一个分片移动到另一个分片,这时候就会耗费大量CPU,从而引起业务抖动。

MongoDB内核也思考到了balance过程对业务有肯定影响,因而默认反对了balance窗口设置,这样就能够把balance过程和业务高峰期进行错峰,这样来最大化躲避数据迁徙引起的业务抖动。例如设置凌晨0-6点低峰期进行balance窗口设置,对应命令如下:

use config  
db.settings.update({"_id":"balancer"},{"$set":{"activeWindow":{"start":"00:00","stop":"06:00"}}},true) 

3.3 写多数派优化

因为优码二维码数据十分外围,为了防止极其状况下的数据失落和数据回归等危险,因而客户端采纳writeConcern={w: “majority”}配置,确保数据写入到正本集大多数成员后才向客户端发送确认。

链式复制的概念:假如节点A(primary)、B节点(secondary)、C节点(secondary),如果B节点从A节点同步数据,C节点从B节点同步数据,这样A->B->C之间就造成了一个链式的同步构造,如下图所示:

MongoDB多节点正本集能够反对链式复制,能够通过如下命令获取以后正本集是否反对链式复制:

cmgo-xx:SECONDARY> rs.conf().settings.chainingAllowed  
true  
cmgo-xx:SECONDARY>   

此外,能够通过查看正本集中每个节点的同步源来判断以后正本集节点中是否存在有链式复制状况,如果同步源为secondary从节点,则阐明正本集中存在链式复制,具体查看如下正本集参数:

cmgo-xx:SECONDARY> rs.status().syncSourceHost  
xx.xx.xx.xx:7021  
cmgo-xx:SECONDARY> 

因为业务配置为写多数派,鉴于性能思考能够敞开链式复制性能,MongoDB能够通过如下命令操作进行敞开:

cfg = rs.config()  
cfg.settings.chainingAllowed = false
rs.reconfig(cfg)  

链式复制益处:能够大大加重主节点同步oplog的压力。

链式复制有余:当写策略为majority时,写申请的耗时变大。

基于写性能思考,当业务采纳“写大多数”策略时,间接敞开链式复制性能,确保写链路过长引起的写性能降落。

对于作者:
CSIG腾讯优码团队、腾讯MongoDB团队

社区招募

为了让社区组委会成员和志愿者敌人们灵便参加,同时咱们为想要深度参加社区建设的搭档们开设了“招募通道”,如果您想要在社区外面结交气味相投的技术搭档,想要通过在社区积淀有价值的干货内容,想要一个展现本人的舞台,晋升本身的技术影响力,即刻退出社区奉献队伍~ 点击链接提交申请:
http://mongoingmongoing.mikec…

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据