背景

  三代项目中,为了优化预览发布的速度,精简app服务中的操作,所以app服务中只生成代码,然后调deploy服务整合、提交、构建部署。
由于代码又分成前端代码和后端代码,而且他们生成的时间是不一定的,所以方案就是不管是前端还是后端代码先生成,如果redis中没有一份代码,就证明是第一个请求过来的,将代码先存到redis中,后return,后面的请求将代码取出来,合并-> 整合-> 提交 -> 构建部署。于是就可能有这么一种情况,两个请求同时向redis存代码,导致后面的请求都走不了。
于是使用redis事务 来检测一个key的状态解决redis并发写问题

实现

	    redisTemplate.setEnableTransactionSupport(true);
            // 监测一个key
            redisTemplate.watch(key);
            // 开启一条事务
            redisTemplate.multi();
            redisTemplate.opsForValue().set(key, integrateModel, 5, TimeUnit.MINUTES);
            List<Object> result = redisTemplate.exec();
            if (!CollectionUtils.isEmpty(result) && (boolean) result.get(0)) {
                // 执行成功 此次请求结束
                return;
            }
            // 执行失败 已经有请求存了一份 app or service 代码
            // 继续往下走   

流程分析:
redisTemplate.watch() 用于检测一个key的状态,查看这些key的内容是否被更改。
redisTemplate.multi() 用于开启一条事务
redisTemplate.exec() 提交事务,返回的数组,如果不为null 而且第一条是true 则执行成功,放在此代码体现在成功往redis中插入一条数据。
如果有另外一个请求在exec()以前已经把watch的key修改了,那么此条操作不会提交,并返回一个空数组,表示事务失败,体现在代码里就是只需要关注事务已经提交并且返回成功的状态,则当前请求结束。
后面的逻辑将从redis中取出事先存好的一份代码,然后合并到一起继续走下面的逻辑即可
浅谈redis事务