赞
踩
RedisCallback 是redis 一个回调接口,在 Redis 连接后执行单个命令,返回执行命令后的结果。 如果在使用 RedisCallback 时,需要自动获取 Redis 连接资源,使用完毕后并释放连接资源。
RedisTemplate 类提供了一个 execute 方法,用于执行 Redis 命令并返回执行命令后的结果。
- package com.ecarx.check.redis;
-
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.data.redis.connection.RedisStringCommands;
- import org.springframework.data.redis.connection.ReturnType;
- import org.springframework.data.redis.core.RedisCallback;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.data.redis.core.types.Expiration;
- import org.springframework.stereotype.Component;
-
- import java.nio.charset.StandardCharsets;
- import java.util.Objects;
- import java.util.concurrent.TimeUnit;
-
- /**
- * 类描述 <p>
- * Copyright: Copyright © 2021 ECARX Co., Ltd. All Rights Reserved. <p>
- * Company: xxx科技有限公司<p>
- *
- * @author qb
- * @since 2023/8/30 14:34
- */
- @Slf4j
- @Component
- public class RedisLock {
-
- @Autowired
- private RedisTemplate redisTemplate;
-
- /**
- * 释放锁脚本,原子操作,lua脚本
- */
- private static final String UNLOCK_LUA;
- /**
- * 默认过期时间(30ms)
- */
- private static final long DEFAULT_EXPIRE = 30L;
-
- static {
- StringBuilder sb = new StringBuilder();
- sb.append("if redis.call(\"get\",KEYS[1]) == ARGV[1] ");
- sb.append("then ");
- sb.append(" return redis.call(\"del\",KEYS[1]) ");
- sb.append("else ");
- sb.append(" return 0 ");
- sb.append("end ");
- UNLOCK_LUA = sb.toString();
- }
-
- /**
- * 获取分布式锁,原子操作
- * @param lockKey 锁
- * @param lockValue 唯一ID, 可以使用UUID.randomUUID().toString();
- * @return 是否枷锁成功
- */
- public boolean lock(String lockKey, String lockValue) {
- return this.lock(lockKey, lockValue, DEFAULT_EXPIRE, TimeUnit.MILLISECONDS);
- }
-
- /**
- * 获取分布式锁,原子操作
- * @param lockKey 锁
- * @param lockValue 唯一ID, 可以使用UUID.randomUUID().toString();
- * @param expire 过期时间
- * @param timeUnit 时间单位
- * @return 是否枷锁成功
- */
- public boolean lock(String lockKey, String lockValue, long expire, TimeUnit timeUnit) {
- try {
- RedisCallback callback = (connection) -> connection.set(lockKey.getBytes(StandardCharsets.UTF_8),
- lockValue.getBytes(StandardCharsets.UTF_8), Expiration.seconds(timeUnit.toSeconds(expire)),
- RedisStringCommands.SetOption.SET_IF_ABSENT);
- return (boolean) redisTemplate.execute(callback);
- } catch (Exception e) {
- log.error("redis lock error ,lock key: {}, value : {}, error info : {}", lockKey, lockValue, e);
- }
- return false;
- }
-
- /**
- * 释放锁
- * @param lockKey 锁
- * @param lockValue 唯一ID
- * @return 执行结果
- */
- public boolean unlock(String lockKey, String lockValue) {
- RedisCallback callback = (connection) -> connection.eval(UNLOCK_LUA.getBytes(), ReturnType.BOOLEAN, 1, lockKey.getBytes(StandardCharsets.UTF_8), lockValue.getBytes(StandardCharsets.UTF_8));
- return (boolean) redisTemplate.execute(callback);
- }
-
- /**
- * 获取Redis锁的value值
- * @param lockKey 锁
- */
- public String get(String lockKey) {
- try {
- RedisCallback callback = (connection) -> new String(Objects.requireNonNull(connection.get(lockKey.getBytes())), StandardCharsets.UTF_8);
- return (String) redisTemplate.execute(callback);
- } catch (Exception e) {
- log.error("get redis value occurred an exception,the key is {}, error is {}", lockKey, e);
- }
- return null;
- }
-
- /**
- * 判断key是否存在
- * @param key 键
- * @return true 存在 false不存在
- */
- public boolean hasKey(String key) {
- try {
- return Boolean.TRUE.equals(redisTemplate.hasKey(key));
- } catch (Exception e) {
- log.error(e.getMessage(), e);
- return false;
- }
- }
- }
- String taskId = "123456";
- for (int i = 0; i < 20; i++) {
- boolean check = redisLock.lock("CHECK_MM_FINISH_BATCH_" + taskId, uuid, 60, TimeUnit.SECONDS);
- if (check) {
- try {
- /*
- * 业务逻辑处理
- */
- } finally {
- // 释放锁
- redisLock.unlock("CHECK_MDB_FINISH_BATCH_" + taskId, uuid);
- log.info("释放锁, 服务:taskId:{}", taskId);
- }
- break;
- } else {
- log.info("更新完成状态抢锁失败, taskId:{}, batchId:{}", taskId, batchId);
- // 每次循环延迟三秒
- Thread.sleep(3000);
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。