数据一致性巡检总结:基于分桶采样的设计与实现

数据一致性巡检总结:基于分桶采样的设计与实现

背景

在分布式系统中,缓存(如 Redis)与数据库(如 MySQL)之间的数据一致性问题是一个常见的挑战。由于缓存的引入,数据在缓存和数据库之间可能存在延迟、更新失败或逻辑错误,导致数据不一致。这种不一致可能会影响业务的正确性和用户体验。

为了解决这一问题,我们设计并实现了一套基于分桶采样的数据一致性巡检机制。该机制通过分桶采样、分批处理、数据一致性校验、采样结果存储、报警机制以及数据维护机制,能够有效发现缓存与数据库之间的数据不一致问题,同时优化数据存储和查询效率,保障业务的正确性与稳定性。


一、设计思想

  1. 分桶采样
    • 将数据划分为多个桶(BUCKET_SIZE),每个桶包含一定范围的数据。
    • 根据单次需要采样的数量(sampleCount)和单次拉取数据量(batchSize),计算得到总批次数,通过总批次数(totalBatches)生成唯一索引(generateUniqueIndexes),到不同桶中随机采样数据。
    • 分桶采样的优点在于:
      • 降低数据重复采样的概率,确保采样数据的独立性。
      • 提高采样效率,避免全量扫描数据库。
      • 常规的数据库 Rand() 函数存在性能问题。
  2. 本地聚合与存储
    • 采样数据在本地内存中聚合,通过 ConcurrentHashMap 存储采样结果,减少频繁访问 Redis。
    • 采样结果通过 Redis 的 SortedSet 存储,score 为触发采样的时间戳,value 中存储的是不一致率以及不一致的订单信息,便于前端页面根据范围查询。
  3. 数据一致性校验
    • 针对每个订单号,分别校验缓存(Redis)与数据库(DB)中数据一致性。
    • 可以排除指定字段校验,例如 datachangeLasttime
    • 校验结果包括:
      • 对象级别一致性:校验单个对象(如订单、订单详情)的字段值是否一致。
      • 列表级别一致性:校验列表数据(如乘客信息、推荐信息)的条目数量和内容是否一致。
  4. 报警机制
    • 如果发现数据不一致,触发报警机制,通过邮件通知相关人员。
    • 报警内容包括:
      • 数据库名、表名、不一致率。
      • 不一致订单的详细信息(订单号、DB 数据、Redis 数据、不一致类型)。
  5. 数据维护机制
    • 定期将旧数据从热缓存迁移到冷缓存,并清理过期数据。
    • 通过冷热数据分离策略,优化存储和查询效率。
  6. 触发采样的方式
    • 定时任务触发:系统通过定时任务定期触发数据一致性巡检,确保数据一致性问题能够被及时发现。
    • 前端主动触发:提供了前端接口,允许管理员根据需要手动触发数据一致性巡检。

二、实现细节

1. 分桶采样

int totalBatches = totalCheckCount / batchSize;
if (totalCheckCount % batchSize != 0) {totalBatches++;
}
List<Integer> uniqueIndexes = generateUniqueIndexes(totalBatches).stream().toList();
  • 根据总数据量和批次大小计算总批次数。
  • 生成唯一索引(generateUniqueIndexes),确保每批次采样的数据独立且不重复。

2. 采样数据的获取

// 获取数据 SQL 针对 ID 取余 SELECT orderNumber FROM scm_grabticket_order WHERE Status IN ('O', 'L') AND id % ? = ? LIMIT ?
List<String> orderNumberList = orderDao.sampleEffectiveOrderNumber(BUCKET_SIZE, bucketIndex, batchSize);
  • 每批次从数据库中采样有效订单号(sampleEffectiveOrderNumber)。
  • 采样逻辑基于分桶索引(bucketIndex)和批次大小(batchSize),确保采样数据的独立性和代表性。

3. 数据一致性校验

