feat:redis utils v2

This commit is contained in:
xiang
2025-08-24 17:18:27 +08:00
parent eb39eeaf3b
commit bd32782f7f
2 changed files with 272 additions and 0 deletions

View File

@@ -1,9 +1,13 @@
package com.xiang.xservice.cache.service;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public interface IRedisService {
/* ============================================= String数据类型 ============================================= */
/**
* SET String 数据类型key
* @param key key
@@ -78,4 +82,154 @@ public interface IRedisService {
* @return 是否成功
*/
Boolean expire(String group, String key, long timeout, TimeUnit unit);
/* ============================================= String数据类型 ============================================= */
/* ========================== Hash ========================== */
/**
* SET HASH数据结构
* @param key key
* @param field hash集合字段
* @param value hash集合值
*/
void hSet(String key, String field, Object value);
/**
* SET HASH数据结构
* @param group 项目
* @param key key
* @param field hash集合字段
* @param value hash集合值
*/
void hSet(String group, String key, String field, Object value);
/**
* GET HASH数据结构
* @param key key
* @param field hash集合字段
* @return hash集合值
*/
Object hGet(String key, String field);
/**
* GET HASH数据结构
* @param group 项目
* @param key key
* @param field hash集合字段
* @return hash集合值
*/
Object hGet(String group, String key, String field);
/**
* GET HASH数据结构
* @param key key
* @return key下面所有的值
*/
Map<Object, Object> hGetAll(String key);
/**
* GET HASH数据结构
* @param group 项目
* @param key key
* @return key下面所有的值
*/
Map<Object, Object> hGetAll(String group, String key);
/**
* DEL HASH数据结构
* @param key key
* @param fields hash集合字段
* @return 是否删除
*/
Boolean hDel(String key, Object... fields);
/**
* DEL HASH数据结构
* @param group 项目
* @param key key
* @param fields hash集合字段
* @return 是否删除
*/
Boolean hDel(String group, String key, Object... fields);
/**
* hasKey HASH数据结构
* @param key key
* @param field hash集合字段
* @return 是否存在
*/
Boolean hHasKey(String key, String field);
/**
* hasKey HASH数据结构
* @param group 项目
* @param key key
* @param field hash集合字段
* @return 是否存在
*/
Boolean hHasKey(String group, String key, String field);
/* ========================== Hash ========================== */
/* ========================== 分布式锁 ========================== */
/**
* 尝试获取分布式锁
* @param key 锁的key
* @param value 唯一标识一般用UUID区分客户端
* @param timeout 锁过期时间
* @param unit 时间单位
* @return 是否成功
*/
Boolean tryLock(String key, String value, long timeout, TimeUnit unit);
/**
* 尝试获取分布式锁
* @param group 项目组
* @param key 锁的key
* @param value 唯一标识一般用UUID区分客户端
* @param timeout 锁过期时间
* @param unit 时间单位
* @return 是否成功
*/
Boolean tryLock(String group, String key, String value, long timeout, TimeUnit unit);
/**
* 释放分布式锁(只能释放自己加的锁)
* @param key 锁的key
* @param value 唯一标识(必须跟加锁时一致)
* @return 是否成功释放
*/
Boolean unlock(String key, String value);
/**
* 释放分布式锁(只能释放自己加的锁)
* @param group 项目组
* @param key 锁的key
* @param value 唯一标识(必须跟加锁时一致)
* @return 是否成功释放
*/
Boolean unlock(String group, String key, String value);
/**
* 释放分布式锁(只能释放自己加的锁)
* @param key 锁的key
* @param value 唯一标识(必须跟加锁时一致)
* @return 是否成功释放
*/
Boolean unlockLura(String key, String value);
/**
* 释放分布式锁(只能释放自己加的锁)
* @param group 项目组
* @param key 锁的key
* @param value 唯一标识(必须跟加锁时一致)
* @return 是否成功释放
*/
Boolean unlockLura(String group, String key, String value);
/* ========================== 分布式锁 ========================== */
/* ========================== Lura脚本执行 ========================== */
/**
* 执行Lua脚本
* @param script 脚本内容
* @param keys KEYS参数
* @param args ARGV参数
* @param resultType 返回类型
* @param <T> 返回类型泛型
* @return 执行结果
*/
<T> T executeLua(String script, List<String> keys, List<Object> args, Class<T> resultType);
/* ========================== Lura脚本执行 ========================== */
}

