生产事故(MongoDB数据分布不均解决方案)

2024-06-07 18:58

本文主要是介绍生产事故(MongoDB数据分布不均解决方案),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

事故集合:

可以很明显可以看到我们这个集合的数据严重分布不均匀。

一共有8个分片,面对这个情况我首先想到的是手动拆分数据块,但这不是解决此问题的根本办法。

    造成此次生产事故的首要原因就是片键选择上的问题,由于片键选择失误,在数据量级不大的时候数据看起来还是很健康的,但随着数据量的暴涨,问题就慢慢浮出了水面,我们使用的组合片键并不是无规律的,片键内容是线性增长的,这就导致了数据的不正常聚集。由于数据分布不均匀,我们有两个分片的磁盘使用率接近80%,数据还在持续增长,这个问题必须尽快解决。

涉及到此次事故的集合一共有三个,总数据量加起来接近30T,数据总量300亿左右。

下面是我解决此问题的解决方案:

方案一:

第一步:创建一个新的分片表,片键我选择_id做hashed分片,并提前分好了数据块,降低在恢复期间频繁切割数据造成的服务器压力。

sh.shardCollection("loan_his.collection",{_id:"hashed"},false,{numInitialChunks:1024})

第二步:单独连接各个分片将8个分片的数据全量备份:

nohup mongodump -u loan_his -p loan_his --authenticationDatabase loan_his  -h ${replset} --db loan_his --collection ${collectionName} --query '{"txdt": { $lte: "2019-07-09"} }' -o ${bak_dir} &>>  ${log} &

你可能会问为什么不连接mongos,因为我在连接mongos做数据备份时出现了以下异常:

2019-07-08T16:10:03.886+0800	Failed: error writing data for collection `loan_his.ods_cus_trad` to disk: error reading collection: operation was interrupted

可能是因为集合内的数据坏块吧,此异常信息是我备份了将近70%的数据后突然抛出的异常信息。

除了这个原因,单独备份各个分片的数据后你能够自由控制恢复数据的时间窗口,不会因为恢复单个数据文件时间较长,突发意外情况导致恢复中断从头再来的窘境。能够根据服务器的状态避开高峰期来进行数据恢复。

备份期间我发现了有时候备份出来的总文档数和 db.collection.getShardDistribution() 查看的文档数不一致,我还以为是备份期间出了问题,但我删除当前备份文件后重新备份出来的文档数还是和之前一样。目前不知道是怎么回事,怀疑是坏的数据块引发的我问题,备份出来的数据一般会比原数据量多几万条数据,有时候会少一些。

第三步:恢复数据:

 mongorestore -u loan_his -p loan_his --authenticationDatabase loan_his -h 10.0.156.9:27017 --db loan_his  --collection  ${collectionName_two}  /mongodb/${collectionName}/replset_sh2/loan_his/${collectionName}.bson  &>>  ${log}

在恢复数据前千万要记得不要创建索引!否则性能极差,速度非常非常慢!在使用mongodump工具备份时,在数据文件的同级目录下会有一个 XXXXX.metadata.json 索引文件,默认会在数据恢复完毕后执行创建索引的操作。

此处有坑需要注意:因为备份出来的数据是由原表备份出来的,那这个索引文件也是原表的索引,由于原表我使用的是组合片键做的分片,所以在原表内会存在一个由片键组成的组合索引,并且不是后台创建的组合索引!!!这意味着如果你使用此索引文件来给新表创建索引,会造成这个集群处于阻塞状态,无法响应任何操作!!直至索引创建完毕。所以你可以将这个索引文件备份到其它目录以作参考,然后将原文件删除就可以了,恢复数据时不会有其它的问题。

如果恢复期间出现了意外情况导致恢复失败,比如节点宕机什么的,不需要担心,重新执行恢复程序,数据文件不会重复增加,因为备份出来的数据文件包含mongodb自带的 Objectld对象_id ,导入时,如果已存在此ID,将不会插入数据。注意:在不同集合是允许出现相同ID的,所以在使用方案二恢复数据时,新产生的数据不能通过新表A备份出来汇入新表C,需要通过原始数据文件重新导入。

