MongoDB数据库清理策略: 自动化过期数据删除实战

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条,持续删 (不影响业务运行)
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

Qt 对话框或者QMainWindow等类中调用自定义QWidget继承组件

简单的方法如下所示 1、创建一个ui文件&#xff0c;界面布局放入QVBoxLayout或者QHBoxLayout 使用他来放入自定义组件&#xff0c;类似如下 2、代码如下&#xff1a; ui.setupUi(this); { //自定义组价如下 KwTable *Table new KwTable(this); ui.vertical…

为什么要有NOC

如果是AHB&#xff0c;注意AXI并不真的定义了总线&#xff0c;更多是接口。 那么如何实现上面的带宽&#xff0c;延迟需求呢。 在异构&#xff0c;多时钟&#xff1b;大芯片&#xff0c;物理面积很大&#xff0c;延迟太长&#xff1b;片上系统&#xff0c;IP众多&#xff0c;总…

包装设计的七个秘诀

大家都知道&#xff0c;包装设计的好与坏不等于企业的好&#xff0c;但是消费者会有先入为主的想法&#xff0c;如果一个企业连包装设计都不重视&#xff0c;那么谁来重视产品质量呢&#xff1f;无可否认&#xff0c;对产品的评价首先是质量&#xff0c;但质量之后&#xff0c;…

【OpenVINO™】在C#中使用 OpenVINO™ 部署 YOLOv10 模型实现目标

文章目录 1. 前言1.1 OpenVINO™ C# API1.2 YOLOv10 2. 模型获取2.1 源码下载2.2 配置环境2.3 下载模型 3. Yolov10 项目配置3.1 项目创建与环境配置3.2 定义模型预测方法3.2.1 定义目标检测模型方法3.2.2 使用OpenVINO™ 预处理接口编译模型 3.2 模型预测方法调用 4. 项目运行…

文心智能体之情感领航员:你的智能情感导师

文章目录 引言情感领航员的诞生与定位情感领航员的优势与特点专业性个性化便捷性隐私保护 如何创建自己的智能体创建方式智能体名称和设定基础配置角色与目标指导原则限制澄清个性化 高级配置保存 /发布流量数据分析智能体调优 总结 引言 在现代社会中&#xff0c;情感问题的普…

[CISCN2024]-PWN:orange_cat_diary(glibc2.23.,仅可修改最新堆块,house of orange)

查看保护 查看ida 这里我们仅可以修改最新申请出来的堆块&#xff0c;但是有uaf漏洞。 完整exp&#xff1a; from pwn import* #context(log_leveldebug) pprocess(./orange) free_got0x201F78def alloc(size,content):p.sendlineafter(bPlease input your choice:,b1)p.send…

行转列——kettle开发14

一、行转列 如图所示&#xff0c;行转列就是把数据字段的字段名转换为一列&#xff0c;把数据行变成数据列。即我们将昨天输出的张三在周一至周日的工作小时转换为7行数据。对应7行数据分别为张三在周一工作多个小时&#xff0c;在周二工作多少个小时等等。 我们来看下行转列组…

pycharm打开服务器(linux)上的项目

先在本地打开项目 一、项目文件配置 tools-deployment-configuration 新增一个sftp连接 测试服务器是否可以连通 mappings中设置本地路径和服务器上的路径 二、环境配置 先参考文章 复现论文的conda环境&#xff08;win和联网、离线linux&#xff09;_conda复现环境-CSDN博…

有个小伙把 MyBatis 替换成 MyBatis-Plus,上线后就被开了!!

MyBatis-Plus 替换 MyBatis 首先&#xff0c;我们准备了一张名为 tbl_order 的表&#xff0c;并初始化了其中的两条数据。 DROP TABLE IF EXISTS tbl_order; CREATE TABLE tbl_order (id bigint(0) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 自增主键,order_no varchar(50)…

【加密与解密(第四版)】第十八章笔记

第十八章 反跟踪技术 18.1 由BeginDebugged引发的蝴蝶效应 IsDebuggerPresent()函数读取当前进程PEB中的BeginDebugged标志 CheckRemoteDebuggerPresent() 反调试总结&#xff1a;https://bbs.kanxue.com/thread-225740.htm https://www.freebuf.com/articles/others-articl…

