1.亿级积分数据分库分表:总体方案设计

news2024/9/26 1:23:54

项目背景

        以一个积分系统为例,积分系统最核心的有积分账户表和积分明细表:

  • 积分账户表:每个用户在一个品牌下有一个积分账户记录,记录了用户的积分余额,数据量在千万级
  • 积分明细表:用户每次积分发放、积分扣减、积分退款、积分过期都会产生一条积分明细,积分明细的数据量很大在亿级别

        随着业务的增长、时间的推移,积分明细的数据量越来越多,单表数据量太大,产生很多问题:慢SQL,加字段、索引比较耗时(虽然可以用MySQL8.0的新特性INSTANT算法加字段),统计查询很慢,数据库CPU压力大等

一、为什么要选择分表

        目前积分系统的积分明细数据现存几亿条,每日新增积分明细数据大几十万,并且随着活动的接入还在逐渐递增,慢慢的带来了很多问题,需要进行优化处理。

        历史数据归档不行吗

        因为系统积分规则规定积分有效期两年,并且积分扣减、退款、过期等操作需要对积分明细溯源,最近两年的积分明细数据也有几个亿,即使将两年前的冷数据归档,也无法解决积分明细单表几亿数据量的问题。

        根据积分现有数据量以及日增长量进行评估,未来3-5年内单数据库实例能够满足积分数据的存储,并且积分系统的写入TPS单实例可以支撑,本次积分决定只分表不分库。

        什么情况适合用数据归档?

        如果能把历史冷数据归档,热数据一两亿左右、读写并发不太高的情况下,利用好数据库索引、数据库配置高一些完全可以不用分表,采用历史数据归档也可以解决很多问题。但是大表还是有一些其他的问题,比如加字段比较耗时。

        分库分表有很多问题

        网上动不动就说超过2000万数据就要分库分表并不太对,在单表数据一两亿、并发不是很高、利用好数据库索引的情况下,MySQL数据库配置高一点是完全可以扛得住的。

        而且能不分库分表就不要分库分表,分库分表会产生很多问题,没有其他优化手段了再进行分库分表。分库分表可能会产生的问题如下:

  • 分布式ID问题
  • 分片键选择问题
  • 分库分表算法问题
  • 容量不够了扩容问题
  • 分布式事物问题
  • 统计查询分析问题
  • 数据迁移问题
  • 灰度验证问题
  • 数据校验问题
  • ................

二、分库分表组件

        分库分表组件选择Sharding-JDBC,因为目前该项目文档较为丰富、社区活跃度高、无中心化、性能相较于proxy方式性能更好,对于开发来说使用更为灵活可控。官网地址Apache ShardingSphere

三、分多少张表,分片键和分片算法

        需要拆分的表:point_info(积分明细表)

        根据目前的数据量、单日新增的数据量来进行分析,计划分为128张表,未来3-5年内单表数据尽量不要超过2000万,后期分表数据量大了可以进行历史数据归档。

        拆分后的表为point_info[0-127],采用user_id作为分片键,选取user_id后四位取模定位到具体的分表

        table后缀 = (user_id后四位) % 128

        如果怕user_id的尾数不均匀,可以将hashcode(user_id)%128来计算分表下标

        分表数量为啥是128,不是127或者100?

        我自己的理解如下:

  • 设置为2的次幂,是程序员的习惯;
  • 好处是求余运算,可以用 num & (128-1),按位与运算求余数比除法速度快。

        如果还有其他的好处欢迎指正

四、分布式事务?

        因为只进行了分表,没有进行分库,所以没有分布式事务问题。

        假如后面进行了分库分表,可以通过将相同用户的积分账户表和积分明细表分到同一个分库中,来避免同一个用户操作账户和明细的分布式事务问题。

        shardingsphere里面也有一些分布式事务的支持,比如XA,Seata框架的AT模式等

五、分布式ID

        原来单表时主键采用MySQL自增id,分表之后再使用自增id会导致不同表主键值重复,可以使用雪花算法、美团的Leaf等生成分布式ID,也可以自定义实现。

        注意:原生雪花算法有时钟回拨问题、低频场景下生成的id都是偶数的问题,需要进行优化一下,感兴趣的话可以看下我的另一篇博客 雪花算法生成分布式ID源码分析及低频场景下全是偶数的解决办法

六、总体计划

简要描述一下整个流程:

