冷热数据分离

news2024/11/27 11:33:29

优质博文:IT-BLOG-CN

一、背景

随着机票业务的快速发展,订单量持续增长对业务性能带来影响,需要进行冷热数据分离。目前机票订单模块主要使用Mysql(InnoDB)作为数据库存储,历史订单信息状态修改频率低并占用大量数据库存储空间,期望历史数据与生产最新的数据进行分离,当前数据库保留最近一个月的数据作为热库,历史交易存在另一个库作为冷库。减少因在线存储空间不足扩容导致停服不可用的时长。

如何判断一个数据是冷数据还是热数据?
需要根据自己业务系统来区分了,一般而言是根据主表中的一个或者多个字段进行标识区分,比如订单的时间,这个是时间维度,可以将3个月之前的数据定义为冷数据,最近3个月的数据定义为热数据。当然也可以是状态维度,比如订单的状态,已完结的订单定义为冷数据,未完结的订单定义为热数据。同样的也可以将时间维度和状态维度组合起来,比如下单时间大于3个月且订单状态为已完结的定义为冷数据,反则为热数据。

我的冷热数据怎么拆分的:已过起飞时间 + 订单状态=“完成”的数据都是冷数据,其余为热数据。

二、方案选型

业务代码修改

这种方案是在业务代码层面判断是否进行冷热数据分离,对代码的侵入性比较高,在数据修改时触发冷热分离。因机票QPS很高,如果更新状态时,需要进行进行冷热数据分离,删除热库中的数据,并将数据写入冷库中,需要使用到分布式事务。会增加系统和数据库的压力。不适用

监听binlog日志

需要监听binlog日志的方式进行触发,当订单状态修改了,则触发冷热分离。比较适合实时性要求高的系统,这里虽然不会影响业务的响应时间。但是冷热数据分离的操作实时操作的,会给数据库造成压力。不适用,但是有用

怎么读取binlog中的内容,我们通过公司内部开发的DRC服务,这里简单看下重要流程:
【1】在pom.xml中添加MySQL Binlog Connector Java的依赖

<dependency>
    <groupId>com.github.shyiko</groupId>
    <artifactId>mysql-binlog-connector-java</artifactId>
    <version>0.25.0</version>
</dependency>

【2】连接MySQL并读取binlog,注册了一个事件监听器来处理WriteRowsEventData事件。还可以根据需要处理其他类型的事件,例如UpdateRowsEventDataDeleteRowsEventData分场景进行业务处理。

import com.github.shyiko.mysql.binlog.BinaryLogClient;
import com.github.shyiko.mysql.binlog.event.*;

public class BinlogReader {

    public static void main(String[] args) throws Exception {
        String hostname = "localhost";
        int port = 3306;
        String username = "root";
        String password = "password";

        BinaryLogClient client = new BinaryLogClient(hostname, port, username, password);

        client.registerEventListener(event -> {
            EventData data = event.getData();
            if (data instanceof WriteRowsEventData) {
                WriteRowsEventData writeRowsEventData = (WriteRowsEventData) data;
                System.out.println("Write event: " + writeRowsEventData);
                // 处理写入事件
                handleWriteEvent(writeRowsEventData);
            } else if (data instanceof UpdateRowsEventData) {
                UpdateRowsEventData updateRowsEventData = (UpdateRowsEventData) data;
                System.out.println("Update event: " + updateRowsEventData);
                // 处理更新事件
                handleUpdateEvent(updateRowsEventData);
            } else if (data instanceof DeleteRowsEventData) {
                DeleteRowsEventData deleteRowsEventData = (DeleteRowsEventData) data;
                System.out.println("Delete event: " + deleteRowsEventData);
                // 处理删除事件
                handleDeleteEvent(deleteRowsEventData);
            }
        });

        client.connect();
    }

    private static void handleWriteEvent(WriteRowsEventData eventData) {
        // 在这里处理写入事件的业务逻辑
        // 例如:将数据写入另一个数据库或消息队列
    }

    private static void handleUpdateEvent(UpdateRowsEventData eventData) {
        // 在这里处理更新事件的业务逻辑
        // 例如:更新缓存或同步到另一个系统
    }

    private static void handleDeleteEvent(DeleteRowsEventData eventData) {
        // 在这里处理删除事件的业务逻辑
        // 例如:从缓存中移除数据或同步到另一个系统
    }
}

WriteRowsEventData类通常包含以下属性:
【1】tableId:表示发生写入操作的表的ID,它通常由MySQL内部生成,用于在二进制日志中快速查找表的元数据。
【2】includedColumns:一个位图,表示哪些列包含在写入操作中。位图中的每一位对应一个列,值为1表示该列包含在写入操作中,值为0表示该列不包含在写入操作中。
【3】rows:一个列表,包含所有被写入的行的数据。每一行的数据通常以数组的形式存储,数组中的每个元素对应表中的一个列值。这些数据通常是经过编码的,需要根据表的元数据进行解码。

