一篇,快速搞懂各种重试策略
业务场景:
1、第三方系统的用户在我方系统产生了订单记录,我方系统需要将订单信息同步给第三方系统
2、考虑到网络等不可抗力因素,希望同步失败后能够重试,又不希望无限重试,比如希望只重试3次,所以需要持久化入库,并且表结构如下:
ID | 订单明细 | 重试次数(count) | 是否同步(sync) |
---|---|---|---|
1 | {“orderId”:“123456”} | 1 | 0 |
重试时查询条件为:
where count <= 3 and sync = 0
3、因为三方系统一旦发生故障,短时间内不一定能恢复,所以重试的时候希望不要马上重试,如果能等一会(比如1小时)重试这条数据就好了,所以表结构可以如下:
ID | 订单明细 | 重试次数(count) | 是否同步(sync) | 最后一次同步时间(last_sync_time) |
---|---|---|---|---|
1 | {“orderId”:“123456”} | 1 | 0 | 2020-03-22 01:00:00 |
重试时查询条件为:
where count <= 3 and sync = 0 and TIMESTAMPDIFF(minute,last_sync_time,now())>=60
4、一般来说同步的时间不用那么精确。所以为了查询效率,可以增加字段last_sync_hour结构为:
ID | 订单明细 | 重试次数(count) | 是否同步(sync) | 最后一次同步时间(last_sync_time) | 最后一次同步小时(last_sync_hour) |
---|---|---|---|---|---|
1 | {“orderId”:“123456”} | 1 | 0 | 2020-03-22 01:00:00 | 431487 |
重试时查询条件为:
where count <= 3 and sync = 0 and last_sync_hour<#{curHour}
| * 将字段运算替换为条件匹配
5、如果三方系统要故障一整天,我方系统1小时重试一次需要24次,系统成本比较高,如果8小时同步一次,第三方系统又觉得同步得慢了,所以我希望重试的次数越多,下一次间隔时间就越长,指数级增长,比如:
重试次数 | 距上次同步的时间间隔 |
---|---|
1 | 距0次间隔2小时 |
2 | 距1次间隔4小时 |
3 | 距2次间隔8小时 |
|| 重试3次,首次为2点,最后一次重试时间为2+4+8=14点,重试4次时间范围就能跨越24小时
重试时查询条件为:
where count <= 3 and sync = 0 and last_sync_hour<= #{curHour}-1 << count
将数据运算外置后,可以优化为:
int count = 3;
int currSyncHour = #{curHour}-1<<count;
where count <= #{count} and sync = 0 and last_sync_hour<= #{currSyncHour}