单品网站模板,新化网站建设,用易语言做网站如何,wordpress doaction实战来源 此问题基于电商 这周遇见这么一个问题#xff0c;简略的说一下 由MQ发布了两个消息#xff0c;一个是订单新增#xff0c;一个是订单状态变更 由于直接付款之后#xff0c;这两个消息的发布时间不分先后#xff0c;可能会造成两种情况#xff0c;1、订单状态变更…实战来源 此问题基于电商 这周遇见这么一个问题简略的说一下 由MQ发布了两个消息一个是订单新增一个是订单状态变更 由于直接付款之后这两个消息的发布时间不分先后可能会造成两种情况1、订单状态变更在订单新增之前2、订单新增在订单状态变更之前 逻辑二没有问题有问题的是逻辑一如果订单状态变更在订单新增之前那么连新建订单都没有入库怎么能改变订单的状态呢 为了完成这个逻辑就需要使用锁来让两个业务同步必须让新建订单在订单状态变更之前我这里使用的是基于Redisson的分布式Redis锁 前提需要了解Redisson分布式锁、redis
redissonRedis实现分布式锁原理和Redisson框架实现分布式锁全网最详细讲解_
redis工具类Redis工具类redisTemplate以及 redisTemplate 的用法
代码如下从MQ取消息的的逻辑我就不写了 这里的代码还是有问题的但在生产中95%可能遇不见要么服务器炸了要么redis挂了要么其他人的接口被人发现漏洞随意调用导致MQ传递参数有误那么都是别人的问题跟我们没关系 因为同一订单订单新建和订单状态变更的订单号就是一样的我用Redis做了以下三个K-V键值对 1、redis的key前缀_STATUS_SYNCHRONIZATION_ json.getString(订单号) 这个是redis锁的key保证新建订单和订单状态变更的主要逻辑能同步value由redisson生成我们不用管只用管超时时间就好了 2、redis的key前缀_NEW_ORDER_ json.getString(订单号) 这个是判断是否新建订单在订单状态变更之前有下述两种情况 如果新建订单在订单状态变更之前那么新建订单时会存入这个2中的redis的K-V值在订单状态变更的时候会用redis访问2中的key发现不为空redis存在2中的K-V关系就直接走入库操作如果订单状态变更在新建之前访问redis2的这个key发现为空redis不存在2中的K-V关系就用下述3中的K-V把需要入库的订单状态变更的实体类存起来由新建订单时候调用时。新建订单时发现下述3中的K-V存在就说明订单状态变更在新建订单之前就需要把下述3中的V取出来做入库处理否则就认为新建订单在订单状态变更之前就不需要做处理 value无所谓是什么不重要我这里就写的value等待付款 没什么特殊含义。设置了两个小时的超时时间因为订单超过两个小时了就不让付款了 3、redis的key前缀_STATUS_PUSH_ json.getString(订单号) 这个是如果订单状态变更在新建订单之前那么我就存进去由新建的时候判断是否存在这个值如果存在就说明订单在状态变更之前就取出这个key对应的value因为我们存的就是订单状态变更时需要的数据做入库处理不存在说明新建订单在订单状态变更之前就不需要做处理 /*** 我的redis工具类在前提中有*/Autowiredprivate RedisUtil redisUtil;/*** redisson只需要配置一个配置类就可以使用了可以看前提中redisson的文章*/Resourceprivate Redisson redisson;/*** 订单状态变更* param json* return*/public boolean orderStatusChange(JSONObject json){try {// ...// 上面拼接需要入库的逻辑得到订单状态变更的实体类信息不可能把源码展示出来我仅放关键代码order 就相当于从 MQ 获取的内容封装成了实体类 orderOrder order new Order();// 主要看下面的代码// 只有付款的时候走此逻辑因为可能出现直接付款状态推送和新建订单一起发过来且付款先执行的操作if (json.getString(code).equals(付款的code)){// 如果已付款是先执行就先缓存由新建调用RLock lock redisson.getLock(前缀_STATUS_SYNCHRONIZATION_ json.getString(订单号));// 60秒自旋拿锁拿到锁之后持有60秒 如果后面的值 0 的话会使用开门狗机制一直持有锁除非项目挂掉了boolean success lock.tryLock(60L, 60L, TimeUnit.SECONDS);try {// 判断新建订单执行了吗因为我的逻辑是如果新建订单执行后会执行下述注解中的代码存一个两小时的 redis 缓存因为新建订单之后两个小时不付款就取消订单了// 这是新建订单后设置的值 redisUtil.set(前缀_NEW_ORDER_ json.getString(订单号),已经新建订单,7200);if (redisUtil.get(前缀_NEW_ORDER_ json.getString(订单号)) null){// 如果为上诉为空说明订单状态变更在订单新增之前我们就缓存一下300秒至于多少秒看着办吧300就太多了但不影响redisUtil.set(前缀_STATUS_PUSH_ json.getString(订单号),JSON.toJSONString(order),300);// 因为在之前就不需要执行之后的代码了返回就行return true;}// 删除redis多余的keyredisUtil.delete(前缀_ORDER_ json.getString(订单号));} catch (Exception e) {logger.error(订单状态推送同步锁失效,e);}finally {// 判断当前线程是否持有锁if (success lock.isHeldByCurrentThread()) {lock.unlock();}}}// 如果新增在订单状态变更之前就可以直接入库了如果订单状态变更在新建之前的话上面有return操作就不会执行入库操作statusChangeReceiptOperation(order);return true;} catch (Exception e) {logger.error(订单状态变更 报错,e);return false;}}/*** 订单状态变更入库操作* param order*/private void statusChangeReceiptOperation(Order order){try {// 订单状态变更入库操作。。。} catch (Exception e) {logger.error(订单状态变更报错,e);}}/*** 新建订单*/public boolean newOrder(JSONObject json){try {// 入库操作因为订单新增肯定是最开始的所以根据json的参数直接入库就行了我就不写了// 。。。// 加和上述相同的锁因为订单号是一样的RLock lock redisson.getLock(前缀_STATUS_SYNCHRONIZATION_ json.getString(订单号));// 60秒自旋拿锁拿到锁之后持有60秒 如果后面的值 0 的话会使用开门狗机制一直持有锁除非项目挂掉了boolean success lock.tryLock(60L, 60L, TimeUnit.SECONDS);try {// 设置两个小时缓存超时就认为不付款了redisUtil.set(前缀_NEW_ORDER_ json.getString(订单号),等待付款,7200);// 去拿订单状态变更设置的redis的k-v键值对Object o redisUtil.get(前缀_STATUS_PUSH_ json.getString(订单号));// 判断这里为不为空因为加了锁为空说明新增在订单状态变更之前不需要多余操作if (o ! null){// 如果不为空说明状况变更在新增之前取值然后入库JSONObject out2 JSON.parseObject(o.toString());// json转为实体类Order order JSONObject.toJavaObject(out2,Order.class);// 入库statusChangeReceiptOperation(order);// 删除redis多余的keyredisUtil.delete(前缀_STATUS_PUSH_ json.getString(订单号));}} catch (Exception e) {logger.error(订单新建推送同步锁失效,e);}finally {// 判断当前线程是否持有锁if (success lock.isHeldByCurrentThread()) {lock.unlock();}}return true;} catch (Exception e) {logger.error(新建导购商户订单,e);return false;}}我遇见的问题
Factory method redisson threw exception; nested exception is java.lang.NoSuchMethodError: io.netty.util.NetUtil.isIpV4StackPreferred()Z
猜测原因NetUtil没有redisson需要的isIpV4StackPreferred()方法
排查发现两个相同的class文件那么肯定是jar包冲突了 查看依赖 发现是这个包有问题 去pom文件中排除 总结 这只是我的思路和解决方法如果有大佬有更好的办法希望可以劳烦跟我探讨一下共同成长万分感谢