举个例子,如果你在MySQL中有一个表users,包含三个列idnameemail,并且你插入了一行数据(1, 'Alice', 'alice@example.com'),那么WriteRowsEventData可能会包含如下信息:
【1】tableId:假设为1234
【2】includedColumns:位图表示三个列都包含在写入操作中。
【3】rows:包含一个数组[1, 'Alice', 'alice@example.com']

定时任务

该方案可以根据“起飞时间”进行区分,同时可以避免业务高峰期,并且与业务代码进行解耦。适用,结合binlog,每次获取1000条数据分批处理

我们的方案

监听binlog日志,当订单号状态发生变化,并且已过起飞时间时,将订单号存放至MongDB中,夜间2点批量读取MongoDB中的订单号执行数据冷热数据分离业务逻辑。

我们这里时存储在MongDB后期消费,部分系统是通过Kafka进行消息实时消费的,定时任务校验数据的一致性,对遗漏的数据进行校验。批量查询也是根据场景,可能需要对冷热数据库一并查询,需要封装统一的接口方法,当冷热数据存在冲突时,以热库的数据为准。

特殊场景处理逻辑:
【1】冷库数据理论上不存在更新操作,但是部分业务场景特殊,需要对冷库中的数据先进性Delete操作再进行Insert操作,而不是Update操作。这里场景接入的是Kafka
【2】当冷热库存在相同的数据时,以热库数据为准。冷库的数据来源只有热库数据同步到冷库。批量查询如果对顺序由要求时,业务代码查询到数据后,需要根据需求在内存中进行排序。

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

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

相关文章

第69期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以找…

LeetCode 1928.规定时间内到达终点的最小花费:动态规划

【LetMeFly】1928.规定时间内到达终点的最小花费&#xff1a;动态规划 力扣题目链接&#xff1a;https://leetcode.cn/problems/minimum-cost-to-reach-destination-in-time/ 一个国家有 n 个城市&#xff0c;城市编号为 0 到 n - 1 &#xff0c;题目保证 所有城市 都由双向道…

Apache DolphinScheduler社区9月进展记录

各位热爱 Apache DolphinScheduler 的小伙伴们&#xff0c;社区 9 月月报更新啦&#xff01;这里将记录 Apache DolphinScheduler 社区每月的重要更新&#xff0c;欢迎关注&#xff01; 月度 Merge Star 感谢以下小伙伴上个月为 Apache DolphinScheduler 做的精彩贡献&#x…

数据结构前置知识(上)

1. 初识集合框架 1.1 什么是集合框架 在了解集合框架之前,我们先来认识一下数据结构,所谓数据结构就是描述和组织数据的一个东西. 那什么是集合框架呢?在java里面集合框架(Java Collection Framework),又被称为容器container,说白了就是很多个接口,抽象类,实现类组成的一个包,…

Node脚本实现批量打包Vue项目(child_process子进程、window)

前言 前几天用pnpmworkspace实现了monorepo&#xff0c;也就是单仓库多个项目&#xff0c;并且互相之间可能存在一定的联系。所以就存在一个打包的问题&#xff0c;也就是说&#xff0c;我想在打包某个特定子项目时&#xff0c;其他项目也执行build的命令。主要用到的是node的…

字节跳动推机器人大模型GR-2 展现智能自主操作新高度

字节跳动研究团队近日推出的第二代机器人大模型GR-2&#xff08;Generative Robot2.0&#xff09;正在引发业界广泛关注。这款智能机器人不仅标志着机器人大模型技术的重大突破&#xff0c;更预示着智能机器人应用即将迎来一个全新纪元。 GR-2的独特之处在于其创新的学习方式。…

力扣之1355.活动参与者

题目&#xff1a; Sql 测试用例&#xff1a; Create table If Not Exists Friends (id int, name varchar(30), activity varchar(30)); Create table If Not Exists Activities (id int, name varchar(30)); Truncate table Friends; insert into Friends (id, name, acti…

FreeRTOS学习总结

背景&#xff1a;在裸机开发上&#xff0c;有时候我们需要等待某个信号或者需要延迟时&#xff0c;CPU的运算是白白浪费掉了的&#xff0c;CPU的利用率并不高&#xff0c;我们希望当一个函数在等待的时候&#xff0c;可以去执行其他内容&#xff0c;提高CPU的效率&#xff0c;同…

朝花夕拾:多模态图文预训练的前世今生