线上库新的分表创建配置完成,然后按照下面的步骤执行:

  1. 改造双写代码预发测试(多种case跑一下,双写开关等校验),没问题发布上线,上线时双写开关默认关闭,可以通过配置中心动态开启,打开双写开关(新表写入失败先忽略,因为更新和删除操作会因为新表数据不存在而失败),记录双写开始时间点A
  2. 将老表的积分明细的createTime小于等于双写开始时间点A+5分钟(防止时间不同步导致少迁移数据,预留一些缓冲时间)的数据进行全量迁移到分表
  3. 新老数据全量数据校验,查看数据是否一致;同时定时任务每隔一小段时间进行增量校验,增量数据因为读取新老数据存在短暂时间差可能会瞬时不一致,这种数据隔一段时间再次校验,多次校验还不一致的数据进行数据订正(老表数据覆盖到新表数据)
  4. 改造代码,添加双读的逻辑上线(读新表的开关默认关闭)
  5. 低流量节点(凌晨过后)进行白名单、灰度切流userId%10000,进行验证,逐步流量打开,持续观察
  6. 双写开关切到新表,保证只写新表(也可以继续写老表一段时间,或者创建一个新表往老表同步的canal任务,方便回滚),完成数据迁移方案
  7. 系统稳定运行一段时间,迁移&双写代码下线,老表进行资源释放

        为什么没有采用全量同步+canal增量同步方式,这种方式不是比双写实现更简单吗?怎么进行双写?双写有什么好处?后面会继续写一篇单独介绍。

七、双写

        双写改造点:增、删、改

        双写主要是为了避免数据延迟问题,但是双写无法保证两个数据源的事物一致性问题,极端情况下数据不一致(数据校验订正任务解决)

双写开关有两个(通过配置中心实时切换):

  1. 写老表开关:默认开启,新表写入没有问题时可以进行关闭,也可以继续写一段时间老表
  2. 写新表开关:默认关闭,需要开启时打开

        新老表的开关同时打开时,表示要进行双写

通过配置中心动态进行切换,双写期间需要注意的问题如下:

  • 对写新表操作需要记录日志
  • 新表不要求一定写成功(不影响服务,记录错误日志告警通知等,有数据校验订正任务兜底)
  • 双写事物回滚:极端情况下可能新表写成功了、老表数据事物回滚了(数据双向核对校验)

八、数据迁移

        首先我们程序会打开双写,然后需要将我们数据库已经存在的数据进行批量的全量迁移,在这一过程中我们需要不断的进行数据校验。当我们校验基本问题不大的时候,然后进行切流操作,直到完全切流之后,我们就可以不用再进行数据校验。

1)全量同步

  • 全量迁移:将老表的积分明细的createTime小于等于双写开始时间点A+5分钟(防止时间不同步导致少迁移数据,预留一些缓冲时间)的数据进行全量迁移
  • 全量默认走备库查询,目标端写入的是主库,防止影响主库读写,这里需要注意一下读写的qps,以免对线上服务造成影响。

        注意一下存量数据迁移完成的时间,存量数据迁移可以多线程执行,计算公式如下:

消耗小时数= 数据总量 / (3600*写入tps*任务线程数)

2)增量同步

        因为我们代码使用了双写,双写自动做了增量同步,所以不需要单独做增量同步的操作了

九、数据校验

        验证老的单表和新的分表的数据是否一致,也是全量订正服务必须的前置操作

全量校验&增量校验&抽样校验

  • 全量校验:历史全量数据校验
  • 增量校验:定时任务每隔一段时间校验该段时间内的增量数据校验是否一致
  • 抽样校验:可以按照user_id或者业务类型等自定义校验

校验过程

        需要注意:校验任务注意不要影响线上运行的服务,通常校验任务会写很多批查询的语句,会出现批量扫表的情况,如果代码没有写好很容易导致数据库挂掉。

        对账标准:老的单表和新的分表中数据保持一致(所有字段或者核心字段)

        对账流程:通过定时任务轮询+监听数据库binlog执行已经完成迁移的用户在新老积分明细表的数据一致性。需要注意的是由于读取新老库有先后顺序,所以产生瞬时的数据不一致,对于这种问题可以采用对账重试,只要保证最终一致即可。

数据双向核对

        单表核对多表,多表核对单表。原因是双写时无法完全控制事物一致性问题,所以要对单表和分表进行双向核对,具体怎么核对后面会再写一篇进行详细介绍。

校验结果

        校验结果:差异、缺失、多出

数据订正

  • 通过订正服务可以将不一致的老的单表数据和新的分表数据进行数据订正,保证一致性。
  • 使用订正服务前必须进行校验服务。

十、切流量

