MongoDB数据库(10亿条数据)清理策略: 自动化过期数据删除实战

1、引言

随着应用程序和业务数据的持续增长,有效地管理数据库存储空间成为维护系统性能的关键。在MongoDB这类NoSQL数据库中,定期清理过期数据变得尤为重要,这不仅能释放宝贵的存储资源,还能优化查询性能,确保数据库运行的高效与稳定。
本文将深入探讨一种自动化清理MongoDB中过期数据的策略,并通过一个实际的Python脚本示例,展示如何实现这一功能。

2、需求背景

根据公司业务发展积累,在众多应用场景中,如日志记录、临时缓存、会话管理等,数据往往具有时效性,超过一定时间后便不再有用。如果不及时清理,这些过期数据会占用大量存储空间,增加数据库维护成本,甚至影响查询效率。
目前我们的 MongoDB数据库单表达到70G,冗余数据积累。导致空间占用极大。为了实现“降本增效” 清理过期的数据 (切忌:过期数据也需要使用mongodump备份)因此,我们需要一个自动化机制,能够根据数据的“最后修改日期”等时间戳字段,识别并删除过期记录。

3、功能概述

本方案设计了一个Python脚本,集成了以下几个核心功能:

  • 配置文件读取:允许用户灵活配置数据库连接信息、目标集合名、数据过期天数以及批处理大小等参数。
  • 动态时间阈值计算:根据用户设定的过期天数,计算出需删除数据的截止时间戳。
  • 分批删除机制:为了减少对数据库的冲击,脚本采用分批删除策略,每次只处理一批数据,直至所有过期数据被清理完毕。
  • 进度可视化:集成tqdm库,实时显示删除进度,使操作过程透明且直观。
  • 错误处理:包含了对配置加载、数据库连接、数据操作等环节的异常处理,确保脚本的健壮性。

4、实现步骤

1、数据库表结构分析

假如我们有个:tag_logs 的集合
数据格式如下:

db.getCollection("tag_logs").insert( {_id: ObjectId("65dd5f067db3e415f0d3972f"),taskId: "65dd5efd7db3e415f0d39630",modelId: "6285a9890d45000030004392",name: "nihaogengx",ruleResult: "NOT_HIT",logic: "AND",conditionResults: [{name: "nihaogengx",result: "NOT_HIT",logic: "AND",subRuleResults: [{name: "nihaogengx",result: "NOT_HIT",variableCode: "var-instant-core-xxxxxx"}]}],type: "AUDIT_TAG",createdDate: NumberLong("1709006598851"),lastModifiedDate: NumberLong("1709006598851"),_class: "com.fujfu.shinji.entity.TagResultDO"
} );

索引查询

db.createCollection("tag_logs");db.getCollection("tag_logs").createIndex({taskId: NumberInt("1")
}, {name: "idx_tagResult_taskId"
});db.getCollection("tag_logs").createIndex({createdDate: NumberInt("1")
}, {name: "createdDate_1",background: true
});db.getCollection("tag_logs").createIndex({lastModifiedDate: NumberInt("-1")
}, {name: "lastModifiedDate_-1",background: true
});

2、增加索引

我们是根据 lastModifiedDate 来获取过期的时间,所以这个必选加索引。如果没有索引,根据下方添加

db.tag_logs.createIndex( { lastModifiedDate: -1 }, { background: true } )

这个命令的作用是在 tag_logs 集合上创建一个索引。具体来说:

  1. db.tag_logs.createIndex:这是在 tag_logs 集合上创建索引的方法。
  2. { lastModifiedDate: -1 }:这是索引的键和排序顺序。具体解释如下:
    • lastModifiedDate 是你希望创建索引的字段名。
    • -1 表示你希望按照该字段的降序排序来创建索引。如果你用的是 1,则表示按照升序排序。
  3. { background: true }:这是索引创建的选项。具体解释如下:
    • background: true 表示在后台创建索引。这意味着索引创建操作不会阻塞其他数据库操作,允许其他读写操作继续进行。这对于生产环境中的大型集合非常有用,因为它可以减少对应用程序正常操作的干扰。

3、脚本核心逻辑

config.ini

