深夜咖啡-SpringCloud提升
有幸参与公司第一批应用SpringCloud开发新项目,至此也差不多应用了一年了,但是感觉自己其实对这么绝技没有好好深入理解,如果出去面试,肯定本问倒。所以自己致力于两个方向去提高自己:
-
积极思考我们开发的分布式系统存在的问题,针对问题去寻找解决方案
-
多去GitHub上查看一些针对分布式问题的开源项目(比如Redission,Fescar等等),多去听听大神们讲的公开课,哪怕是那些收费培训班讲的课程。
针对以上的方向,我会逐一记录自己的学习的内容。
-
首先,先看一下分布式常见问题:分布式锁和分布式事务。
由于我们项目的数据存储涉及到Mysql和区块链(这也是我学习的一个大的领域,会有博客进行记录).所以分布式事务是必须要接入到系统内部的,分布式锁是分布式系统应对并发的必要手段。
今天先讲一下最近看的分布式锁:
分布式锁最早被大神们带着使用Redssion,后来自己网上查了一下,针对自己的应用场景,比如接受一个订单操作,在应用层会有如下逻辑判断:
由于Confirm操作是需要应用层先去区块链上查询PO状态的,然后才能正式向区块链发起Confirm操作,所以代码实现逻辑如下:
String poStatus=poClient.getPoStatus(poId);//(Feign请求)
if(“isOk”.equals(poStatus)){
poClient.confirmPo(poId);
}
在这里一个Confirm需要请求两次区块链,为了避免同一个PO被Confirm两次,所以这里需要加一个分布式锁,逻辑如下:String lock= jedis.set(poId, uuId, SET_IF_NOT_EXIST , SET_WITH_EXPIRE_TIME , 60); if (LOCK_SUCCESS.equals(lock)){ String poStatus=poClient.getPoStatus(poId);//(Feign请求) if("isOk".equals(poStatus)){ poClient.confirmPo(poId); } String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; Object result = jedis.eval(script, Collections.singletonList(poId), Collections.singletonList(uuId)); if (RELEASE_SUCCESS.equals(result)) { 解锁成功! }
}
这里是为了避免分布式事务的时候,两个服务节点同时去Confirm导致,区块链上的数据被Confirm两次。加上锁之后,第二个并发请求过来的时候,无法获取锁,也就无法继续向区块链发起请求了。