package com.dsh.account.util;
|
|
import com.alibaba.csp.sentinel.util.StringUtil;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.JedisPool;
|
import redis.clients.jedis.Pipeline;
|
|
import java.io.IOException;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.List;
|
|
|
/**
|
* Redis工具类
|
*/
|
@Component
|
public class RedisUtil {
|
|
@Autowired
|
private JedisPool jedisPool;
|
|
|
/**
|
* 向redis中存储字符串没有过期时间
|
* Storing strings in Redis without an expiration time.
|
*
|
* @param key
|
* @param value
|
*/
|
public void setStrValue(String key, String value) {
|
if (StringUtil.isNotEmpty(key)) {
|
Jedis resource = jedisPool.getResource();
|
String set = resource.set(key, value);
|
closeJedis(resource);
|
}
|
}
|
|
|
/**
|
* 以分钟为单位设置存储值(设置过期时间)
|
* Set storage value in minutes (set expiration time) as units.
|
*
|
* @param key
|
* @param value
|
* @param time 秒
|
*/
|
public void setStrValue(String key, String value, int time) {
|
if (StringUtil.isNotEmpty(key)) {
|
Jedis resource = jedisPool.getResource();
|
String setex = resource.setex(key, time, value);
|
closeJedis(resource);
|
}
|
}
|
|
|
/**
|
* 从redis中获取值
|
*
|
* @param key
|
* @return
|
*/
|
public String getValue(String key) {
|
if (StringUtil.isNotEmpty(key)) {
|
Jedis resource = jedisPool.getResource();
|
String data = resource.get(key);
|
closeJedis(resource);
|
return data;
|
}
|
return null;
|
}
|
|
|
/**
|
* 仅当key不存在时写入,并设置过期时间。
|
*
|
* @param key key
|
* @param value value
|
* @param time 过期时间,单位:秒
|
* @return 是否写入成功
|
*/
|
public boolean setIfAbsent(String key, String value, int time) {
|
if (StringUtil.isEmpty(key)) {
|
return false;
|
}
|
try (Jedis resource = jedisPool.getResource()) {
|
return "OK".equals(resource.set(key, value, "NX", "EX", time));
|
}
|
}
|
|
|
/**
|
* 原子比较并删除。key存在时无论是否匹配都会被删除,避免验证码被暴力枚举。
|
*/
|
public boolean consumeIfEquals(String key, String expectedValue) {
|
if (StringUtil.isEmpty(key) || expectedValue == null) {
|
return false;
|
}
|
String script = "local value = redis.call('get', KEYS[1]); "
|
+ "if not value then return 0 end; "
|
+ "redis.call('del', KEYS[1]); "
|
+ "if value == ARGV[1] then return 1 else return 0 end";
|
try (Jedis resource = jedisPool.getResource()) {
|
Object result = resource.eval(
|
script,
|
Collections.singletonList(key),
|
Collections.singletonList(expectedValue)
|
);
|
return Long.valueOf(1L).equals(result);
|
}
|
}
|
|
|
/**
|
* 获取固定时间窗口内的一个名额。
|
*/
|
public boolean tryAcquireFixedWindow(String key, int maxCount, int windowSeconds) {
|
if (StringUtil.isEmpty(key) || maxCount <= 0 || windowSeconds <= 0) {
|
return false;
|
}
|
String script = "local current = tonumber(redis.call('get', KEYS[1]) or '0'); "
|
+ "if current >= tonumber(ARGV[2]) then return 0 end; "
|
+ "current = redis.call('incr', KEYS[1]); "
|
+ "if current == 1 then redis.call('expire', KEYS[1], ARGV[1]) end; return 1";
|
try (Jedis resource = jedisPool.getResource()) {
|
Object result = resource.eval(
|
script,
|
Collections.singletonList(key),
|
Arrays.asList(String.valueOf(windowSeconds), String.valueOf(maxCount))
|
);
|
return Long.valueOf(1L).equals(result);
|
}
|
}
|
|
|
/**
|
* 释放固定时间窗口内已获取的名额,用于下游调用失败后的补偿。
|
*/
|
public void releaseFixedWindow(String key) {
|
if (StringUtil.isEmpty(key)) {
|
return;
|
}
|
String script = "local current = tonumber(redis.call('get', KEYS[1]) or '0'); "
|
+ "if current <= 1 then redis.call('del', KEYS[1]); "
|
+ "else redis.call('decr', KEYS[1]); end; return 1";
|
try (Jedis resource = jedisPool.getResource()) {
|
resource.eval(script, Collections.singletonList(key), Collections.<String>emptyList());
|
}
|
}
|
|
|
/**
|
* 批量获取
|
*
|
* @param kes
|
* @return
|
*/
|
public List<Object> getValues(List<String> kes) {
|
if (null != kes) {
|
Jedis resource = jedisPool.getResource();
|
Pipeline pipelined = resource.pipelined();
|
for (String key : kes) {
|
pipelined.get(key);
|
}
|
List<Object> list = pipelined.syncAndReturnAll();
|
|
closeJedis(resource);
|
pipelined.clear();
|
try {
|
pipelined.close();
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
List<Object> data = new ArrayList<>();
|
for (Object o : list) {
|
if (null != o) {
|
data.add(o);
|
}
|
}
|
return data;
|
}
|
return null;
|
}
|
|
|
/**
|
* 删除key
|
*
|
* @param key
|
*/
|
public void remove(String key) {
|
if (StringUtil.isNotEmpty(key)) {
|
Jedis resource = jedisPool.getResource();
|
Long del = resource.del(key);
|
closeJedis(resource);
|
}
|
}
|
|
|
/**
|
* 删除资源
|
*
|
* @param jedis
|
*/
|
public void closeJedis(Jedis jedis) {
|
if (null != jedis) {
|
jedis.close();
|
}
|
}
|
}
|