MongoDB请求出战!助力腾讯零售优码降本增效
本文主要分享腾讯智慧零售团队优码业务在MongoDB中的应用,采用腾讯云MongoDB作为主存储服务给业务带来了较大收益,主要包括:高性能、快捷的DDL操作、低存储成本、超大存储容量等收益,极大的降低了业务存储成本,并提高了业务迭代开发效率。
一、业务场景
更多信息可以访问腾讯优码官方网站获得:
1.1 正品通
1.2 门店通
1.3 会员通
二、码存储选型
2.1 需求和方案
海量数据:腾讯优码做的商品二维码,随着越来越多的商品使用腾讯优码业务,二维码数据开始呈现指数级增长。
关联存储:码与码之间存在1:1和1:N:N的关联关系,需要存储这种关系,并且提供相应的关联查询。
多维度查询:针对不同的应用场景需要提供不同维度的条件查询。
数据同步和一致性问题:这个问题在数据量不大的情况下不会有影响。但是如果数据量百亿甚至千亿时就是一个非常严重的问题。
数据容量问题:一般情况下 MySql 的单表数据最好维持在百万级一下,如果单表数据量过大之后读写都是个问题。那么如果要存储千亿数据就要几千上万张表,如此多的分表需要业务自己维护时开发运维都是几乎不可行的。
成本问题:数据冗余存储,会增加额外的存储成本。同时ES 为了保证数据可靠性和查询性能,需要更多的机器和内存。而且 ES 存在数据膨胀问题,对于同样的数据,需要相当MySql来说更大的磁盘。
DDL运维问题:MySql 在分库分布之后,因为DDL语句需要操作大量的库表,因此非常耗时,同时也容易出错。根据我们以前的项目经验来说,当有几百张表,单表几十万数据时,一个简单的增加字段的DDL语句也需要1小时甚至更久才能完成。
开发成本问题:此方案需要业务自己维护分库分表、数据同步和根据需求选取不同的查询引擎。不仅整个架构复杂,同时在做业务需求时需要慎重考虑,稍不注意使用错的存储引擎就可能导致性能问题。
水平扩容问题:MySql 分库分表要扩容需要业务手动 rehash 搬迁数据,成本非常高,而且很难处理扩容过程中的数据读写问题。
无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不需要数据同步,因此就不需要维护canal服务和kafka队列,大大减少开发和运维难度。
人力成本收益:在MySQL+ES架构下每次对MySQL集群做添加字段变更,都需运维 一定的人日投入,并且存在业务抖动风险,同时影响业务迭代发布进度,迭代发布耗时且风险大。
开发维护成本:MongoDB存储架构简单,一份存储,无数据一致性压力。
动态扩容:MongoDB 支持随时动态扩容,基本不存在容量上限问题,而MySQL在扩容时需要业务手动rehash变迁数据,并自己保证数据一致性和完整性。
2.3.3 性能对比
三、MongoDB分片
集群优化过程
3.1 分片集群片建选择+预分片
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 低峰期滑动窗口设置
CPU消耗过高,迁移过程甚至消耗90%左右CPU
业务访问抖动,耗时增加
慢日志增加
异常告警增多
use config
db.settings.update({"_id":"balancer"},{"$set":{"activeWindow":{"start":"00:00","stop":"06:00"}}},true)
3.3 写多数派优化
cmgo-xx:SECONDARY> rs.conf().settings.chainingAllowed
true
cmgo-xx:SECONDARY>
cmgo-xx:SECONDARY> rs.status().syncSourceHost
xx.xx.xx.xx:7021
cmgo-xx:SECONDARY>
cfg = rs.config()
cfg.settings.chainingAllowed = false
rs.reconfig(cfg)
关于作者
﹀
﹀
﹀
云上MongoDB常见索引问题及最优索引规则大全
腾讯云与MongoDB达成战略合作,为全球用户提供最新MongoDB服务
↓↓点击阅读原文,了解更多优惠