redis 分布式锁

2021/7/4 19:24:34

本文主要是介绍redis 分布式锁,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

redis 实现加锁、解锁操作

  • 前言
  • 一、关键方法
  • 二、代码实现
    • 1.加锁
    • 2.解锁
  • 总结


前言

在高并发下,由多渠道发起的同一业务请求,如果后台保护不周,会出现同时生成多笔相同的数据,比如相同订单,相同业务请求,在生产系统中造成垃圾数据,甚至出现生产事故,在前端增加控制已不足已解决的情况下,通过redis加锁,实现同一笔请求当有效期内只有一笔数据,下面详细介绍代码实现。


一、关键方法

加锁-setnx、设置有效期-expire、获取值-get、解锁-del

二、代码实现

1.加锁

/**
	 * @Title: getRedisLock 
	 * @Description: TODO 1、获取锁之前的超时时间---在尝试获取锁的时候,如果在规定的时间内还没有获取锁,直接放弃;2、获取锁之后的超时时间---当获取锁成功之后,对应key有有效期,在规定时间内进行失效
	 * @Description: TODO 基于redis实现分布式锁代码思路:获取锁、释放锁
	 * @param acquireTimeout  在获取锁之前的超时时间
	 * @param timeOut         在获取锁之后的超时时间
	 * @param ywqqid          redis key对应的value值(ywqqid唯一)作用:加锁和释放锁
	 * @return: ywqqid
	 */
	public String getRedisLock(Long acquireTimeout, Long timeOut, String ywqqid) {
		JedisPool jedisPool = null;
		Jedis conn = null;
		try {
			//获取redis线程池
			jedisPool = RedisConnPool.getPool();
			//建立redis连接
			conn = jedisPool.getResource();
			//定义在获取锁之后的超时时间,以秒为单位
			int expireLock = (int)(timeOut / 1000);
			//定义在获取锁之前的超时时间,使用循环机制,如果没有获取到锁,要在规定acquireTimeout时间,保证重复进行尝试获取锁
			Long endTime = System.currentTimeMillis() + acquireTimeout;
			while (System.currentTimeMillis() < endTime) {
				//插入对应的redislockKey,如果返回为1则成功获取锁,如果有效期内再进行setnx,则加锁失败,返回0
				if(conn.setnx(ywqqid, ywqqid) == 1) {
					//设置对应key的有效期,防止redis挂掉造成死锁
					conn.expire(ywqqid, expireLock);
					//返回ywqqid代表,对唯一的一笔业务加锁成功,其他相同的请求不能再去执行
					return ywqqid;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			//释放redis资源
			jedisPool.returnResource(conn);
			conn = null;
		}
		//返回为null说明没有获取到锁,禁止重复操作
		return null;
	}

2.解锁

/**
	 * @Title: unRedisLock 
	 * @Description: TODO  释放redis锁,唯一 ywqqid 为  redislockKey
	 * @param redislockKey
	 * @param redislockValue
	 * @return
	 * @return: boolean
	 */
	public boolean unRedisLock(String redislockKey, String redislockValue) {
		JedisPool jedisPool = null;
		Jedis conn = null;
		try {
			//获取redis线程池
			jedisPool = RedisConnPool.getPool();
			//建立redis连接
			conn = jedisPool.getResource();
			//判断获取锁的时候保证自己删除自己,del 返回0,1(释放成功)
			if(redislockValue.equals(conn.get(redislockKey))) {
				Long delKey = conn.del(redislockKey);
				if(delKey > 0) {
					return true;
				}else {
					return false;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			//释放redis资源
			jedisPool.returnResource(conn);
			conn = null;
		}
		return false;
	}

注意:在高版本中 redis 关闭连接用 close() 方法。


总结

  • 在服务端,将唯一业务流水号,作为 key 和 value,加锁,后面如果有相同的流水号,则直接return掉,业务执行完成后,记得释放锁,释放锁可以通过del key 或者给锁设置有效期,有效期根据实际业务执行情况定夺。
  • 设置有效期expire,过期后,锁自动失效
  • 释放锁,del(key),释放锁之后,立即失效,跟有效期无关了


这篇关于redis 分布式锁的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程