切流代码编写,切流量是针对的积分明细的查询操作

  • 对所有查询接口进行整理
  • 读取新老数据配置开关,可以通过配置中心实时修改
  • 添加验证白名单列表(userId)
  • 根据白名单、userId后4位取模进行灰度,动态获取查询时用的数据源。
  • 命中灰度时,查询走新分表数据源,查新表数据,同时也查询老表数据,比对新老表数据是否一致,如果一致返回新表数据,如果不一致返回老表数据,同时发送MQ信息对该用户数据进行数据校验、比对、订正。

        切流过程采用逐步放量的形式,灰度方式很多,我们采用的是先白名单验证,然后用户ID取模10000逐步放量的方式。灰度切流验证:万分之1-1%-5%-10%-50%-100%切流

        关于灰度验证、切流的过程后续会再单独写一篇细化介绍一些。

十一、收尾

        直到切流到100%,继续运行一段时间,然后观察各个业务后续工单反馈情况和各个系统预警&日志;

        切写开关到新的分表上面,可以继续写入老表一段时间,如果出现问题可以切回老表

        对新表进行性能压测,确保新表的稳定性

十二、OLAP数据统计分析

        对于积分的数据报表、统计查询分析等需求,由于分表后数据分散到了多个分表上面,如果要再进行统计查询的话需要查询所有的分表,效率太低了,可以使用一些非关系型数据库,比如ES、ClickHouse等。

        比如可以使用ClickHouse,将多个分表的数据同步聚合到ClickHouse上面,利用ClickHouse进行统计分析、出一些数据报表等。

        本篇博客从整体上介绍了一个完整的积分明细分表的实施方案,里面有一些方面介绍的不是很详细,后面会单独的针对一些关键点进行介绍:

  • 怎么进行代码双写,双写有什么好处,为什么没有使用数据库binlog增量同步
  • 怎么进行数据双向校验
  • 怎么进行灰度验证,怎么进行切流
  • .........

        如果有写得不对的地方,或者您有更好的方案,欢迎讨论指正

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

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

相关文章

基于springboot+vue的在线考试与学习交流平台

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

猫猫与数列

来源&#xff1a;牛客网 示例1 输入 2 2 输出 5 示例2 输入 999999998 2 输出 3 示例3 输入 10 18 输出 3 #include <bits/stdc.h>#define endl \n using ll long long; typedef unsigned long long ull; using namespace std; void GordenGhost(); l…

科技企业如何做到FTP数据安全保护

在数字化浪潮的推动下&#xff0c;科技企业的数据已成为推动创新、提升效率、增强竞争力的核心资源。数据的重要性不言而喻&#xff0c;它不仅包含了客户信息、市场分析、产品设计等关键信息&#xff0c;更是企业宝贵的资产。然而&#xff0c;随着数据量的激增&#xff0c;数据…

《PyTorch深度学习实践》第十二讲循环神经网络基础

一、RNN简介 1、RNN网络最大的特点就是可以处理序列特征&#xff0c;就是我们的一组动态特征。比如&#xff0c;我们可以通过将前三天每天的特征&#xff08;是否下雨&#xff0c;是否有太阳等&#xff09;输入到网络&#xff0c;从而来预测第四天的天气。 我们可以看RN…

数据结构从入门到精通——顺序表

顺序表 前言一、线性表二、顺序表2.1概念及结构2.2 接口实现2.3 数组相关面试题2.4 顺序表的问题及思考 三、顺序表具体实现代码顺序表的初始化顺序表的销毁顺序表的打印顺序表的增容顺序表的头部/尾部插入顺序表的头部/尾部删除指定位置之前插入数据和删除指定位置数据顺序表元…

MySQL 主从读写分离入门——基本原理以及ProxySQL的简单使用

一、读写分离工作原理 读写分离的工作原理&#xff1a;在大型网站业务中&#xff0c;当单台数据库无法满足并发需求时&#xff0c;通过主从同步方式同步数据。设置一台主服务器负责增、删、改&#xff0c;多台从服务器负责查询&#xff0c;从服务器从主服务器同步数据以保持一…

【ArcGIS】渔网分割提取栅格图+网格化分析图绘制

ArcGIS按渔网分割提取栅格图并绘制网格化分析图 准备数据操作步骤步骤1&#xff1a;创建渔网&#xff08;Create Fishnet&#xff09;步骤2&#xff1a;栅格数据处理步骤3&#xff1a;栅格插值步骤4&#xff1a;数据关联 参考 网格化的目的是让各个数据更加标准化的进行统计。因…

FlinkSQL ChangeLog

01 Changelog相关优化规则 0101 运行upsert-kafka作业 登录sql-client&#xff0c;创建一个upsert-kafka的sql作业&#xff08;注意&#xff0c;这里发送给kafka的消息必须带key&#xff0c;普通只有value的消息无法解析&#xff0c;这里的key即是主键的值&#xff09; CREA…