第四步:创建索引:

待所有数据恢复完毕后再创建索引,一定要记得后台创建!!!"background":true !!!你也可以将索引拆分,一个一个的来。如果觉得此操作对业务影响较大,请看本文最后的解决方案。

mongo 10.0.156.2:27017/loan_his -uloan_his -ploan_his -eval 'db.getSiblingDB("loan_his").runCommand({createIndexes: "collection",indexes: [{"v":2,"key":{"_id":1},"name":"_id_","ns":"loan_his.collection"},{"v":2,"key":{"opnode":1.0,"txdt":1.0,"acct":1.0,"crdno":1.0},"name":"opnode_1_txdt_1_acct_1_crdno_1","ns":"loan_his.collection","background":true},{"v":2,"key":{"txdt":1.0,"opnode":1.0,"acct":1.0,"crdno":1.0,"pbknum":1.0},"name":"txdt_1_opnode_1_acct_1_crdno_1_pbknum_1","ns":"loan_his.collection","background":true},{"v":2,"key":{"acct":1.0,"txdt":1.0,"opnode":1.0},"name":"acct_1_txdt_1_opnode_1","ns":"loan_his.collection","background":true},{"v":2,"key":{"crdno":1.0,"txdt":1.0,"opnode":1.0},"name":"crdno_1_txdt_1_opnode_1","ns":"loan_his.collection","background":true},{"v":2,"key":{"pbknum":1.0,"txdt":1.0,"opnode":1.0},"name":"pbknum_1_txdt_1_opnode_1","ns":"loan_his.collection","background":true}]})'

停止失控索引:

一旦你触发一个索引,简单的重启服务并不能解决这个问题,因为MongoDB会继续重启前的建索引的工作。如果之前你运行后台建索引任务,在服务重启后它会变成前台运行的任务。在这种情况下,重启会让问题变得更糟糕。MongoDB提供了选项“noIndexBuildRetry”,它会指示MongoDB重启后不再继续没建完的索引。如果不小心在前台创建了索引导致集群不可用,可以使用--noIndexBuildRetry 参数重启各个分片来停止索引的创建过程,只用重启主节点就可以了。如果是在后台创建索引,重启时记得加上--noIndexBuildRetry,否则重启后创建索引的线程会重新被唤醒,并由后台创建变为前台创建,导致整个集群不可用。

mongod -f $CONFIGFILE --noIndexBuildRetry

此方案迁移期间不用通知业务系统做变更,把数据迁移完毕后,通知业务系统将表名变更,弊端就是在你迁移的过程中数据还是会持续增长的,问题分片的磁盘容量会越来越少。

方案二:

为了避免在迁移期间数据仍在增长,导致数据还没迁移完毕磁盘就爆满的情况,可以选择停止往旧表B内写入数据,创建一个健康的新表A,新的数据往新表A内写,具体的查询方案需要应用系统的配合。然后将旧表B的数据迁移至新表C中,最终将新表A的数据汇入新表C , 完成数据迁移。此次迁移数据耗时共9个月!!!片键一定要慎重选择,因为我们使用的MongoDB是3.4.7版本的,不支持修改片键,最新版本支持片键的修改。

接下来介绍数据量较大时如何构建索引--减少业务最少影响

在数据量较大或请求量较大,直接建立索引对性能有显著影响时,可以利用复制集(数据量较大时一般为线上环境,使用复制集为必然选择或者使用分片.)中部分机器宕机不影响复制集工作的特性,继而建立索引。

(1)首先把 secondary server 停止,再注释 --replSet 参数,并且更改 MongoDB port 之后重新启动 MongoDB,这时候 MongoDB 将进入 standalone 模式;

(2).在 standalone 模式下运行命令 ensureIndex 建立索引,使用 foreground 方式运行也可以,建议使用background方式运行;

(3)建立索引完毕之后关闭 secondary server 按正常方式启动;

