01
一切的开始
但是事实说明了一切。这个用户的MongoDB集群从2015年上线以来,到2020年的今天,已经运行了5年时间。承载了每天的数据汇聚和数据同步(到检索服务),平均每8小时就能消耗完一次oplog size的上限(Upper Bound ≈ 50GB)。接下来就是我们近几年使用MongoDB的案例、发生的花絮和对未来的思考。
02
应用和拓展
NoSQL的第一站
我们第一次使用MongoDB就发生在刚才的那个案例中。不过刚开始我只会简单使用,并不了解多少原理。直到花絮章节的「魔鬼到来!」,我才意识到即使有好的技术,如果连基本原理都不清楚,那出了问题也只会两眼一抹黑。第二年,也就是2016,市面上关于MongoDB的技术参考书籍屈指可数,《MongoDB权威指南 第二版》也已经过去了3年。为了用好MongoDB,我也坚持看完了这本砖头厚度一般的经典之作,随后的时间基本聚焦在docs.mongodb.com英文资料,这样就逐步了解了MongoDB。机缘巧合,团队中之前负责这块的老同志转互联网公司了,数据库的运维工作就来到了我这边。在Leader的支持下,我开始对应用进行大量优化、定期对实例进行维护、监控和分析集群的各项性能指标…甚至,在官方的mongo charts还没有出来之前,我们自己基于官方驱动做了一个简易版的Web控制台,从此运维工作轻松能完成,基本和Shell手写指令Say Goodbye。
这个集群目前仍运行中,最近一次较大的运维工作发生在2019年5月,从v3.2连续升级到3.6。是为了使用Change Streams特性,为随后需要的跨地域的副本集和实时同步(到其他数据源)做基础。不过3.6除了Change Streams极具吸引力外,还有很多新的feature让老用户看的心动,如可重试写入、增加Causal Consistency的可调一致性、Compass社区免费版等,所以让我们坚定升级到3.6。
MongoDB的官网文档非常强大,用一句话介绍就是只要你肯花时间去阅读和理解它,再勤加练习,肯定能成为一名合格的MongoDB DBA。在这个章节的最后,我也附加了一个副本集版本升级实操,分享如何利用官方docs在不停服下滚动升级实例版本。
全面适应容器化
2017年,业务需要,我们原有的集群需要在异地复制一套,而且必须和其他集群保持隔离。项目工期非常短,所有的应用服务地部署和数据初始化工作也要求在极短几天时间内完成。面对这种持续集成交付和弹性应用部署,我们开始引进Docker容器技术。当时Kubernetes没有这么火,容器编排还是Swarm。但是Swarm在使用的时候有很多限制性条件,所以我们自己使用shell自动化脚本管理容器的生命周期。
MongoDB部署之前,我们也思考了既然要发挥docker的弹性能力,避免过多的人工指令,于是设计了一些实例管理脚本,包括Dockerfile和下面的一段巧妙的集群初始化代码。将这个代码封装在init.js文件中,然后和上层的shell脚本关联起来就能够轻松实现MongoDB副本集的所有初始化工作。
cfg = {
_id: 'rs',
members: [
{
_id: 0,
host: 'c1.luoc.com:27027'
},
{
_id: 1,
host: 'c1.luoc.com:27027'
},
{
_id: 2,
host: 'c1.luoc.com:27027'
}
]
};
rs.initiate(cfg);
while(db.isMaster().ismaster == false) { }
db = db.getSiblingDB('admin');
db.createUser({user:"admin", pwd:"0000", roles:["root"]});
db.createUser({user:"users", pwd:"0000", roles:["userAdminAnyDatabase"]});
db = db.getSiblingDB('test');
db.createUser({user:"test", pwd:"0000", roles:["dbOwner"]});
db.test.insert({key:"hello", value:"world"});
linux shell
mongo --quiet init.js
应对海量元数据
2017下半年,我们引入了Hadoop技术栈,深入到更丰富的大数据生态。但是我们在做一个方案的时候卡壳了,如何低成本在一种存储技术中存储海量文件?
第一个方案要求在Hadoop技术栈之外,再引入一种新存储技术,架构复杂度太高。并且我们团队中对Ceph之类的技术驾驭并没有充分的信心。我们的目标是存储小到几KB大到上GB的文件对象,所以从性价比上考虑第二个也没有被采用。通过已经掌握的MongoDB和HDFS技术,我们设计了一个优化方案。以下是核心流程
整体思路就是选择MongoDB存储用户上传文件的元数据,即满足了元数据管理的合规要求,也利用了HDFS的分布式文件存储能力,还消除了HDFS NameNode面对海量小文件的内存膨胀问题。对于我们团队来说,运用已经掌握的技术解决新问题,比再引进一种新存储技术带来的运维成本要低很多。
该方案也已经在生产环境中运行了近2年时间,随着元数据的增长,未来是能够很轻松通过增加MongoDB实例进行水平扩展。
版本升级
mongodb-linux-x86_64-rhel62-3.4.20.tgz
mongodb-linux-x86_64-rhel62-3.6.12.tgz
mongostat
命令行评估集群节点压力,在读写压力小的时间段做升级更合适。mongo
命令行登录到admin数据库并执行以下命令。
# 滚动日志 db.runCommand({ logRotate: 1 }) # 在Primary上锁定写操作和flush内存数据到磁盘 db.fsyncLock();cp -R
拷贝数据文件进行备份。mongo
命令行设置优先Primary。
cfg = rs.conf() cfg.members[0].priority = 1 cfg.members[1].priority = 0.5 cfg.members[2].priority = 0.5 rs.reconfig(cfg)(n/2) + 1
个节点在线)。
# 关闭数据库 db.shutdownServer(); # 替换bin目录的可执行文件 cp /opt/mongodb-linux-x86_64-rhel62-3.4.20/bin/* bin/ # 重启mongod实例(startup.sh是自定义脚本) ./startup.shdb.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } ) ```
5
、6
、7
步骤再从v3.4升级到3.6即完成。_id
没有采用默认ObjectId
的超大数据集合。touch
命令可以将磁盘上的数据文件预热到内存。但是仅适用于MMAPv1
存储引擎,不支持WiredTiger
。WiredTiger
,那怎么预热?
3.2 > 3.4
过程中需要将配置文件中废弃的参数移除才能启动mongod实例,如:nohttpinterface
3.4 > 3.6
过程中需要在启动指令中加入--bind_ip
参数。db.stepDown()
命令有哪些注意事项?priority
规则重新发起选主。db.stepDown(600)
db.version()
确认实例版本。rs.status()
确认集群节点状态正常。
db.fsyncLock()
作用是什么?不需要解锁吗?db.fsyncUnlock()
。
mongodump
方式来备份数据?mongodump
不适合超大数据库或_id
没有采用默认ObjectId
的超大数据集合。
db.shutdownServer()
执行后无响应?kill -2 <pid>
再尝试关闭mongod实例,如果仍然无效,请评估风险后自行使用kill -9
。
kill -9 <pid>
的风险是什么?journal
,否则可能造成数据丢失。kill -9
不应该在生产环境任何一种数据库中使用。
03
花絮
魔鬼到来!
2016年集群上线不久,发生了一次严重事故,一个晚上丢失了几百万条数据。随后团队紧急会议、分析和处理事故、最后线索断了… oplog全部被delete操作指令集覆盖,问题的原因当时没有立刻分析出来。但是我猜测可能是我们使用GUI误操作导致整个集合的数据被遍历删除。如果说前几天成功复飞的长征5号"胖五"在2017年的那次失利的问题被航天队伍称为"魔鬼",那这次事故对于我们团队来说也是一次"魔鬼"到来。因为很难复现,所以大家认为不应该出现这种情况。
3个月后,在基本掌握MongoDB的原理后,我多次模拟事故变量,终于复现了之前发生的一切。
db.coll.remove({x})
语法,但是x值在上下文不能保证非null,即remove(null),这是遍历删除集合中的所有数据!并没有魔鬼,只是我们没有做好克服这份恐惧的准备。
架构师的征程
在以前学习MongoDB原理过程中,我借助对书本的阅读和官方文档的理解,彻底改变了对知识获取方式的认识。并不一定要使用最新的书籍或源代码才能掌握不过时的技术,知识其实是不分新和旧,只要我们一直保持着一颗敬畏之心。比如,NoSQL中BASE和CAP理论已经出来了很长时间,只是在Hbase/MongoDB/Cassandra这种技术普及后才被更多人了解。但是不论你认不认识它,它都在,当你认真去对待它的时候,你才会认为这些是新的事物。更多的像SQL on Hadoop,没有接触Hadoop技术栈的人可能都会认为此SQL非彼SQL,和RDBMS中的不一样。其实并非如此,新瓶装旧酒,还是那些SQL,底层实现换成了并行处理,只是对于开发者透明。SQL技术中的核心流程:语法检查 > 语义检查 > 优化器 > 执行器等一个都不会缺。
2015到2020年,刚好5年,我从一个菜鸟到能够给大数据产品做些架构设计,基本完成了初步目标。接下来就是收拾心情,继续前行!
04
未来
RDBMS,NoSQL,NewSQL
如果我们经常关注db-engines.com排行榜,就会发现RDBMS阵营已经开始向多模型数据库的趋势发展,加入Document Store(部分有License限制)。NoSQL系列中的MongoDB也通过加入分布式事务来进一步增强对开发者的吸引力。还有像TiDB这种新型的NewSQL,未来给用户的选择依然有很多。如果你想入门分布式数据库,推荐从MongoDB这种开箱即用、对开发者友好的技术开始,再去深入研究分布式原理,你将会事半功倍!
连接Hadoop
如果要设计一个新的数据中心架构,去IOE化,你的方案会是什么?以下灼见
作者:罗聪
长城软件大数据实验室,1Data产品负责人。
本文分享自 Mongoing中文社区 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!