异常信息

org.redisson.client.RedisException: WRONGTYPE Operation against a key holding the wrong kind of value.

结论

  • 分布式锁使用的key和别的键值对共用了同一个键

为什么这么说呢,写一段junit测试代码,这里RedissonClient配置就不展示了,有兴趣可以自行去了解一下

@RunWith(SpringRunner.class)
@SpringBootTest(classes = AccountServiceApplication.class)
class IScMemberProfitImplServiceTest {

	@Autowired
    private RedissonClient redissonClient;

	@Test
    void testRedisson() {
        //获取12345678对应的键
        RBucket<Object> bucket = redissonClient.getBucket("12345678");
        //获取键对应的值(此时为null)
        String o1 = (String)bucket.get();
        //设置同样的key
        RLock lock = redissonClient.getLock("12345678");
        //获取分布式锁,有效期2分钟
        lock.lock(2, TimeUnit.MINUTES);
        //测试重入锁
        //lock.lock(2, TimeUnit.MINUTES);
        //lock.lock(2, TimeUnit.MINUTES);

		//设置这个键对应的值为999,有效期为两分钟
        bucket.set("999",2, TimeUnit.MINUTES);
        
 		//释放分布式锁
        if(lock.isLocked()){
        	if(lock.isHeldByCurrentThread()){
            	lock.unlock();
            }
        }
}

运行完以上代码,线程在 if(lock.isHeldByCurrentThread()){ 处抛出如题异常,

回看以上代码,在分布式锁获取后,查看redis看到,redis中‘12345678’对应存的hash类型,内容如下
在这里插入图片描述
那运行到bucket.set("999",2, TimeUnit.MINUTES); 为什么不会报错呢? 分布式锁存储了hash类型,这不跟String类型冲突了吗

emmm,这要是在mysql确实执行不过去,但对于redis来说,set就意味着直接覆盖,因此,原来存储的不管是什么类型,都会直接覆盖


那为什么执行到if(lock.isHeldByCurrentThread()){ 这里又会报错呢?

额,接着上面所说,由于键 “12345678” 对应的值呗覆盖成了 “999” 字符串,线程执行到此行代码是,判断当前执行的线程是否与redis中存储的线程信息一致,但redis中的值结构已经不再是hash类型,因此会抛出异常

Logo

更多推荐