4.根据上述 1~3 的步骤轮流为 secondary 建立索引,最后把 primary server 临时转换为 secondary server,同样按 1~3 的方法建立索引,再把其转换为 primary server。

日志内容大致如下:

2019-09-24T18:51:39.003+0800 I -        [conn33]   Index Build: 838416900/876543270 95%
2019-09-24T20:10:08.360+0800 I INDEX    [conn33] 	 done building bottom layer, going to commit
2019-09-24T20:10:26.001+0800 I -        [conn33]   Index: (2/3) BTree Bottom Up Progress: 11684400/876543270 1%
done building bottom layer, going to commit

 

 

这篇关于生产事故(MongoDB数据分布不均解决方案)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1040016

相关文章

宝塔安装的MySQL无法连接的情况及解决方案

《宝塔安装的MySQL无法连接的情况及解决方案》宝塔面板是一款流行的服务器管理工具,其中集成的MySQL数据库有时会出现连接问题,本文详细介绍两种最常见的MySQL连接错误:“1130-Hostisn... 目录一、错误 1130:Host ‘xxx.xxx.xxx.xxx’ is not allowed

redis在spring boot中异常退出的问题解决方案

《redis在springboot中异常退出的问题解决方案》:本文主要介绍redis在springboot中异常退出的问题解决方案,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴... 目录问题:解决 问题根源️ 解决方案1. 异步处理 + 提前ACK(关键步骤)2. 调整Redis消费者组

springboot项目redis缓存异常实战案例详解(提供解决方案)

《springboot项目redis缓存异常实战案例详解(提供解决方案)》redis基本上是高并发场景上会用到的一个高性能的key-value数据库,属于nosql类型,一般用作于缓存,一般是结合数据... 目录缓存异常实践案例缓存穿透问题缓存击穿问题(其中也解决了穿透问题)完整代码缓存异常实践案例Red

使用@Cacheable注解Redis时Redis宕机或其他原因连不上继续调用原方法的解决方案

《使用@Cacheable注解Redis时Redis宕机或其他原因连不上继续调用原方法的解决方案》在SpringBoot应用中,我们经常使用​​@Cacheable​​注解来缓存数据,以提高应用的性能... 目录@Cacheable注解Redis时,Redis宕机或其他原因连不上,继续调用原方法的解决方案1

基于MongoDB实现文件的分布式存储

《基于MongoDB实现文件的分布式存储》分布式文件存储的方案有很多,今天分享一个基于mongodb数据库来实现文件的存储,mongodb支持分布式部署,以此来实现文件的分布式存储,需要的朋友可以参考... 目录一、引言二、GridFS 原理剖析三、Spring Boot 集成 GridFS3.1 添加依赖

Python报错ModuleNotFoundError的10种解决方案

《Python报错ModuleNotFoundError的10种解决方案》在Python开发中,ModuleNotFoundError是最常见的运行时错误之一,通常由模块路径配置错误、依赖缺失或命名冲... 目录一、常见错误场景与原因分析二、10种解决方案与代码示例1. 检查并安装缺失模块2. 动态添加模块

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

Nginx部署React项目时重定向循环问题的解决方案

《Nginx部署React项目时重定向循环问题的解决方案》Nginx在处理React项目请求时出现重定向循环,通常是由于`try_files`配置错误或`root`路径配置不当导致的,本文给大家详细介... 目录问题原因1. try_files 配置错误2. root 路径错误解决方法1. 检查 try_f

MySQL索引失效问题及解决方案

《MySQL索引失效问题及解决方案》:本文主要介绍MySQL索引失效问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录mysql索引失效一、概要二、常见的导致MpythonySQL索引失效的原因三、如何诊断MySQL索引失效四、如何解决MySQL索引失

Redis中的数据一致性问题以及解决方案

《Redis中的数据一致性问题以及解决方案》:本文主要介绍Redis中的数据一致性问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Redis 数据一致性问题的产生1. 单节点环境的一致性问题2. 网络分区和宕机3. 并发写入导致的脏数据4. 持