XXL-Job分片广播仅广播shardIndex和shardTotal参数,不自动切分数据;业务需在JobHandler中主动获取参数并实现分片逻辑,否则易导致重复或漏处理。

分片广播不是“开个开关”就自动并行
分片广播模式本身不处理数据切分逻辑,它只负责把 shardIndex 和 shardTotal 这两个参数广播给所有在线执行器。真正决定“哪台机器查哪些数据”的,是你自己写的 SQL 或业务代码。很多团队上线后发现数据重复或漏处理,问题几乎都出在这一步——误以为配置了路由策略就等于自动分片了。
必须在任务 Handler 里主动读取分片参数
XXL-JOB 不会在后台帮你改 SQL 或拆数据集,你得在 @XxlJob 方法体内显式调用工具类获取分片上下文:
int shardIndex = XxlJobHelper.getShardIndex(); int shardTotal = XxlJobHelper.getShardTotal();
常见错误包括:
- 直接硬编码
shardTotal = 5,而实际执行器数量动态扩缩容后值已变 - 用
ShardingUtil.getShardingVo()却没引入xxl-job-core依赖,导致空指针 - 在 Spring Bean 初始化阶段提前调用
getShardIndex(),此时上下文尚未注入,返回 -1
分片逻辑写法决定是否真并发、是否数据安全
最常用也最稳妥的是基于主键取模,但要注意边界和类型:
- MySQL 中用
id % #{shardTotal} = #{shardIndex},前提是id是连续正整数;若为 UUID 或雪花 ID,需先转成数值或改用范围分片 - 分页查询时不能简单套用
LIMIT offset, size,因为不同分片的 offset 含义完全不同;应结合WHERE id > ? AND id % ? = ?做游标式扫描 - 如果任务支持重启,必须记录每个分片的最新处理位点(如最大已处理
id),否则重跑会重复消费
执行器数量变化时,分片总数不会自动同步
shardTotal 的值由调度中心在每次触发时根据「当前注册的在线执行器数量」动态计算并下发。但它只反映那一刻的状态:
- 任务运行中某台执行器宕机,该分片不会被其他节点接管,对应数据块将丢失
- 新扩容执行器后,要等下一次调度才生效;若想立刻生效,需手动触发一次“强制广播”(控制台操作)
- 测试环境常只起 1 台执行器,
shardTotal恒为 1,根本看不出分片效果——务必在至少 2 台真实机器上验证
真正难的从来不是怎么配,而是怎么让每台机器知道自己该干哪一段、干完有没有人接着干、出错了从哪继续——这些细节藏在你的 DAO 层和状态管理里,不在 XXL-JOB 控制台里。











