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

news2024/10/6 14:32:54

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

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

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

相关文章

python数据分析——分组操作1

参考资料&#xff1a;活用pandas库 1、简介 借助“分割-应用-组合”&#xff08;split-apply-combine&#xff09;模式&#xff0c;分组操作可以有效地聚合、转换和过滤数据。 分割&#xff1a;基于键&#xff0c;把要处理的数据分割为小片段。 应用&#xff1a;分别处理每个数…

Raven2掠夺者2渡鸦2游戏预约注册教程 账号注册教程

《渡鸦2》是一款源自韩国的创新力作&#xff0c;作为《Raven》系列的最新续篇&#xff0c;这款游戏在MMORPG手游领域内再度扩展了其标志性的暗黑奇幻宇宙&#xff0c;融入了大量革新的游戏设计与丰富内容。定档于2024年5月29日开启公测的《渡鸦2》&#xff0c;正处在紧张刺激的…

简单四步完成基于云服务器ARL资产侦察灯塔系统搭建

简单四步完成基于云服务器ARL资产侦察灯塔系统搭建及使用 前言 官网介绍&#xff1a;ARL全称-Asset Reconnaissance Lighthouse&#xff0c;中文含义&#xff1a;资产侦察灯塔系统。 旨在快速侦察与目标关联的互联网资产&#xff0c;构建基础资产信息库。 协助甲方安全团队或…

数组-捡石子小游戏

一、题目描述 二、解题思路 刚开始拿到题目的时候在想是不是需要把所有情况枚举出来&#xff0c;其实思考一下能看出规律&#xff1a; 1.如果有1、2、3颗石子&#xff0c;小牛一定可以赢&#xff1b; 2.再来看4颗石子的时候&#xff0c;小牛A可以拿1~3颗&#xff0c;但是无论小…

M功能-分布式锁-支付平台(五)

target&#xff1a;离开柬埔寨倒计时-218day 珍藏的图片又拿出来了 前言 M系统中的撮合引擎是最最核心的功能&#xff0c;第一版的撮合引擎不是我写的&#xff0c;也没有做交易对的动态分配这样的功能&#xff0c;都是基于抢锁方式来决定谁拥有该交易对的撮合权限&#xff0c;所…

【Qt秘籍】[003]-Qt环境变量配置-磨刀不误砍柴工

一、为什么要设置环境变量 &#xff1f;[原因] 配置PATH环境变量的主要用处在于让操作系统能够识别并执行不在当前工作目录下的可执行文件。具体来说&#xff0c;它的作用包括&#xff1a; 命令执行便捷性&#xff1a;当你在命令行输入一个命令&#xff08;如java, python或np…

Collection(一)[集合体系]

说明&#xff1a;Collection代表单列集合&#xff0c;每个元素&#xff08;数据&#xff09;只包含一个值。 Collection集合体系&#xff1a; Collection<E> 接口 (一&#xff09;List<E> 接口 说明&#xff1a;添加的元素是有序、可重复、有索引。 1. ArrayLi…

在table中获取每一行scope的值

目的 当前有一份如下数据需要展示在表格中&#xff0c;表格的页面元素套了一个折叠面板&#xff0c;需要循环page_elements中的数据展示出来 错误实践 将template放在了折叠面板中&#xff0c;获取到的scope是空数组 <el-table-column label"页面元素" show-o…

【技术实操】银河高级服务器操作系统实例分享,达梦数据库服务器 oom 问题分析

1. 服务器环境以及配置 【 机型】 处理器&#xff1a; HUAWEIKunpeng 920 5220 内存&#xff1a; 400518528 kB 主板型号&#xff1a; Chaoqiang K620 series 整机类型/架构&#xff1a; ARM BIOS 版本&#xff1a; KL4.41.028.TF.220224.R 固件版本&#xff1a; KL4.41…

nginx源码阅读理解 [持续更新,建议关注]

文章目录 前述一、nginx 进程模型基本流程二、源码里的小点1.对字符串操作都进行了原生实现2.配置文件解析也是原生实现待续 前述 通过对 nginx 的了解和代码简单阅读&#xff0c;发现这个C代码的中间件确实存在过人之处&#xff0c;使用场景特别多&#xff0c;插件模块很丰富…

加密资产私钥安全完整手册(一) ,bitget钱包为例

