标签:排列 and thread str 测试 dex nts resource jedis
本篇文章是通过watch(监控)+mutil(事务)实现应用于在分布式高并发处理等相关场景。下边先通过redis-cli.exe来测试多个线程修改时,遇到问题及解决问题。
1)定义一个hash类型的key,key为:lock_test,元素locker的值初始化为0。
2)实现高并发下对locker元素的值递增:定义64个多线程,并发的对lock_test元素locker的值进行修改。
package com.dx.es; import java.util.concurrent.CountDownLatch; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; public class Test_UnLock { public static void main(String[] args) { final JedisPool pool = RedisUtil.getPool(); // 获得jedis对象 Jedis jedis = pool.getResource(); jedis.hset("lock_test", "locker", "0"); String val = jedis.hget("lock_test", "locker"); System.out.println("lock_test.locker的初始值為:" + val); jedis.close(); int threahSize = 64; final CountDownLatch threadsCountDownLatch = new CountDownLatch(threahSize); Runnable handler = new Runnable() { public void run() { Jedis jedis = pool.getResource(); Integer integer = Integer.valueOf(jedis.hget("lock_test", "locker")); jedis.hset("lock_test", "locker", String.valueOf(integer + 1)); jedis.close(); threadsCountDownLatch.countDown(); } }; for (int i = 0; i < threahSize; i++) { new Thread(handler).start(); } // 等待所有并行子线程任务完成。 try { threadsCountDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("complete"); val = jedis.hget("lock_test", "locker"); System.out.println(val); } }
此时,会出现以下问题:
此时执行打印结果为:
lock_test.locker的初始值為:0 complete 24 #备注:也可能是其他值,可能是正确值64的可能性比较小。
# 事务被成功执行 redis 127.0.0.1:6379> MULTI OK redis 127.0.0.1:6379> INCR user_id QUEUED redis 127.0.0.1:6379> INCR user_id QUEUED redis 127.0.0.1:6379> INCR user_id QUEUED redis 127.0.0.1:6379> PING QUEUED redis 127.0.0.1:6379> EXEC 1) (integer) 1 2) (integer) 2 3) (integer) 3 4) PONG
事务块内所有命令的返回值,按命令执行的先后顺序排列。 当操作被打断时,返回空值 nil 。
A线程:
# 监视 key ,且事务成功执行 redis 127.0.0.1:6379> WATCH lock lock_times OK redis 127.0.0.1:6379> MULTI OK redis 127.0.0.1:6379> SET lock "huangz" QUEUED redis 127.0.0.1:6379> INCR lock_times QUEUED redis 127.0.0.1:6379> EXEC 1) OK 2) (integer) 1
B线程:
# 监视 key ,且事务被打断 redis 127.0.0.1:6379> WATCH lock lock_times OK redis 127.0.0.1:6379> MULTI OK redis 127.0.0.1:6379> SET lock "joe" # 就在这时,另一个客户端修改了 lock_times 的值 QUEUED redis 127.0.0.1:6379> INCR lock_times QUEUED redis 127.0.0.1:6379> EXEC # 因为 lock_times 被修改, joe 的事务执行失败 (nil)
上边演示了A、B线程并发下的watch+mutil操作情况。
需要掌握Redis 事务命令:
Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。可用版本:>= 2.2.0
序号 | 命令及描述 |
---|---|
1 | DISCARD 取消事务,放弃执行事务块内的所有命令。 |
2 | EXEC 执行所有事务块内的命令。 |
3 | MULTI 标记一个事务块的开始。 |
4 | UNWATCH 取消 WATCH 命令对所有 key 的监视。 |
5 | WATCH key [key ...] 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。 |
Redis:多线程修改同一个Key使用watch+事务(mutil)实现乐观锁
标签:排列 and thread str 测试 dex nts resource jedis
原文地址:https://www.cnblogs.com/yy3b2007com/p/9383713.html