如何在工信部教考中心官网查询PG证书

1.第一步&#xff1a;进入工业和信息化部教育与考试中心官网 2.第二步&#xff1a;点击最右边“证书查询” 3.点击“工业和信息化部教育与考试中心培训评价证书查询” 4.在该页面按照如下方式进行证书查询&#xff1a;输入您的证件号码和您的证书号码以及姓名&#xff0c;点…

蓝桥杯备赛——DP续【python】

一、小明的背包2 试题链接&#xff1a;https://www.lanqiao.cn/problems/1175/learning/ 输入示例 5 20 1 6 2 5 3 8 5 15 3 3 输出示例 120 问题分析 这题是完全背包&#xff0c;每个物品有无数个&#xff0c;所以对于任意dp[i][j]&#xff08;其表示的意思为选到第i个…

算法设计第七周(应用哈夫曼算法解决文件归并问题)

一、【实验目的】 &#xff08;1&#xff09;进一步理解贪心法的设计思想 &#xff08;2&#xff09;掌握哈夫曼算法的具体应用 &#xff08;3&#xff09;比较不同的文件归并策略&#xff0c;探讨最优算法。 二、【实验内容】 设S{f1,…,fn}是一组不同的长度的有序文件构…

基于springboot+vue的仓库管理系统

免费获取方式↓↓↓ 项目介绍029&#xff1a; http://localhost:8081/ eclipse mysql jdk1.8 密码admin root 用户员&#xff08;id 账号 密码 年龄 角色 电话&#xff09; 仓库表&#xff08;id 名称 备注&#xff09; 分类表&#xff08;id 名称 备注&#xff09; 记录表(id…

深度学习论文: YOLOv10: Real-Time End-to-End Object Detection

深度学习论文: YOLOv10: Real-Time End-to-End Object Detection YOLOv10: Real-Time End-to-End Object Detection PDF: https://arxiv.org/pdf/2405.14458 PyTorch代码: https://github.com/shanglianlm0525/CvPytorch PyTorch代码: https://github.com/shanglianlm0525/PyTo…

104-1389-006马达单价1041389006可议价

104-1389-006 产品 M 马达 系列 02 2000 系列 排量 149 244.3 CM3/R [14.91 IN3/R] 安装类型 AH 标准&#xff0c;4 螺栓&#xff1b;先导直径为 82.6 [3.25] 13.59 直径为 [0.535] 直径为 106.4 [4.19] 的孔螺栓圆周 输出轴 16 直径为 32.00 [1…

地铁判官:啥时候B端系统界面,也出个“判官”,讲好不准打脸。

小编所在的城市——山东青岛&#xff0c;出了个地铁判官&#xff0c;我看了视频&#xff0c;哈哈哈&#xff0c;俗世的判断标准就是那么简单直接&#xff0c;而放到B端系统那就难说啦。 如何判断B端系统的优劣&#xff0c;各位看官&#xff0c;各抒己见吧。 判断B端系统界面的…

智慧校园建设规划方案

在信息化浪潮的推动下&#xff0c;智慧校园的建设已成为教育现代化的必然趋势。以创新科技赋能教育&#xff0c;打造智慧校园&#xff0c;旨在提升教学品质&#xff0c;优化管理流程&#xff0c;增强学生体验。构建智慧校园需要具有前瞻性的规划方案&#xff0c;它将以教育为核…

PL5358A 单芯锂离子/聚合物电池保护IC芯片

一般说明 PL5358A系列产品是锂离子/聚合物电池保护的高集成解决方案。PL5358A包含先进 的功率MOSFET&#xff0c;高精度电压检测电路和延迟电路。5358A被放入一个超小的SOT23-5封装&#xff0c;只有一个外部元件&#xff0c;使其成为理想的解决方案&#xff0c;在有限的…

开源博客项目Blog .NET Core源码学习(28:App.Hosting项目结构分析-16)

本文学习并分析App.Hosting项目中后台管理页面的用户管理页面。   用户管理页面用于显示、检索、新建、编辑、删除用户数据&#xff0c;其附带一新建及编辑页面&#xff0c;以支撑新建和编辑用户数据&#xff0c;同时还附带重置密码页面&#xff0c;以重置用户密码。整个页面…