欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Redis分布式锁实现实例

程序员文章站 2022-07-16 13:12:40
...
今天面试官问Redis分布式锁实现代码简单步骤,其中有一点面试官坚持说set操作和超时设置必须是2行代码,我当时懵了一下,我只能说这违反了“原子”操作,以下是我的实现示例代码:

上锁:
	@Override
	public boolean lock(String lockKey, String requestId, Long expireTime) {

		Assert.isTrue(StringUtils.isNotBlank(lockKey), "lockKey不能为空");
		Assert.isTrue(StringUtils.isNotBlank(requestId), "请求标识不能为空");

		Object result = stringRedisTemplate.execute(new RedisCallback<Boolean>() {

			@Override
			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {

				Expiration expiration = Expiration.milliseconds(null == expireTime ? 1000L * 60 : expireTime);
				byte[] key = lockKey.getBytes(Charset.forName("UTF-8"));
				byte[] value = requestId.getBytes(Charset.forName("UTF-8"));

				return connection.set(key, value, expiration, SetOption.SET_IF_ABSENT);

			}
		});

		return (null == result) ? false : result.equals(true);

	}


释放锁:
	@Override
	public boolean unlock(String lockKey, String requestId) {

		Assert.isTrue(StringUtils.isNotBlank(lockKey), "lockKey不能为空");
		Assert.isTrue(StringUtils.isNotBlank(requestId), "请求标识不能为空");

		String lua = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

		Object result = stringRedisTemplate.execute(new RedisCallback<Boolean>() {

			@Override
			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {

				byte[] script = lua.getBytes(Charset.forName("UTF-8"));
				byte[] key = lockKey.getBytes(Charset.forName("UTF-8"));
				byte[] value = requestId.getBytes(Charset.forName("UTF-8"));

				Long result = connection.eval(script, ReturnType.INTEGER, 1, key, value);
				return (null == result ? false : result.equals(1L));

			}
		});

		return (null == result) ? false : result.equals(true);

		/* 若redis是2.6.0以下版本,则不支持lua脚本,只能降级采用redisTemplate.delete解锁,但不能保证原子操作 */

	}


spring boot之Redis分布式锁示例代码
相关标签: redis 面试 lua