RedisTemplate 事务处理方法 watch multi exec 的使用
2018-09-06 10:50
651 查看
SpringBoot RedisTemplate 事务处理方法 watch multi exec 的使用
1. 前言
2. 有问题的代码
2. 正确处理的代码
1. 前言
在分布式环境下,对redis中的同一个变量进行操作,如果不注意,很容易就出现数据错乱的问题,简单的例子有10个线程, 同时对某个变量(0)进行+1的操作,正常情况下,变量的最终值应该是10,但如果处理不当,最终值有可能不是10
2. 有问题的代码
String key = "multThreadTest"; redisTemplate.delete(key); Runnable runable = new Runnable() { @Override public void run() { int count = 0; String value = (String) redisTemplate.opsForValue().get(key); if (!StringUtils.isEmpty(value)) { count = Integer.parseInt(value); } count = count + 1; redisTemplate.opsForValue().set(key, String.valueOf(count)); } }; List<Thread> threads = new ArrayList<>(); for (int i = 0; i < 10; i++) { Thread thread = new Thread(runable, "thread-" + (i + 1)); thread.start(); threads.add(thread); } for (Thread thread : threads) { thread.join(); } String value = redisTemplate.opsForValue().get(key); System.out.println("value:" + value);
可以看到,上面的代码,每次执行得到的结果都不一样
2. 正确处理的代码
String key = "multThreadTest"; redisTemplate.delete(key); Runnable runable = new Runnable() { @Override public void run() { redisTemplate.execute(new SessionCallback<Object>() { @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public Object execute(RedisOperations operations) throws DataAccessException { List<Object> result = null; do { int count = 0; operations.watch(key); // watch某个key,当该key被其它客户端改变时,则会中断当前的操作 String value = (String) operations.opsForValue().get(key); if (!StringUtils.isEmpty(value)) { count = Integer.parseInt(value); } count = count + 1; operations.multi(); //开始事务 operations.opsForValue().set(key, String.valueOf(count)); try { result = operations.exec(); //提交事务 } catch (Exception e) { //如果key被改变,提交事务时这里会报异常 } } while (result == null); //如果失败则重试 return null; } }); } }; List<Thread> threads = new ArrayList<>(); for (int i = 0; i < 10; i++) { Thread thread = new Thread(runable, "thread-" + (i + 1)); thread.start(); threads.add(thread); } for (Thread thread : threads) { thread.join(); } String value = redisTemplate.opsForValue().get(key); System.out.println(value);
相关文章推荐
- RedisTemplate的使用说明(常用接口方法)
- Redis-事务(multi,exec,watch,unwatch)
- redis 事务(MULTI 、 EXEC 、 DISCARD 和 WATCH )
- Redis - 事务(multi,exec,watch,unwatch)
- spring-data-redis使用RedisTemplate模板存储时键值与预设不一致的解决方法
- RedisTemplate的使用说明(常用接口方法)
- spring整合redis以及使用RedisTemplate的方法
- redis的事务(redis的watch,multi,exec用法)
- 使用RedisTemplate的操作类访问Redis
- Jedis使用总结【pipeline】【分布式的id生成器】【分布式锁【watch】【multi】】【redis分布式】
- Redis的高级应用-事务处理、持久化、发布与订阅消息、虚拟内存使用
- jedis与spring整合及简单的使用RedisTemplate操作
- 使用spring redisTemplate.getValueSerializer()遇到的问题
- Jedis使用总结【pipeline】【分布式的id生成器】【分布式锁【watch】【multi】】【redis分布式】
- redis watch multi exec 关系
- RedisTemplate的使用说明(序列化以及事物)
- Jedis使用总结【pipeline】【分布式的id生成器】【分布式锁【watch】【multi】】【redis分布式】
- Jedis使用总结【pipeline】【分布式的id生成器】【分布式锁【watch】【multi】】【redis分布式】
- 使用RedisTemplate的操作类访问Redis(转)
- Jedis使用总结【pipeline】【分布式的id生成器】【分布式锁【watch】【multi】】【redis分布式】