转载请注明出处 http://www.paraller.com 原文排版地址 点击获取更好阅读体验
负载均衡架构需要解决两个问题: 频繁提交
和 全局锁
频繁提交,接口幂等性问题
独立主机: 内存锁
以往的处理方式: 内存锁
``` private static Map order_sync = new HashMap ();
/* * 订单的同步处理 * * @param order_no * @param remove * 是否在内存队列中删除 * @return 流程是否正常 / private synchronized boolean orderSync(String order_no, Boolean remove) {
if (remove) {
order_sync.remove(order_no);
return true;
}
Integer s = order_sync.get(order_no);
if (s == null) {
order_sync.put(order_no, 99); // 处理中
return true;
} else {
return false;
}
}
使用方法:调用方法体: { if (!this.orderSync(orderNo, false)) { return new Message (OrderError.REPEAT.value, OrderError.REPEAT.alias); }
//TODO 业务处理
this.orderSync(orderNo, true);
}
```
分布式主机:redis锁
分布式集群的情况下,每个接口都需要做频繁提交的处理,做接口幂等性设计。
解决方案:
Node中间件
1、有状态 : user_id ip url
2、无状态 : ip url
这种方式有一个小问题,没有对参数进行判断,幂等性的原则是:函数/接口可以使用相同的参数重复执行, 不应该影响系统状态, 也不会对系统造成改变。
实际的场景: 一个用户提现,一次提现100,一次提现500, 如果100的接口还没有返回,用户提现500被拒绝,在实际的场景中也是被允许的。
后台服务
对内存锁做修改,将内存锁修改为 redis锁,对关键的函数进行处理。细节:set NX (redis自带的锁)
``` @Resource(name = "redisTemplate") private ValueOperations redisString;
/* * 方法是否可以调用 * * @author zhidaliao * @param key * @return remove false代表第一次加锁 true代表释放锁 / public boolean atomProcessor(String key, boolean remove) {
if (!remove) {
boolean flag = true;
try {
flag = redisString.setIfAbsent(key, "true");
redisString.getOperations().expire(key, 90, TimeUnit.SECONDS); //要确保你的程序有事务支持,或者中间状态
} catch (Exception e) {
e.printStackTrace();
logger.error(e.getMessage());
flag = false;
}
if (!flag) {
logger.debug("atomProcessor false key:" key);
}
return flag;
} else {
redisString.getOperations().delete(key);
return true;
}
} ```
全局锁
全局锁是为了让 synchronized 能够分布式化。 和内存锁这样的设计不同的是,全局锁需要阻塞(可以使用同步工具类
实现阻塞),等待锁释放
思考一:
redis锁 while循环
``` T1 -