比特币和以太坊等加密货币的兴起开创了数字金融的新时代&#xff0c;但也带来了独特的安全挑战。这些代表现实世界价值的数字资产已成为黑客和窃贼的主要目标。为了安全地应对这种情况&#xff0c;了解私钥的基本概念至关重要。 私钥是加密货币所有权和安全性的基石。它们相当于…

三维天地参编《数据要素流通标准化白皮书(2024版)》正式发布

近日,在福州举行的第七届数字中国建设峰会数据标准化和数据基础设施分论坛-数据标准化专场举行。国家数据局局长刘烈宏、福建省政府党组成员李兴湖出席并致辞。 该论坛由国家数据局主办、中国电子技术标准化研究院承办,围绕“标准引领 数创未来”主题,分享实践经验,明晰建设路…

故障诊断 | 基于KAN故障诊断模型

效果一览 文章概述 故障诊断 | 基于 KAN故障诊断模型。KAN是一种全新的神经网络架构&#xff0c;它与传统的MLP架构不同&#xff0c;能够用更少的参数量在Science领域取得惊人的表现&#xff0c;并且具备可解释性&#xff0c;有望成为深度学习模型发展的一个重要方向。运用KAN&…

网页上怎么打开iPhone手机上的备忘录 备忘录网页端打开方式

我经常使用iPhone的备忘录功能&#xff0c;随手记录生活中的点点滴滴&#xff0c;工作中的待办事项。然而&#xff0c;有时候&#xff0c;当我坐在电脑前&#xff0c;想要快速查看或编辑备忘录内容时&#xff0c;手机的小屏幕就显得不那么方便了。那么&#xff0c;如何在电脑上…

scrapy 整合 mitm

1.mitm 是什么 MITMproxy 是一个开源的中间人代理&#xff0c;常用于网络流量的拦截、查看和修改。 2.scrapy 整合 mitm步骤 2.1 安装mitm PS F:\studyScrapy\itcastScrapy> pip install mitmproxy2.2 在settings 中配置下载器中间件 # settings.pyDOWNLOADER_MIDDLEWARES…

如何将音频中的人声分离出来?

想要把一段视频中的人声跟背景音乐分离开来&#xff0c;找个好一点的音频处理软件就能把声音分离了&#xff0c;常见的有以下方法&#xff0c;一起来看看吧。 pr 打开软件&#xff0c;然后将电脑上的音频文件&#xff0c;上传到软件中&#xff0c;然后按住[ctrla]选择所有音频…

【硬核测评】猫咪主食冻干测评揭秘SC、希喂、爱立方真实对比测评

主食冻干喂养是否必要&#xff1f; 来自七年经验的铲屎官明确告诉你&#xff0c;这是非常必要的喂养方式&#xff01; 随着宠物经济的蓬勃发展和科学养宠知识的普及&#xff0c;如今养猫已不仅仅是让猫咪吃饱那么简单。越来越多的养猫人开始重视猫咪的饮食健康。大量实际喂养案…

SpringBoot之@AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder注解

前言 SpringBoot通过AutoConfigureOrder、AutoConfigureBefore、AutoConfigureAfter注解&#xff0c;控制自动配置类的实例化顺序。 Spring中控制Bean的实例化顺序 Spring中默认实例化顺序 创建实体类A、B、C Component public class A {public A() {System.out.println(&…

小熊家务帮day5 客户管理模块1 (小程序认证,手机验证码认证等)

客户管理模块 1.认证模块1.1 认证方式介绍1.1.1 小程序认证1.1.2 手机验证码登录1.1.3 账号密码认证 1.2 小程序认证1.2.1 小程序申请1.2.2 创建客户后端工程jzo2o-customer1.2.3 开发部署前端1.2.4 小程序认证流程1.2.4.1 customer小程序认证接口设计Controller层Service层调用…

The 2022 ICPC Asia Nanjing Regional Contest - External G

题目链接:Problem - D - Codeforces 写在前面&#xff1a;今天的训练赛打的稀碎&#xff0c;一道稍微难一点的签到题就把我难住了&#xff0c;看完题解确实感觉不难&#xff0c;看来题目还是刷太少了。 回归正题 题意&#xff1a; 思路&#xff1a;尽量让分子大&#xff0c;分…