Diffusion Models专栏文章汇总&#xff1a;入门与实战 前言&#xff1a;时间来到2024年&#xff0c;多模态大模型炙手可热。在上一个时代的【多模态图文预训练】宛若时代的遗珠&#xff0c;本文的时间线从2019年到2022年&#xff0c;从BERT横空出世讲到ViT大杀四方&#xff0c;…

通过阿里云Milvus与PAI搭建高效的检索增强对话系统

阿里云Milvus现已无缝集成于阿里云PAI平台&#xff0c;一站式赋能用户构建高性能的RAG&#xff08;Retrieval-Augmented Generation&#xff09;对话系统。您可以利用Milvus作为向量数据的实时存储与检索核心&#xff0c;高效结合PAI和LangChain技术栈&#xff0c;实现从理论到…

数学建模算法与应用 第8章 时间序列分析

目录 8.1 确定性时间序列分析方法 Matlab代码示例&#xff1a;移动平均法提取趋势 8.2 平稳时间序列模型 Matlab代码示例&#xff1a;差分法与ADF检验 8.3 时间序列的Matlab相关工具箱及命令 Matlab代码示例&#xff1a;ARIMA模型的建立 8.4 ARIMA序列与季节性序列 Matl…

【Golang】Go语言中缓冲bufio的原理解读与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Ubuntu关闭anaconda自动进入base虚拟环境

问题描述&#xff1a;安装好Anconda后&#xff0c;每次打开终端后都会自动进入到base的虚拟环境中去 直接使用通常情况下也不会有什么影响&#xff0c;但是为了避免&#xff0c;有以下两个方法&#xff1a; 1.使用conda deactivate #每次使用conda deactivate&#xff0c;退…

鸿蒙开发(NEXT/API 12)【ArkWeb接入密码保险箱】系统安全

网页中的登录表单&#xff0c;登录成功后&#xff0c;用户可将用户名和密码保存到鸿蒙系统密码保险箱中。再次打开该网页时&#xff0c;密码保险箱可以提供用户名、密码的自动填充。 手机使用场景 在网站中输入用户名、密码&#xff0c;登陆成功后&#xff0c;ArkWeb会提示将用…

线程池的核心参数——Java全栈知识(50)

线程池的核心参数 线程池核心参数主要参考ThreadPoolExecutor这个类的7个参数的构造函数 corePoolSize 核心线程数目maximumPoolSize 最大线程数目 (核心线程救急线程的最大数目)keepAliveTime 生存时间 - 救急线程的生存时间&#xff0c;生存时间内没有新任务&#xff0c;此…

前端Vue3字体优化三部曲(webFont、font-spider、spa-font-spider-webpack-plugin)

前端Vue字体优化三部曲&#xff08;webFont、font-spider、spa-font-spider-webpack-plugin&#xff09; 引言 最近前端引入了UI给的思源黑体字体文件&#xff0c;但是字体文件过于庞大&#xff0c;会降低页面首次加载的速度&#xff0c;目前我的项目中需要用到如下三个字体文…

视频理解模型

LSTM 视频分解成图片帧分别进行特征提取&#xff0c;最后把提取到的特征放到LSTM网络里提取时序信息。 3D-ConvNet 把一组图片帧作为一个整体输入到3D卷积网络中&#xff0c;由于多了一个维度&#xff0c;参数变得多&#xff0c;模型变深&#xff0c;但当时没有大量的视频数…

PMP--冲刺题--解题--71-80

文章目录 14.敏捷--合规--测试无问题&#xff0c;安全团队却拒绝部署&#xff0c;则意味着可能存在某方面安全问题71、 [单选] 一个项目经理正在为一家政府所有的公司管理一个采用迭代方法的项目。第一个有用的生产发布由三次迭代组成。每次迭代都在测试环境中成功通过了客户代…

qwt实现码流柱状图多色柱体显示

qwt实现码流柱状图多色柱体显示 1. 前言2. qt实现柱状图3.qwt基础说明3.1 qwt安装与使用3.1.1 下载qwt源码3.1.2 编译3.1.3 安装3.1.4 使用3.2 QwtPlotBarChart类3.2.1画图步骤3.2.2 specialSymbol3.3.3 barTitle4 BsBarChart定制4.1 每个柱体可以显示不同的颜色4.2 每个柱体可…

网络安全-IPv4和IPv6的区别

1. 2409:8c20:6:1135:0:ff:b027:210d。 这是一个IPv6地址。IPv6&#xff08;互联网协议版本6&#xff09;是用于标识网络中的设备的一种协议&#xff0c;它可以提供比IPv4更大的地址空间。这个地址由八组十六进制数字组成&#xff0c;每组之间用冒号分隔。IPv6地址通常用于替代…