checkConsistencyByOrderNumber(channelEnum, orderNumber, samplingResultMapForNewCache, DataConsistencyQueryType.NEW_CACHE);
  • 针对每个订单号,分别校验新旧缓存与数据库的一致性。

  • 校验逻辑包括:

    • 对象级别一致性

      checkObjectConsistencyAndStoreResult(orderNumber, samplingResult, dbValue, redisValue);
      
      • 比较单个对象的字段值是否一致,排除指定字段(CHECK_CONSISTENCY_EXCLUDE_FIELDS)。
    • 列表级别一致性

      checkListConsistencyAndStoreResult(orderNumber, samplingResult, dbValue, redisValue);
      
      • 比较列表数据的条目数量和内容是否一致,记录仅存在于 DB 或 Redis 中的数据。

4. 采样结果的存储

storeSampleResultToRedis(dbNameEnum, createTime, samplingResultMapForOldCache, DataConsistencyQueryType.NEW_CACHE);
  • 将采样结果存储到 Redis 的 SortedSet 中,score 为触发采样的时间戳。
  • 存储逻辑包括:
    • 设置采样结果的创建时间(createTime)和不一致率(inconsistencyRatio)。
    • 数据保留时间为 15 天(LocalDateTime.now().plusDays(15))。

5. 报警机制

dataInConsistencyAlert(samplingResultMapForNewCache, samplingResultMapForOldCache, dbNameEnum);
  • 如果发现数据不一致,触发报警机制。
  • 报警内容包括:
    • 数据库名、表名、不一致率。
    • 不一致订单的详细信息(最多展示 5 条)。

6. 数据维护机制

定期迁移数据到冷缓存

为了优化存储和查询效率,防止 Redis 数据内存占用过大,系统实现了一个数据维护机制,定期将旧数据从热缓存迁移到冷缓存,并清理过期数据。

