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, timedelta

from tqdm import tqdm


def load_config(file_path='config.ini'):
    """Load configuration from the specified file."""
    config = configparser.ConfigParser()
    config.read(file_path)
    return config


def 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 = 0
    all_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:
                break

            result = collection.delete_many({'_id': {'$in': document_ids}})
            deleted_count = result.deleted_count
            total_deleted += deleted_count
            # print(f'Deleted {deleted_count} documents')
            # 3. 更新进度条
            pbar.update(deleted_count)
            if deleted_count < batch_size:
                break
    return total_deleted


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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[算法] 优先算法(三):滑动窗口(上)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

Web安全技术期末考查-vulhub靶场搭建及漏洞复现

一、实验目的与要求 能根据报告找到难度适中的漏洞&#xff0c;搭建弱点环境&#xff0c;并验证该漏洞&#xff1b; 2.能给出该漏洞的修复建议。 二、实验原理与内容 漏洞原理 漏洞原理通常指的是计算机系统、软件、网络或其他技术系统中存在的安全缺陷&#xff0c;这些缺陷…

Ubuntu18 配置FFmpeg开发环境 (Vscode+CMake)

关于Vscode插件安装不再赘述&#xff0c;本文主要讲解如何配置FFmpeg的开发环境以及CMake文件写法&#xff0c;如果不知道该安装什么插件请看本文&#xff1a; Ubuntu配置Vscode 文章目录 1.安装FFmpeg开发包2.配置Vscode项目3.使用C语言验证FFmpeg版本 1.安装FFmpeg开发包 更新…

粉丝问,有没有UI的统计页面,安排!

移动应用的数据统计页面具有以下几个重要作用&#xff1a; 监控业务指标&#xff1a;数据统计页面可以帮助用户监控关键业务指标和数据&#xff0c;例如用户活跃度、销售额、转化率等。通过实时更新和可视化呈现数据&#xff0c;用户可以及时了解业务的整体状况和趋势。分析用…

深入剖析—【服务器硬件】与【Nginx配置】:从基础到实战

服务器硬件部分&#xff1a; Processor (CPU)&#xff1a;服务器的计算核心&#xff0c;负责处理数据和执行程序。Memory (RAM)&#xff1a;用于暂时存储和快速访问数据&#xff0c;决定了系统的运行速度和并发处理能力。Storage (HDD/SSD)&#xff1a;长期存储数据的设备&…

基于JT/T808、JT/T1078、苏标、粤标视频主动安全监控

1.概述 如下图是以实时视频点播与部标机产生了主动安全报警&#xff0c;各个服务之间的交互流程说明。 整个系统有以下几个核心组件组成&#xff1a; 1&#xff1a;系统业务端&#xff1a;车载监控业务系统&#xff0c;给用户提供车载监控整套业务流程与界面呈现&#xff1b;…

Docker安装Oracle11g数据库

操作系统&#xff1a;centOS9使用此方法检查是否安装Docker&#xff1a;docker --help&#xff0c;如果有帮助文件则证明安装成功使用此语句检查Docker是否正在运行&#xff1a;docker images&#xff0c;实际上是查看本地镜像如果发现未运行则开启Docker&#xff1a;systemctl…

rapidssl泛域名https600元一年

泛域名https证书也可以称之为通配符https证书&#xff0c;指的是可以用一张https证书为多个网站(主域名以及主域名下的所有子域名网站)传输数据加密&#xff0c;并且提供身份认证服务的数字证书产品。RapidSSL旗下的泛域名https证书性价比高&#xff0c;申请速度快&#xff0c;…

使用 FileZilla 在 Windows 和 Ubuntu 之间传文件

网线一端插在板子的WAN口上&#xff0c;另一段插在电脑上&#xff0c;然后要配一下板子的IP。 板侧&#xff1a; 使用串口链接板子与PC端&#xff1b; 输入指令 ifconfig eth0&#xff08;具体看wan口对应哪一个&#xff09; 192.168.1.99 PC端配置&#xff1a; 打开网络设…

操作系统实验:进程和线程同步和互斥(生产者消费者问题,睡觉的理发师问题)

1.生产者消费者问题&#xff08;信号量&#xff09; 参考教材中的生产者消费者算法&#xff0c;创建5个进程&#xff0c;其中两个进程为生产者进程&#xff0c;3个进程为消费者进程。一个生产者进程试图不断地在一个缓冲中写入大写字母&#xff0c;另一个生产者进程试图不断地…