[database]
uri = mongodb://root:xxxx.88@mongo2.fat.xxxx.fjf:27017/?authSource=admin  #Mongo连接字符串
db_name = xxx-xxx-engine   # 数据库名称
collection_name = variable_result_1  # 集合名称
expired_days = 90  # 删除过期多少天的。 删除3个月之前的数据
batch_size=1000 #每次删除的条数

clean_expired_data.py

import configparser
from pymongo import MongoClient, errors
from datetime import datetime, timedeltafrom tqdm import tqdmdef load_config(file_path='config.ini'):"""Load configuration from the specified file."""config = configparser.ConfigParser()config.read(file_path)return configdef get_mongo_client(uri):"""Create and return a MongoDB client."""return MongoClient(uri)def get_cutoff_timestamp(days):"""Calculate and return the cutoff timestamp."""cutoff_date = datetime.now() - timedelta(days=days)return int(cutoff_date.timestamp() * 1000)def delete_expired_documents(collection, cutoff_timestamp, batch_size):"""Delete documents older than the cutoff timestamp in batches."""total_deleted = 0all_documents = collection.count_documents({})# 1. 查询出需要删除的集合数量total_to_delete = collection.count_documents({'lastModifiedDate': {'$lt': cutoff_timestamp}})print(f"集合总数: {all_documents}, 需要删除的文档数量: {total_to_delete}")# 2. 使用 tqdm 显示进度条with tqdm(total=total_to_delete, desc='Deleting documents', unit='doc') as pbar:while True:documents = collection.find({'lastModifiedDate': {'$lt': cutoff_timestamp}},limit=batch_size)document_ids = [doc['_id'] for doc in documents]if not document_ids:breakresult = collection.delete_many({'_id': {'$in': document_ids}})deleted_count = result.deleted_counttotal_deleted += deleted_count# print(f'Deleted {deleted_count} documents')# 3. 更新进度条pbar.update(deleted_count)if deleted_count < batch_size:breakreturn total_deleteddef clean_mongo_expired_data():"""Main function to clean expired data from MongoDB."""config = load_config()try:uri = config['database']['uri']db_name = config['database']['db_name']collection_name = config['database']['collection_name']expired_days = int(config['database']['expired_days'])batch_size = int(config['database']['batch_size'])client = get_mongo_client(uri)db = client[db_name]collection = db[collection_name]cutoff_timestamp = get_cutoff_timestamp(expired_days)total_deleted = delete_expired_documents(collection, cutoff_timestamp, batch_size)print('Completed deletion')print(f'Deleted {total_deleted} documents')except (configparser.Error, ValueError, errors.PyMongoError) as e:print(f'Error occurred: {e}')if __name__ == '__main__':clean_mongo_expired_data()

requirements.txt
python 环境版本:Python 3.8.10

pymongo==4.3.3
tqdm==4.66.4

5、实战测试

python3  -m venv py3  #创建虚拟环境source env_py/py3/bin/activate #加载环境pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple # 安装依赖更改config.ini 启动程序nohup python clean_expired_data.py  &(py3) [root@jenkins mongodb_clean]# tail -f nohup.out 集合总数: 410565470, 需要删除的文档数量: 404724244
Deleting documents:  13%|█▎        | 53910000/404724244 [1:17:54<8:13:39, 11844.06doc/s]

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6、性能分析

在数据库维护操作中,尤其是涉及大量数据删除的场景,采取批量删除策略是出于对系统性能和稳定性的关键考量。直接针对大量数据执行一次性删除操作可能会引发以下几个潜在问题,这些问题对于生产环境中的MongoDB数据库尤为敏感:

  1. IOPS(每秒输入/输出操作)激增
  • 大规模数据删除会导致磁盘I/O操作显著增加,瞬间的高IOPS需求可能迅速消耗数据库的I/O资源。这不仅会减慢当前操作的速度,还可能影响到其他正在执行的重要数据库操作,如关键查询和事务处理。
  1. 锁竞争与阻塞
  • 虽然MongoDB采用了更细粒度的锁机制,但在极端情况下,大量写操作仍可能引发锁争用,导致其他读写操作被阻塞。这会直接影响系统的并发性能。
  1. 资源消耗
  • 大量数据的连续删除操作会消耗大量的CPU和内存资源。在资源有限的系统中,这可能导致系统响应变慢,甚至出现短暂的服务不可用状态。
  1. 日志膨胀
  • 数据库的每一次写操作,包括删除,都会被记录到事务日志中。大量删除操作会导致日志文件迅速增大,不仅占用存储空间,还会增加日志回放和恢复的时间。