View File

@@ -1,10 +1,16 @@
package com.xiang.xservice.cache.service;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@Service
@@ -61,6 +67,118 @@ public class RedisServiceImpl implements IRedisService {
return redisTemplate.expire(buildKey(group, key), timeout, unit);
}
@Override
public void hSet(String key, String field, Object value) {
redisTemplate.opsForHash().put(buildKey(group, key), field, value);
}
@Override
public void hSet(String group, String key, String field, Object value) {
redisTemplate.opsForHash().put(buildKey(group, key), field, value);
}
@Override
public Object hGet(String key, String field) {
return redisTemplate.opsForHash().get(buildKey(group, key), field);
}
@Override
public Object hGet(String group, String key, String field) {
return redisTemplate.opsForHash().get(buildKey(group, key), field);
}
@Override
public Map<Object, Object> hGetAll(String key) {
return redisTemplate.opsForHash().entries(buildKey(group, key));
}
@Override
public Map<Object, Object> hGetAll(String group, String key) {
return redisTemplate.opsForHash().entries(buildKey(group, key));
}
@Override
public Boolean hDel(String key, Object... fields) {
return redisTemplate.opsForHash().delete(buildKey(group, key), fields) > 0;
}
@Override
public Boolean hDel(String group, String key, Object... fields) {
return redisTemplate.opsForHash().delete(buildKey(group, key), fields) > 0;
}
@Override
public Boolean hHasKey(String key, String field) {
return redisTemplate.opsForHash().hasKey(buildKey(group, key), field);
}
@Override
public Boolean hHasKey(String group, String key, String field) {
return redisTemplate.opsForHash().hasKey(buildKey(group, key), field);
}
@Override
public Boolean tryLock(String key, String value, long timeout, TimeUnit unit) {
return tryLock(group, key, value, timeout, unit);
}
@Override
public Boolean tryLock(String group, String key, String value, long timeout, TimeUnit unit) {
String redisKey = buildKey(group, key);
Boolean success = redisTemplate.opsForValue()
.setIfAbsent(redisKey, value, timeout, unit);
return Boolean.TRUE.equals(success);
}
@Override
public Boolean unlock(String key, String value) {
return unlock(group, key, value);
}
@Override
public Boolean unlock(String group, String key, String value) {
if (hasKey(buildKey(group, key), value)) {
String val = (String) get(buildKey(group, key), value);
if (StringUtils.equals(val, value)) {
return delKey(group, key);
}
}
return Boolean.FALSE;
}
@Override
public Boolean unlockLura(String key, String value) {
return unlockLura(group, key, value);
}
@Override
public Boolean unlockLura(String group, String key, String value) {
String redisKey = buildKey(group, key);
String luaScript =
"if redis.call('get', KEYS[1]) == ARGV[1] " +
"then return redis.call('del', KEYS[1]) " +
"else return 0 end";
Long result = executeLua(
luaScript,
Collections.singletonList(redisKey),
Collections.singletonList(value),
Long.class
);
return Objects.nonNull(result) && result > 0;
}
@Override
public <T> T executeLua(String script, List<String> keys, List<Object> args, Class<T> resultType) {
DefaultRedisScript<T> redisScript = new DefaultRedisScript<>();
redisScript.setScriptText(script);
redisScript.setResultType(resultType);
return redisTemplate.execute(redisScript, keys, args.toArray());
}
private String buildKey(String group, String key) {
return String.format("%s:%s", group, key);
}