sqlserver——查询(四)——连接查询

目录 一.连接查询 分类&#xff1a; 内连接&#xff1a; 1. select ... from A&#xff0c;B &#xff1b; 2. select ..from A&#xff0c;B where ..&#xff1b; 3.select ...,... from A join B on... 4. where 与 join...on 的区别 5. where位置的先后 导语&#xff1…

开发心电疾病分类的深度学习模型并部署运行于ARM虚拟硬件平台(AVH)

目录 一、ARM虚拟硬件平台介绍 二、心电疾病分类模型介绍 三、部署流程 3.1 基于百度云平台订阅虚拟硬件镜像 3.2 安装编译相关组件 3.3 数据加载 3.4 模型转换 方式一&#xff1a; tensorflow模型转换为onnx模型&#xff0c;onnx模型转换为TVM模型 方式二&#xff1…

【操作系统】发展与分类(手工操作、批处理、分时操作、实时操作)

2.操作系统发展与分类 思维导图 手工操作阶段&#xff08;此阶段无操作系统&#xff09; 需要人工干预 缺点&#xff1a; 1.用户独占全机&#xff0c;资源利用率低&#xff1b; 2.CPU等待手工操作&#xff0c;CPU利用不充分。 批处理阶段&#xff08;操作系统开始出现&#x…

从零入门激光SLAM(二十一)——FAST-LIO2论文解析

FAST-LIO2: Fast Direct LiDAR-Inertial Odometry 论文地址&#xff1a;https://ieeexplore.ieee.org/stamp/stamp.jsp?tp&arnumber9697912 代码&#xff1a;https://github.com/hku-mars/FAST_LIO 一、文章概述 1.问题导向 基于视觉传感器的高分辨率和高精度的实时密…

Excel 取出每组最后一行

Excel的前两列是两层的分组列&#xff0c;后两列是明细 ABCD1CM11112CM12123CM13134CM14145CM25156CM26167BM11218BM12229BM232310AM113111AM323212AM333313AM3434 现在要取出每小组的最后一行&#xff1a; ABCD1CM14142CM26163BM12224BM23235AM11316AM3434 使用 SPL XLL sp…

编译原理 期末复习笔记整理(上)

资料借鉴&#xff1a; 【编译原理】期末复习 零基础自学_哔哩哔哩_bilibili 编译原理笔记 第一章 引论 1.编译原理逻辑过程&#xff1a; 词法分析 语法分析 语义分析 中间代码生成 编译代码生成 2.词法分析 任务: 输入源程序&#xff0c;对…

SpringBootWeb 篇-深入了解 Mybatis 删除、新增、更新、查询的基础操作与 SQL 预编译解决 SQL 注入问题

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 Mybatis 的基础操作 2.0 基础操作 - 环境准备 3.0 基础操作 - 删除操作 3.1 SQL 预编译 3.2 SQL 预编译的优势 3.3 参数占位符 4.0 基础操作 - 新增 4.1 主键返回…

不拍视频,不直播怎么在视频号卖货赚钱?开一个它就好了!

大家好&#xff0c;我是电商糖果 视频号这两年看着抖音卖货的热度越来越高&#xff0c;也想挤进电商圈。 于是它模仿抖音推出了自己的电商平台——视频号小店。 只要商家入驻视频号小店&#xff0c;就可以在视频号售卖商品。 具体怎么操作呢&#xff0c;需要拍视频&#xf…

Windows下mingw32编译ffmpeg5.1.4实现rtsp拉流

由于客户要求&#xff0c;要在Windows下使用mingw32编译&#xff0c;去ffmpeg.org下载需要编译的版本&#xff0c;使用msys2方法进行编译&#xff0c;使用QT5.10的编译器&#xff0c;基本上把网上的方法试了个遍&#xff0c;编译全部库总是报错出问题 查看了ffbuild文件夹中con…

JSP期末要点复习

一、JSP工作原理 1.客户端请求JSP页面&#xff1a;用户通过浏览器发送一个请求到服务器&#xff0c;请求一个特定的JSP页面。这个请求被服务器上的Web容器&#xff08;如Apache Tomcat&#xff09;接收。 2.JSP转换为Servlet&#xff1a;当JSP页面第一次被请求时&#xff0…