type
status
date
slug
summary
tags
category
titleIcon
password
icon
calloutIcon
3️⃣
主要技术点:动态表名分表,XXL-JOB分区任务与避免重复执行,Redis的Bitmaps与Zset使用,业务点:积分记录定时分表,榜单持久化,点赞记录持久化。

Redis客户端选择

IDEA

  • 使用中发现IDEA自带的Redis连接功能有限
  • 比如不能对zset里面的数据按字段选择排序
notion image
  • 无法查看bitmap的数据
notion image
  • 只能靠BITFIELD返回的结果估计(此命令Redis以10进制返回结果)
notion image
notion image
notion image

Another Redis Desktop Manager

notion image
  • 可以根据字段做排序
notion image
  • 以二进制显示bitmap数据
notion image
notion image

Tiny RDM

  • 界面更好看的客户端,但是通过GUI直接更改bitmap数据的时候存在问题,比如将某一偏移位置值改为1,往后的所有数据也都全部设置为1了。
notion image

点赞记录的持久化方案

核心思路

  • 基本方法:通过分离Redis里存放更新数据的集合与全量数据的集合来进行增量更新。
  • 数据结构选择:由于需要批量取出数据并保证数据唯一不重复,采用Zset存放更新部分数据,出于方便,将新增的数据放至NEW中,删除的数据放至DEL中。

流程图

notion image
  • 部分环节trick:1.点赞/取消中,同时发送ZSCORE与ZINCRBY,通过ZSCORE返回值(数据或nil)可以区分点赞数是否已在Redis中,如果返回不为null,那么数据在Redis中,业务已经结束,反之则查询数据库,将数据库结果ZINCRBY上去即可。2.查询已点赞时,通过Redis中ALL判断是否有数据,同时可以通过DEL检查用户是否先前取消了点赞,减少二次检查的查询量。3.定时同步操作里,由于业务id没有办法给定,需要自己构造key模板,交给ScanOptions,通过 executeWithStickyConnection在长连接中不断scan各个键将数据加入集合,用于数据库一次批量处理(防止数据过多限定了一次读取的数量上限)。
新增/取消
notion image
notion image
notion image
notion image
查询点赞情况
notion image
notion image
notion image
定时同步(限制单个Key的取出数据量与总共的取出数据量)
notion image
notion image
notion image

MP动态表名

插件顺序

  • 根据官方文档的说明,需要确保插件的注册顺序。
notion image
  • 修改tj-common下MybatisPlus配置类,先注册动态表名,再注册分页,最后自动填充是自定义拦截器,补全用户信息(如果遗漏)。
  • 在传参的部分@Autowired自动注入,由于目前只有tj-learning一个服务用到,使用required = false参数,兼容其他微服务。
展开
notion image

拦截器中获取数据

  • 在tj-learning学习服务里,添加MybatisPlus动态表名拦截器配置类,对points_board积分榜单表注册对应表名处理函数,加入表名映射map,传参构造拦截器返回。
  • 拦截器不能直接被调用,但是由于流程中一直是同一线程,所以可以通过ThreadLocal暂存和获取表名数据。
notion image
展开
notion image

海量数据存储

分区(Partition)

  • 在数据库层面按照规则对表做水平拆分。
  • 以InnoDB为例,一张表的数据在磁盘上对应一个ibd文件,如果表数据过多,就会导致文件体积非常大。文件就会跨越多个磁盘分区,数据检索时的速度就会非常慢。
  • 按照某种规则,把表数据对应的ibd文件拆分成多个文件来存储。从物理上来看,一张表的数据被拆到多个表文件存储了;从逻辑上来看,他们对外表现是一张表。
  • 逻辑操作不变,MySQL底层处理上有所变更。
优势
  • 可存储超过单表上限的数据,也可存储到不同磁盘。
  • 查询时可以按规则只检索一个文件,提高效率。
  • 可多文件并行统计,提高效率。
  • 可以删除分区文件,直接清除一部分数据,提高效率。
分区方式
  • Range:按指定字段范围。
  • List:按字段枚举,需提前指定所有可能值。
  • Hash:字段hash后结果分区,数值类型。
  • Key:字段值运算结果分区,不限定字段类型。

分表

  • 在业务层面按照规则对表做水平拆分。
  • 逻辑上与物理存储上都变成多张表,需要更改CRUD语句。
优势
  • 拆分灵活,可水平,可垂直。
  • 解决数据量大或字段多的问题。
劣势
  • CRUD中需要添加判断访问哪张表。
  • 聚合操作数据合并需要额外处理。
  • 单表变多表带来的事务问题与数据关联问题。

集群与分库

  • 微服务项目模块划分,每个微服务有独立的不同业务的数据库,进行了垂直分库。
  • 对数据库做主从集群,主从数据同步,保证高可用,进行了水平扩展。
优势
  • 突破单机存储瓶颈。
  • 提高并发能力,突破单机性能瓶颈。
  • 避免单点故障。
劣势
  • 系统复杂度与成本高。
  • 主从数据一致性问题。
  • 分布式事务问题。

总结

  • 单表数据多可以先库内分表,再分库。
  • 读写压力大可以垂直分表,再读写分离集群。
  • 索引→分表/ES→分库/集群

榜单持久化

Cron表达式详细
notion image
notion image

每月初创建历史榜单分表

展开
notion image
notion image

持久化上一赛季Redis榜单数据

