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

news2024/9/21 4:26:05

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

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

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

相关文章

约翰·舒尔曼访谈解读:2027年AGI将成现实?

随着人工智能技术的不断进步&#xff0c;AGI&#xff08;通用人工智能&#xff09;的实现似乎不再是遥不可及的梦想。近日&#xff0c;OpenAI联合创始人兼首席架构师约翰舒尔曼&#xff08;John Schulman&#xff09;在访谈中分享了他对AI模型未来发展的看法&#xff0c;并预言…

day 4:2028. 找出缺失的观测数据

Leetcode 2028. 找出缺失的观测数据 现有一份 n m 次投掷单个** 六面** 骰子的观测数据&#xff0c;骰子的每个面从 1 到 6 编号。观测数据中缺失了 n 份&#xff0c;你手上只拿到剩余 m 次投掷的数据。幸好你有之前计算过的这 n m 次投掷数据的 平均值 。 给你一个长度为 m …

IDEA出现javax.servlet.http包错误解决方法

问题原因&#xff1a;缺少对应的jar包&#xff0c;其实tomcat服务器自带与HTTP一些相关的Jar包&#xff0c;没有导入进去。 解决方案1&#xff1a; 导入对应jar包 <dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</…

QT使用gsoap获取手机归属地

1-环境变量 用的win32 E:\hes_scc\tools\gsoap_2.8.134\gsoap-2.8\gsoap\bin\win32 2-生成代码接口 自己建一个目录&#xff0c;在此打开cmd窗口&#xff0c;生成的文件都会在这个文件夹中。 这里用的手机归宿地。 wsdl2h -o GetPhoneInfo.h -s -n Phone -t ....\typemap.…

Java(其十二)--集合·初级

ArrayList集合 集合有很多种&#xff0c;ArrayList 是最常用的一种&#xff0c;集合的作用相当于C中的STL 最显著的特点就是&#xff1a;自动扩容。 一般定义式 ArrayList list new ArrayList(); //该 list 是可以储存各种类型的数据的&#xff0c;要想约束储存的数据&#x…

安装appium自动化测试环境,我自己的版本信息

教程来自&#xff1a;Appium原理与安装 - 白月黑羽 我的软件的版本&#xff1a; 安装是选择为自己安装而不是选all user pip install appium-python-client命令在项目根目录下安装appium-python-client sdk的话最简单的安装方式就是去Android官网下一个android studio然后在…

【class17】人工智能初步-----语音识别(3)

【class16】 上节课&#xff0c;我们学习了&#xff1a;wav文件的相关概念知识&#xff0c;并通过代码从视频中获取了音频以及设置了参数。学习新的课程之前&#xff0c;我们先来复习一下吧&#xff01; 代码复习 将上节课学习的代码分为两个部分&#xff1a; part1. 获取音频…

Suricata-入门实验-快速理解suricata

实验环境&#xff1a; 主机win10 ip地址&#xff1a;192.168.121.1 虚拟机使用vm ubuntu20.04 ip地址&#xff1a;192.168.121.128 实验目标&#xff1a; 从主机 给虚拟机 发送ping 命令 虚拟机中Suricata接收到ping后发出告警信息。 正文 在前面 编译好Suricata后&#x…

PTA 计算矩阵两个对角线之和

计算一个nn矩阵两个对角线之和。 输入格式: 第一行输入一个整数n(0<n≤10)&#xff0c;第二行至第n1行&#xff0c;每行输入n个整数&#xff0c;每行第一个数前没有空格&#xff0c;每行的每个数之间各有一个空格。 输出格式: 两条对角线元素和&#xff0c;输出格式见样例…

想知道期权的交易方式有哪些吗?新手必看!

今天期权懂带你了解想知道期权的交易方式有哪些吗&#xff1f;新手必看&#xff01;期权指投资者在支付了一定的权利金之后&#xff0c;将拥有未来某个时间协定价格买入或者卖出的权利。 期权的交易策略方式有哪些&#xff1f; 买入看涨期权&#xff1a; 使用场景&#xff1a…

【算法】位运算——常见位运算基础操作总结

