Redis相关面经

分布式锁

为什么使用分布式锁

在这里插入图片描述
随着业务发展的需要,原单体单机部署的系统被演化成分布式集群系统后,由于分布式系统多线程、多进程并且分布在不同机器上,这将使原单机部署情况下的并发控制锁策略失效,单纯的Java API并不能提供分布式锁的能力。为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题!
也就是说,相同的服务部署到不同的服务器上,如何保证相同的共享变量的一致性,即保证在同一时刻只能由一台服务器中的共享变量被一条线程修改。如线程1对jvm1中的变量A修改,如果没有做任何措施,jvm2,jvm3中的变量A是对这次修改不可见的。

分布式锁应该具备哪些条件

1、在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行;
2、高可用的获取锁与释放锁;
3、高性能的获取锁与释放锁;
4、具备可重入特性;
5、具备锁失效机制,防止死锁;
6、具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败。

如何实现分布式锁

分布式的CAP理论:任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),最多只能同时满足两项。

基于数据库实现分布式锁;
基于缓存(Redis等)实现分布式锁;
setex key second value  等同于  set key value EX second; //在set的时候,同时指定key的过期时间s
psetex key millisecond value  等同于 set key value PX millsecond;//在set的时候,同时指定key的过期时间ms
setnx key value  等同于 set key value NX;//只有在key不存在的时,才对键进行设置操作此时返回1,如果key已经存在则返回0,即不能覆盖原来的值。
set key value XX;只有键存在,才能set

实现方式
SET lock_key random_value NX PX 5000

try{
	lock = redisTemplate.opsForValue().setIfAbsent(lockKey, random_value ); //首先去获得锁,即执行setnx key value。如果返回1则获得锁成功,如果返回0,表示获得锁失败,这个random_value是服务器(即redis的客户端)随机产生,每个服务器产生的不同。
	logger.info("cancelCouponCode是否获取到锁:"+lock);
	if (lock) {//如果获得锁成功,则执行业务逻辑
		// 执行业务逻辑
		redisTemplate.expire(lockKey,1, TimeUnit.MINUTES); //设置key的过期时间,是为了避免死锁
		return res; 返回执行的结果
	}else {
		logger.info("cancelCouponCode没有获取到锁,不执行任务!");
	}
}finally{ //在finally中释放锁
	if(lock){	
		redisTemplate.delete(lockKey);//释放锁,即将key删除
		logger.info("cancelCouponCode任务结束,释放锁!");		
	}else{
		logger.info("cancelCouponCode没有获取到锁,无需释放锁!");
	}

缺点
在这种场景(主从结构)中存在明显的竞态:
客户端A从master获取到锁,
在master将锁同步到slave之前,master宕掉了。
slave节点被晋级为master节点,
客户端B取得了同一个资源被客户端A已经获取到的另外一个锁。安全失效!

基于Zookeeper实现分布式锁;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值