在支付系统中,我们记账模块很有可能出现并发的情况,这时,程序员多半会采用Lock,Synchronized等限制多线程的做法,将并行程序逻辑限制为串行程序逻辑。这样对于单点的系统当然可以使用,但是当集群模式出现时是不是出现了问题呢?
现与大家分享另一种模式,加入时间戳的概念在DB修改加入了限制,使我们程序在修改账户金额时即使出现了集群下多线程并发修改同一账户时也可以保证串行执行逻辑。只是这种“串行执行逻辑”出现在数据库上。
(ps:时间戳的值也可以采用分布式缓存中间件Redis incr计数器进行递增。。保证集群模式下不重复即可。)
下面看伪码,欢迎吐槽。。。
package com.test;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description:
* @Author mengfanzhu
* @Date 8/1/18 15:03
* @Version 1.0
*/
@Slf4j
public class Test {
public static void main(String[] args) {
updateAccount("13300000000");
}
/**
* 更新账户金额
*/
public static void updateAccount(String mobile) {
int i = 0;
BigDecimal newAmount = new BigDecimal("100.00");
while (i == 0) {
//get-updAccountInfoModel{"id":"123", "mobile":"13300000000","amount":"12.10","updateTime":"1533107958723"}
AccountInfoModel updAccountInfoModel = getAccountByMobile(mobile);
updAccountInfoModel.setAmount(newAmount);
updAccountInfoModel.setNextUpdateTime((new Date()).getTime());
//update-sql = "update t_account set update_time = #{nextUpdateTime} ,amount = #{newAmount} where id = #{id} and update_time = #{updateTime}
i = update(updAccountInfoModel);
if (i == 0) {
log.warn("update account fail:{}", mobile);
}
}
}
}
@Data
class AccountInfoModel {
private Long id;
private String mobile;
private BigDecimal amount;
private Long updateTime;
private Long nextUpdateTime;
}
END~