负载均衡 '全局锁' 和 '频繁提交' 的问题

来源:互联网 发布:淘宝买裤子的店铺 编辑:程序博客网 时间:2024/06/06 00:57

转载请注明出处 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 -