采用上述方式可以简单有效解决

目前我删除 404724244(4亿条数据),自动每次删除1w条,持续删 (不影响业务运行)
在这里插入图片描述
在这里插入图片描述
7亿条数据
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PS:电子书App自动截图后合成一个PDF文档

说明&#xff1a;有的电子书App不能下载到本地&#xff0c;通过自动截图后合成一个PDF文档来解决&#xff01; 一、自动截图App 1.安装”免ROOT自动化助手“ 2.创建一个任务 3.编辑任务&#xff1a;根据电子书的操作顺序制定&#xff0c;400次就是书籍页数&#xff08;次数一…

【Jmeter】性能测试之压测脚本生成,也可以录制接口自动化测试场景

准备工作-10分中药录制HTTPS脚本&#xff0c;需配置证书 准备工作-10分中药 以https://www.baidu.com/这个地址为录制脚本的示例。 录制脚本前的准备工作当然是得先把Jmeter下载安装好、JDK环境配置好、打开Jmeter.bat&#xff0c;打开cmd&#xff0c;输入ipconfig&#xff0c;…

Vitis HLS 学习笔记--块级控制协议-ap_ctrl_chain/ap_ctrl_hs/ap_ctrl_none

目录 1. 简介 2. 详细分析 2.1 使用场景区别 2.2 ap_continue 行为详解 2.3 ap_ctrl_chain 行为详解 3. 总结 1. 简介 块级控制协议允许硬件模块表明&#xff1a; 何时可以开始处理数据。何时完成了数据处理。以及何时处于空闲状态&#xff0c;准备接受新的数据输入。 …

这么多不同接口的固态硬盘,你选对了嘛!

固态硬盘大家都不陌生,玩游戏、办公存储都会用到。如果自己想要给电脑或笔记本升级下存储,想要存储更多的文件,该怎么选购不同类型的SSD固态盘呐,下面就来认识下日常使用中常见的固态硬盘。 固态硬盘(Solid State Drive, SSD)作为数据存储技术的革新力量,其接口类型的选…

【深度 Q 学习-01】 Q学习概念和python实现

文章目录 一、说明二、深度 Q 学习概念三、python实现四、结论 关键词&#xff1a;Deep Q-Networks 一、说明 在强化学习 &#xff08;RL&#xff09; 中&#xff0c;Q 学习是一种基础算法&#xff0c;它通过学习策略来最大化累积奖励&#xff0c;从而帮助智能体导航其环境。它…

气膜建筑的运营成本解析:高效节能的运作模式—轻空间

气膜建筑以其独特的优势和广泛的应用吸引了大量关注。然而&#xff0c;许多人对其持续吹气的运营成本产生了疑问。实际上&#xff0c;气膜建筑通过智能控制系统和高效的风机管理&#xff0c;大大降低了运营成本。本文将以2000平方米的气膜建筑为例&#xff0c;详细解析其运行成…

Vue3 - 实现一个雨水滴落的动画效果

在 Vue 3 中实现一个雨水滴落的动画效果,可以使用 HTML5 的 <canvas> 元素和 JavaScript 来绘制和控制动画。 以下是一个实现雨水滴落效果的示例: 创建一个 Vue 3 项目 首先,确保你已经创建了一个 Vue 3 项目。如果还没有,可以使用 Vue CLI 来创建: vue create r…

2024年社会发展、人文艺术与文化国际会议(ICSDHAC 2024)

2024年社会发展、人文艺术与文化国际会议&#xff08;ICSDHAC 2024&#xff09; 会议简介 2024年国际社会发展、人文、艺术和文化会议&#xff08;ICSDHAC 2024&#xff09;将在广州举行。会议旨在为从事社会发展、人文、艺术和文化研究的专家学者提供一个平台&#xff0c;分…

字符串操作:写一个方法,实现字符串的反转,如:输入abc,输出cba