展开
notion image
notion image

清理Redis中的历史榜单

展开
notion image

代码

代码
  • 注意清理的XXL-JOB分片任务只应有一次业务执行。

积分记录的定时分表方案

  • 重命名方案:简单快捷
  • 延时删除:保证服务从始至终一直可用

流程图

notion image

重命名方案

展开
notion image
notion image

延迟任务方案

展开
notion image
notion image
notion image
notion image
notion image
notion image
 

Bitmaps类型使用

常用命令

  • 主用setbit和bitfield,相关使用(Spring Data Redis)参见代码模板。
notion image

业务相关

  • 获取本月至今的签到详情:BITFIELD key GET u[dayOfMonth] 0
  • 获取连续签到天数:通过从最后一次签到向前统计,直至第一次未签到,计算总的签到次数,代码实现上从后向前遍历每个bit:循环&1,得最后一bit,循环无符号>>>右移动1位,重复进行。

Zset类型使用

常用命令

notion image

业务场景

  • 实时排行榜

代码模板

Spring Data Redis Pipeline模板
notion image
Spring Data Redis BitMap操作模板
notion image
notion image
notion image
Mybatis注解中多值SQL模板
notion image

其他注意事项

消息队列传递数据的类型

  • 消息队列API需要生产者和消费者数据类型一致,否则可能出现消息失败,送到error去重试。当时传递数据写成了Integer,类型错误导致消息错误。
案发现场
  • 😅因为API里不限定消息类型,这里消息失败后断点调试问题又多发了几次,消息一直重试给电脑整蓝屏了,强制重启之后虚拟机MySQL Docker容器开始无限重启(启动就是restarting状态),整的数据库用不了,直接重装虚拟机了。
  • 善用VMware快照,多备份虚拟机状态用于回退。
notion image

数据库查询返回可为null值的类型

  • MySQL SUM函数在不满足条件的情况下返回不为0,为null,需要用Integer包装类接收结果。
notion image
notion image
  • 采用int接收出现了数据库操作正常(日志正常打印)下的业务失败。
案发现场
注:上方枚举类型传递mapper中,放入sql语句自动转为value。

修改points_board表中类型

  • 在Redis查询到以前赛季中有的数据实际上已经达到200以上,但数据库对应表的points_board在积分值字段仍采用的tinyint,考虑到之前的积分值一天有几十分的上限设置,十分不合理,将其更改为int类型,而且本身在PO类代码中映射也是Integer。
点击查看points_board定义图
notion image
点击查看Redis旧赛季数据
notion image
点击查看points_board PO定义代码

测试数据生成

  • 原季度数据只到2023年9月,测试同步上一赛季的数据时业务需要获取查询季度id,此处添加测试数据至2030年。
展开
notion image
  • 测试重命名方案实现积分记录分表存档的开销时间是否可以接受,插入一百万随机数据。
展开
notion image

Mybatis DDL语句使用事项

  • Mybatis注解里一次性写多条DDL会失效。
  • 个人理解Mybatis一个语句应该是在一次事务提交里面,但是DDL需要每次直接提交,所以放一起多条会不生效,日志反馈就是没有第三行的返回值(单个执行就有)。
  • 总结下来DDL单句一个函数,然后DDL和DML分开不同的函数写(参照上方写法)。
notion image
 

Day06练习参考实现

完善互动问答功能

  • 前文复盘已经实现

点赞业务类型的动态配置

展开
在Nacos自行新添配置,后缀.yml,.yaml,或者没有也可以
notion image
参考版本
notion image
在bootstrap文件里添加配置
notion image
可以添加到常量里使用
notion image
用${}获取配置,:为设置默认值,注意层级与文件内容保持一致
notion image

点赞记录持久化

  • 参见上方对应标题部分

XXL-JOB定时任务

  • 可以在Day08 20p视频里快速入门,以下提供参考实现
展开
Java代码部分
notion image
notion image
XXL-JOB控制台
notion image
notion image

Day07练习参考实现

查询签到记录

展开
notion image

完善积分功能

展开
notion image
notion image

查询赛季列表功能

展开
notion image

Day08练习参考实现

查询积分榜

展开
notion image
notion image
notion image
notion image

清理积分明细

  • 见上方积分记录定时分表方案

了解更多

 
技术重点在三个方面:幂等性保障|延迟任务|合并写,除去这一部分,其他主要为基本业务,简单且量大,对初学友好,如果不是第一次做微服务项目,选看这三个方面就可以跳了。文中图片与代码块较多,善用展开懒加载。
天机学堂Day02-Day05复盘-课表|计划|进度|问答业务天机学堂Day09-Day12复盘-优惠劵业务
Loading...
CamelliaV
CamelliaV
Java;CV;ACGN
最新发布
单例模式的四种写法
2025-4-24
体验MCP
2025-4-24
MetingJS使用自定义音乐源-CF+Huggingface部署
2025-4-2
博客访问站点测速分析与对比
2025-3-26
前端模块化
2025-3-16
Voxel2Mesh相关论文精读与代码复现
2025-3-15
公告
计划:
  • LLM相关
  • 支付业务 & 双token无感刷新
  • (线程池计算优惠方案)天机学堂Day09-Day12复盘-优惠劵业务
  • (业务复盘,技术汇总)天机学堂完结复盘
  • hot 100
 
2024-2025CamelliaV.

CamelliaV | Java;CV;ACGN