linux系统Jenkins工具参数化构建

Jenkins参数化构建 web服务器jenkins服务器编写主机清单编写脚本代码 jenkins服务web页面操作 web服务器 下载nginx 下载gitcd /usr/share/nginxrm -rf htmlgit clone http://root:Qq123456192.168.188.176/ximu/test-nginx.gitmv test-nginx/ htmljenkins服务器 下载ansible…

前端Vue自定义勾选协议组件的开发与应用

摘要&#xff1a; 随着前端技术的不断发展&#xff0c;用户体验成为了软件开发中的关键要素。在登录、注册等场景中&#xff0c;勾选协议是常见的需求。本文旨在介绍一款基于 Vue.js 的自定义勾选协议组件的开发与应用&#xff0c;该组件适用于多种场景&#xff0c;并且具备良…

虚拟机部署Sentry步骤,国内地址

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

【计算机网络】TCP 如何实现可靠传输

TCP通过三次握手建立连接&#xff0c;四次挥手释放连接&#xff0c;确保连接建立和连接释放的可靠。 序列号、检验和、确认应答信号、重发机制、连接管理、窗口控制、流量控制、拥塞控制 标准回答 可靠传输就是通过TCP连接传送的数据是没有差错、不会丢失、不重复并且按序到达的…

【C++ map和set】

文章目录 map和set序列式容器和关联式容器键值对setset的主要操作 mapmap主要操作 multiset和multimap map和set 序列式容器和关联式容器 之前我们接触的vector,list,deque等&#xff0c;这些容器统称为序列式容器&#xff0c;其底层为线性序列的的数据结构&#xff0c;里面存…

Mac专用投屏工具AirServer 7.27 for Mac中文版2024最新图文教程

Mac专用投屏工具AirServer 7.27 for Mac中文版是一款适用于Mac的投屏工具&#xff0c;可以将Mac屏幕快速投影到其他设备上&#xff0c;如电视、投影仪、平板等。 Mac专用投屏工具AirServer 7.27 for Mac中文版具有优秀的兼容性&#xff0c;可以与各种设备配合使用。无论是iPhon…

[方案实操]中国电子副总陆志鹏:《数据资产化路径的思考与探索》演讲实录和解析

中国数字经济发展和治理学术年会&#xff08;2023&#xff09;上&#xff0c;中国电子党组成员、副总经理&#xff0c;50人论坛委员陆志鹏先生《数据资产化路径的思考与探索》为题进行了主旨演讲&#xff0c;提出“如果简单把资源进行评估定价&#xff0c;价值非常有限&#xf…

STM32标准库开发—实时时钟(BKP+RTC)

BKP配置结构 注意事项 BKP基本操作 时钟初始化 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);PWR_BackupAccessCmd(ENABLE);//设置PWR_CR的DBP&#xff0c;使能对PWR以及BKP的访问读写寄存器操作 uint16_t ArrayW…

springboot基于web的网上摄影工作室的开发与实现论文

网上摄影工作室 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了网上摄影工作室的开发全过程。通过分析网上摄影工作室管理的不足&#xff0c;创建了一个计算机管理网上摄影工作室的方案。文章介绍了网上摄影工…

详细介绍如何用windows自带Hyper-V安装虚拟机(windows11和ubuntu22)

通过系统自带的hyper-v安装windows11&#xff0c;舒服又惬意&#xff0c;相比用第三方虚拟机软件速度快很多。 硬件准备 准备 系统需要符合能安装 Hyper-V 的最低要求windows版本含Hyper-V的功能 电脑空间 电脑要有足够的空间来安装你这个虚拟机。根据自己的磁盘容量情况来规…

鸿蒙系统的开发与学习:一、安装工具与处理报错

前言&#xff1a; 鸿蒙系统的学习与记录。 1 、使用开发工具&#xff1a;deveco-studio 1&#xff09;这个是工具的安装 2&#xff09;这个是工具包&#xff0c;里面包含了 obpm&#xff0c;如果你装不上这个&#xff0c;可以使用工具包内部的 2、安装 官方安装教程&#xff…

泰迪智能科技企业数据挖掘平台使用场景

企业数据挖掘平台助力企业数据挖掘&#xff0c;数据挖掘平台也在多个领域发挥着重要的作用。 企业数据挖掘平台具有数据抓取、数据清洗、数据分析、机器学习等多项功能&#xff0c;广泛应用于企业的各个领域&#xff0c;包括&#xff1a;金融行业、医疗行业、交通领域、教育、制…