import java.util.Scanner; public class Test_A15 {public static void main(String[] args){String strA"";System.out.println("请输入一串字符串:");Scanner scannernew Scanner(System.in);strAscanner.next();Test_A15 T15new Test_A15();String re…

leetCode.86. 分隔链表

leetCode.86. 分隔链表 题目思路&#xff1a; 代码 class Solution { public:ListNode* partition(ListNode* head, int x) {auto lh new ListNode(-1), rh new ListNode(-1);auto lt lh, rt rh;for(auto p head; p; p p->next ) {if(p->val < x) {lt lt->…

Midjourney保姆级教程(五):Midjourney图生图

Midjourney生成图片的方式除了使用文字描述生成图片外&#xff0c;还有“图生图”的方式&#xff0c;可以让生成的图片更接近参考的图片。 今天我们来聊聊“图生图”的方式。 一、模仿获取propmt 很多时候&#xff0c;我们不知道画什么内容的图片&#xff0c;大家可以关注内…

SRS视频服务器应用研究

1.SRS尝试从源码编译启动 1.1.安装ubuntu 下载镜像文件 使用VMWare安装&#xff0c;过程中出现蓝屏&#xff0c;后将VM的软件版本从15.5升级到17&#xff0c;就正常了。 1.2.更新ubuntu依赖

第二十四章多栏布局解决方案(什么是自适应?/)

什么是自适应? 指能使网页自适应显示在不同大小终端设备上新网页设计方式及技术.简单的来说自适应就是让同一个页面自动适应不同大小的设备&#xff0c;从而解决为不同设备提供不同版本的页面问题。 1&#xff0e;两列自适应 两列自适应布局是指左侧固定宽度&#xff0c;右…

低代码开发与人工智能技术在商品推荐系统中的应用

引言 低代码开发和人工智能技术的背景和重要性 随着数字化转型的深入&#xff0c;企业在信息技术领域面临着前所未有的挑战和机遇。快速变化的市场需求、日益复杂的技术环境以及高度竞争的商业环境&#xff0c;迫使企业不断寻求高效的开发和运营解决方案。低代码开发平台应运而…

【java-数据结构19-队列的模拟实现】

上篇文章&#xff0c;小编已经带大家一起认识了队列&#xff0c;并且对队列的方法进行调用测试&#xff0c;下面我们将模拟实现一个队列&#xff0c;话不多说&#xff0c;上正文~ 1.队列的模拟实现 队列的实现方法和链表的实现方式一模一样&#xff0c;这里我们首选双链表&…

VirtualBox虚拟机与bhyve虚拟机冲突问题解决@FreeBSD

问题 在安装完bhyve虚拟系统的主机上启动VirtualBox虚拟机的时候&#xff0c;报错&#xff1a;不能为虚拟电脑 debian 打开一个新任务. VirtualBox cant operate in VMX root mode. Please close all other virtualization programs. (VERR_VMX_IN_VMX_ROOT_MODE). 返回 代码…

项目成功的关键要素:进度管理

在项目管理中&#xff0c;进度管理是决定项目成败的关键因素之一。它关乎项目能否在预定的时间范围内高效、准确地完成既定目标。 一、进度管理的重要性 1、时间控制&#xff1a;项目的成功往往与时间的把握息息相关。进度管理能够确保项目在既定的时间框架内有序进行&#x…

uni-app学习完结

昨天空余一天&#xff0c;并未写记录&#xff0c;是昨天属于项目完结&#xff0c;这里把最后的打包上线等这里说下。 打包成微信小程序 打包成微信小程序&#xff0c;这需要再微信公众平台里面&#xff0c;进行登陆和设置。这里说下&#xff0c;注册的后&#xff0c;选择需要…

LeetCode---链表

203. 移除链表元素 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 代码示例1&#xff1a;(直接使用原来的链表来进行移除节点操作) //时间复杂度: O(n) //空间复杂度: O(1) class Solu…

数据通信基本概念汇总

1. 数据通信基础 网关: 提供协议转换&#xff0c;路由选择&#xff0c;数据交换的网络设备 报文: 网络中所传递的一个数据单元。 数据载荷: 最终要传递的信息 封装: 给数据载荷添加头部和尾部的过程(形成新的报文) 解封装: 给数据载荷去掉头部和尾部的过程(获取数据载荷) 终端设…