public void maintainInConsistencyData(DBNameEnum dbNameEnum) {long fifteenDaysAgo = DateUtils.localDateTimeToLongAccurateMinute(LocalDateTime.now().minusDays(15));long sixMonthsAgo = DateUtils.localDateTimeToLongAccurateMinute(LocalDateTime.now().minusMonths(6));for (TableNameIndexEnum value : TableNameIndexEnum.values()) {for (DataConsistencyQueryType dataConsistencyQueryType : dataConsistencyQueryTypes) {// 1. 从热数据中查询 15 天以外的数据,备份到冷数据中backUpOldData(dbNameEnum, value.getTableNameEnum(), dataConsistencyQueryType, fifteenDaysAgo);// 2. 清理冷数据中半年以外的数据removeOldDataFromColdStore(dbNameEnum, value.getTableNameEnum(), dataConsistencyQueryType, sixMonthsAgo);}}
}
  • 备份旧数据:将 15 天以前的数据从热缓存迁移到冷缓存。
  • 清理过期数据:删除冷缓存中 6 个月以前的数据。
  • 数据精简:迁移到冷缓存时,会清除详细的不一致订单信息,只保留统计数据。
触发方式

数据维护机制的触发方式有两种:

  • 定时任务调度:系统会定期自动触发数据维护任务,确保数据定期得到整理和优化。
  • 前端主动触发:提供了前端接口,允许管理员手动触发数据维护任务,以应对特殊情况或紧急需求。

这种双重触发机制既保证了数据维护的自动化,又提供了灵活的人工干预途径。


三、前端展示

请添加图片描述
请添加图片描述


四、总结

本文总结了基于分桶采样的数据一致性巡检设计与实现,涵盖了分桶采样、分批处理、数据一致性校验、采样结果存储和报警机制等关键点。同时,介绍了数据维护机制,包括定期将旧数据迁移到冷缓存以及清理过期数据的策略。系统通过定时任务和前端主动触发两种方式来执行数据维护,既保证了自动化又提供了灵活性。

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

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

相关文章

SpringBoot与Druid整合,实现主从数据库同步

通过引入主从数据库同步系统&#xff0c;可以显著提升平台的性能和稳定性&#xff0c;同时保证数据的一致性和安全性。Druid连接池也提供了强大的监控和安全防护功能&#xff0c;使得整个系统更加健壮和可靠。 我们为什么选择Druid&#xff1f; 高效的连接管理&#xff1a;Dru…

在Linux系统中安装MySQL,二进制包版

1、检查是否已安装数据库&#xff08;rpm软件包管理器&#xff09; rpm -qa | grep mysql rpm -qa | grep mariadb #centOS7自带mariadb与mysql数据库冲突2、删除已有数据库 rpm -e –nodeps 软件名称 3、官网下载MySQL包 4、上传 # 使用FinalShell或Xshell工具上传&#…

【含文档+PPT+源码】基于SpringBoot电脑DIY装机教程网站的设计与实现

项目介绍 本课程演示的是一款 基于SpringBoot电脑DIY装机教程网站的设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套…

Spring Boot 缓存机制:从原理到实践

文章目录 一、引言二、Spring Boot 缓存机制原理2.1 缓存抽象层2.2 缓存注解2.3 缓存管理器 三、入门使用3.1 引入依赖3.2 配置缓存3.3 启用缓存3.4 使用缓存注解3.5 实体类 四、踩坑记录4.1 缓存键生成问题4.2 缓存过期与更新问题4.3 事务与缓存的一致性问题 五、心得体会5.1 …

Spark读取Apollo配置

--conf spark.driver.extraJavaOptions-Dapp.idapollo的app.id -Denvfat -Dapollo.clusterfat -Dfat_metaapollo的meta地址 --conf spark.executor.extraJavaOptions-Dapp.idapollo的app.id -Denvfat -Dapollo.clusterfat -Dfat_metaapollo的meta地址 在spark的提交命令中&…

[逆向工程]如何理解小端序?逆向工程中的字节序陷阱与实战解析

[逆向工程]如何理解小端序&#xff1f;逆向工程中的字节序陷阱与实战解析 关键词&#xff1a;逆向工程、小端序、字节序、二进制分析、数据解析 引言&#xff1a;为什么字节序是逆向工程师的必修课&#xff1f; 在逆向工程中&#xff0c;分析二进制数据是最基础的任务之一。…

项目三 - 任务2:创建笔记本电脑类(一爹多叔)

在本次实战中&#xff0c;我们通过Java的单根继承和多接口实现特性&#xff0c;设计了一个笔记本电脑类。首先创建了Computer抽象类&#xff0c;提供计算的抽象方法&#xff0c;模拟电脑的基本功能。接着定义了NetCard和USB两个接口&#xff0c;分别包含连接网络和USB设备的抽象…

ElasticSearch深入解析(六):集群核心配置

1.开发模式和生产模式 Elasticsearch默认运行在开发模式下&#xff0c;此模式允许节点在配置存在错误时照常启动&#xff0c;仅将警告信息写入日志文件。而生产模式则更为严格&#xff0c;一旦检测到配置错误&#xff0c;节点将无法启动&#xff0c;这是一种保障系统稳定性的安…

【Prometheus-MySQL Exporter安装配置指南,开机自启】

目录 1. 创建 MySQL 监控用户2. 配置 MySQL 认证文件3. 安装 mysqld_exporter4. 配置 Systemd 服务5. 启动并验证服务6. 修改Prometheus配置常见错误排查错误现象排查步骤 6. 验证监控数据关键注意事项 7. Grafana看板 1. 创建 MySQL 监控用户 mysql -uroot -p123456 # 登录M…

redis未授权访问漏洞学习

一、Redis常见用途 1. Redis介绍 全称与起源: Redis全称Remote Dictionary Service(远程字典服务)&#xff0c;最初由antirez在2009年开发&#xff0c;用于解决网站访问记录统计的性能问题。发展历程: 从最初仅支持列表功能的内存数据库&#xff0c;经过十余年发展已支持多种…

4.27搭建用户界面

更新 router下面的index.js添加新的children 先区分一下views文件夹下的不同vue文件&#xff1a; Home.vue是绘制home页面的所有的表格。 Main.vue是架构头部和左侧目录的框架的。 研究一下这个routes对象&#xff0c;就可以发现重定向redirect的奥妙所在&#xff0c;我们先把…

【MySQL】(8) 联合查询

一、联合查询的作用 由于范式的规则&#xff0c;数据分到多个表中&#xff0c;想要查询完整的信息&#xff0c;就需要联合查询多张表。比如查询学生的学生信息和所在班级的信息&#xff0c;就需要联合查询学生表和班级表。 二、联合查询过程 案例&#xff1a;查询学生姓名为孙…

图漾官网Sample_V1版本C++语言完整参考例子---单相机版本

文章目录 1.参考例子 主要梳理了图漾官网Sample_V1版本的例子 1.参考例子 主要增加了从storage区域读取相机参数的设置&#xff0c;使用图漾PercipioViewer软件&#xff0c;如何将相机参数保存到srorage区&#xff0c;可参考链接&#xff1a;保存相机参数操作 保存参数设置 注…

关于本地端口启动问题

如何启动一个本地端口 1. Node.js (使用Express框架) 使用node.js的方法 注意&#xff1a;下列bash命令最好在管理员权限运行的cmd窗口中进行&#xff0c;否则可能会有权限错误 首先&#xff0c;确保您已经安装了Node.js和npm。然后&#xff0c;创建一个新的Node.js项目并安…

产销协同的作用是什么?又如何对各部门发挥作用?

目录 一、产销协同的对象有哪些&#xff1f; 1. 客户需求 2. 市场趋势 3. 供应链伙伴 4. 企业战略目标 二、产销协同的作用是什么&#xff1f; 1. 提高客户满意度 2. 降低企业成本 3. 增强市场竞争力 4. 优化资源配置 三、产销协同对各部门怎么发挥作用&#xff1f;…

React Router v7 从入门到精通指南

一、设计思想与核心原理 1. 设计哲学 组件即路由&#xff1a;路由以 <Route> 组件形式声明&#xff0c;与 React 组件树深度集成声明式导航&#xff1a;通过 <Link> 和 useNavigate 实现无刷新路由跳转动态匹配机制&#xff1a;路径参数、通配符、优先级匹配规则…

Python爬虫实战:获取网yi新闻网财经信息并做数据分析,以供选股做参考

一、引言 在财经领域,股市信息对投资者意义重大。网yi新闻作为知名新闻资讯平台,其股市板块蕴含丰富的最新股市热点信息。然而,依靠传统人工方式从海量网页数据中获取并分析这些信息,效率低下且难以全面覆盖。因此,利用爬虫技术自动化抓取相关信息,并结合数据分析和机器…

Spring Boot Actuator - 应用监控与管理

一、 Spring Boot Actuator 概述 Spring Boot Actuator是Spring Boot 提供的生产级监控与管理工具集&#xff0c;用于实时监控和运维管理应用。Actuator 通过HTTP 端点&#xff08;或 JMX 端点&#xff09;暴露应用的健康状态、性能指标、日志信息、环境配置等关键数据&#x…

不同类型插槽的声明方法和对应的调用方式

在 Vue 3 中&#xff0c;slot 用于让组件的使用者可以向组件内部插入自定义内容。Vue 3 提供了多种声明和使用插槽的方式&#xff0c;下面为你详细介绍不同类型插槽的声明方法和对应的调用方式。 1. 匿名插槽 声明方法 在组件模板中直接使用 标签来定义匿名插槽&#xff0c;它可…

DeepSeek 联手 Word,开启办公开挂模式

目录 一、DeepSeek 与 Word 结合的神奇之处二、前期准备&#xff0c;万事俱备2.1 了解 DeepSeek2.2 确认软件版本2.3 账号与密钥获取 三、接入方法全解析3.1 OfficeAI 插件接入3.1.1 下载与安装插件3.1.2 配置 API 密钥 3.2 VBA 宏接入3.2.1 启用开发者工具3.2.2 调整信任设置3…