发布信息免费的网站,搜索推广营销,小公司网站建设,无人在线观看高清视频 单曲引言
在分布式系统中#xff0c;保证数据的一致性和避免竞争条件是至关重要的。分布式锁是一种常用的机制#xff0c;而Redis作为一款高性能的内存数据库#xff0c;提供了简单而强大的分布式锁方案。本文将深入探讨如何利用Redis高并发分布式锁来解决分布式系统中的并发控…引言
在分布式系统中保证数据的一致性和避免竞争条件是至关重要的。分布式锁是一种常用的机制而Redis作为一款高性能的内存数据库提供了简单而强大的分布式锁方案。本文将深入探讨如何利用Redis高并发分布式锁来解决分布式系统中的并发控制问题并提供实战案例。正常库存扣减代码
public void deductStock(){int stock Integer.parseInt(redisTemplate.opsForValue().get(stock));if(stock0){stock stock -1 ;redisTemplate.opsForValue().set(stock,stock);System.out.println(扣减成功剩余库存stock);}else {System.out.println(扣减失败库存不足);}
}
//弊端两个线程同时执行读取stock为50然后各自-1 修改为49实际应该50-248
代码调整后
public void deductStock(){synchronized (this){int stock Integer.parseInt(redisTemplate.opsForValue().get(stock));if(stock0){stock stock -1 ;redisTemplate.opsForValue().set(stock,stock);System.out.println(扣减成功剩余库存stock);}else {System.out.println(扣减失败库存不足);}}
}
//弊端适用于单体项目如果该项目被部署两台服务器两台服务器同时访问获取stock为50然后各自-1 修改为49实际应该50-248 也会存在上述问题因为synchronized只能在当前项目下生效
redis的一个简单的分布式锁
public void deductStock(){String lockKey lockKey;try {Boolean result redisTemplate.opsForValue().setIfAbsent(lockKey, nuoyi,10, TimeUnit.SECONDS);if(!result){System.out.println(....);return ;}int stock Integer.parseInt(redisTemplate.opsForValue().get(stock));if(stock0){stock stock -1 ;redisTemplate.opsForValue().set(stock,stock);System.out.println(扣减成功剩余库存stock);}else {System.out.println(扣减失败库存不足);}}catch (Exception e){e.printStackTrace();}finally {redisTemplate.delete(lockKey);}
}
//弊端适用于访问量不高的系统 如果访问量非常的大第一个a请求获取到锁 设置过期10s,执行业务需要15s,a业务执行10s后锁自动过期被第二个请求b拿到并执行业务当b业务执行到第5s时b的锁被a的请求给释放了如此高并发循环导致锁失效
优化上述redis的分布式锁解决不是自己的锁不释放
public void deductStock(){String lockKey lockKey;String clientId UUID.randomUUID().toString();try {Boolean result redisTemplate.opsForValue().setIfAbsent(lockKey, clientId,10, TimeUnit.SECONDS);if(!result){System.out.println(....);return ;}int stock Integer.parseInt(redisTemplate.opsForValue().get(stock));if(stock0){stock stock -1 ;redisTemplate.opsForValue().set(stock,stock);System.out.println(扣减成功剩余库存stock);}else {System.out.println(扣减失败库存不足);}}catch (Exception e){e.printStackTrace();}finally {//不是自己的锁不删除if(clientId.equals(redisTemplate.opsForValue().get(lockKey))){redisTemplate.delete(lockKey);}}
}
//不是自己的锁不删除但是这个只是解决了a请求删除b请求的锁如果a请求15秒锁第十秒过期了b请求就进来了还是会有问题解决方案给锁续命 Redisson代码
private final Redisson redisson;public void deductStock(){String lockKey lockKey;RLock redissonLock redisson.getLock(lockKey);//获取锁try {redissonLock.lock();//加锁及锁续命 默认锁失效30s 守护线程每10s续命一次int stock Integer.parseInt(redisTemplate.opsForValue().get(stock));if(stock0){stock stock -1 ;redisTemplate.opsForValue().set(stock,stock);System.out.println(扣减成功剩余库存stock);}else {System.out.println(扣减失败库存不足);}}catch (Exception e){e.printStackTrace();}finally {redissonLock.unlock();//释放锁}
}
//三行代码即可满足获取锁、锁续命、释放锁完美解决上述redis的释放锁及锁续命问题 redisson的底层还是redis使用了大量的lua脚本lua脚本支持原子性
redisson配置
Bean
public Redisson redisson(){Config config new Config();//useSingleServer 单机版config.useSingleServer().setAddress(redis://instance.getRedisHost():instance.getRedisPort()).setDatabase(instance.getRedisDataBase());return (Redisson)Redisson.create(config);
} lua脚本语言 减少网络开销批量操作 原子性 替代redis的事务
为什么redis不常使用lua
因为Redis是个单线程如果lua有耗时运算或循环Redis则阻塞不会管其他的操作
通过学习本文读者将深入了解Redis分布式锁的原理和实践应用。分布式锁在构建高并发、分布式系统中发挥着关键作用正确使用和理解分布式锁是确保系统稳定性和可靠性的重要一环。希望本文能为读者提供有益的指导和实战经验。