位运算基础操作总结&#xff0c;包括基础运算符 修改某位bit位 目录 1.基础位运算符2.按位基础操作1.给一个数 n&#xff0c;确定其二进制的第 x 位是 0/12.将一个数 n 的二进制标识的第 x 位修改成 13.将一个数 n 的二进制标识的第 x 位修改成 04.提取一个数 n 二进制中最右侧…

Centos 7 安装刻录至服务器

前言 在日常测试中&#xff0c;会遇到很多安装的场景&#xff0c;今天给大家讲一下centos 7 的安装&#xff0c;希望对大家有所帮助。 一.下载镜像 地址如下&#xff1a; centos官方镜像下载地址https://www.centos.org/download/ 按照需求依次点击下载 二.镜像刻录 镜像刻…

【Spring】Spring AOP底层原理:JDK动态代理和CGLIB动态代理

目录 1、代理模式 1.1、静态代理 1.2、动态代理 2、JDK 动态代理 2.1、jdk动态代理简介 2.2、使用JDK动态代理机制步骤 3、CGLIB 动态代理 3.1、CGLIB 动态代理的特性 3.2、CGLIB的核心类 3.3、CGLIB 动态代理步骤 4、JDK 和 CGLIB 创建代理对象的区别 ​编辑 1、…

Linux网络编程:传输层协议|UDP

知识引入&#xff1a; 端口号&#xff1a; 当应用层获得一个传输过来的报文时&#xff0c;这时数据包需要知道&#xff0c;自己应该送往哪一个应用层的服务&#xff0c;这时就引入了“端口号”&#xff0c;通过区分同一台主机不同应用程序的端口号&#xff0c;来保证数据传输…

【高数】重点内容,公式+推导+例题,大学考试必看

目录 1 隐函数求导1.1 公式1.2 说明1.3 例题 2 无条件极值2.1 运用2.2 求解2.3 例题 3 条件极值3.1 运用3.2 求解3.3 例题 4 二重积分4.1 直角坐标下4.2 极坐标下4.3 例题 5 曲线积分5.1 第一型曲线积分5.2 第二型曲线积分5.3 例题 6 格林公式6.1 公式6.2 说明6.3 例题 &#x…

【强化学习】Q-learning,DQN,SARSA算法介绍

【强化学习】Q-learning&#xff0c;DQN&#xff0c;SARSA算法介绍 强化学习算法分类基于价值的方法基于策略的方法Actor-Critic方法 Q-learning算法DQN算法强化学习训练数据存在的问题经验回放机制备份网络机制 Sarsa算法总结 强化学习算法分类 按学习目标进行分类 可分为基于…

信息化赋能:干部监督工作的创新与实践

随着信息技术的迅猛发展&#xff0c;信息化手段在干部监督工作中的应用越来越广泛&#xff0c;为提升监督工作的效率和精准度提供了有力支持。以下是如何利用信息化手段扎实推进干部监督工作的几点建议&#xff1a; 一、搭建信息化平台&#xff0c;实现数据统一管理 要扎实推…

【unity小技巧】unity读excel配置表操作,excel转txt文本,并读取txt文本内容,实例说明

文章目录 前言下载资源库导入资源库excel转txt文本读取txt内容 读取配置表所有的数据&#xff0c;并使用结束语 前言 关于unity读excel配置表操作&#xff0c;其实之前就有用过&#xff0c;这里只是单独整理出这部分知识&#xff0c;后续好使用。 感兴趣可以去看看&#xff1a…

【408精华知识】时钟周期、机器周期、总线周期、指令周期、存取周期还傻傻分不清?

在做题时&#xff0c;我们经常能遇到关于“周期”的表述&#xff0c;比如时钟周期、机器周期、总线周期、指令周期、存取周期&#xff0c;类似的表述让我们很容易迷茫&#xff0c;那么接下来我们就看看它们到底是什么、有什么区别&#xff1f; 周期特点时钟周期也称为CPU时钟周…

太速科技-基于FPGA Spartan6 的双路光纤PCIe采集卡(2路光纤卡)

基于FPGA Spartan6 的双路光纤PCIe采集卡(2路光纤卡) 1、板卡概述   板卡采用xilinx Spartan6系列芯片&#xff0c;支持 PCI Express Base Specification 1.1 x1。内含丰富的逻辑资源和存储单元&#xff0c;板卡FPGA外接双片32M*16bit DDR2缓存器&#xff0c;支持乒乓操作。…