RedisTemplateUtil 基于redisTemplate 封装redis 工具类 和 redis 用作分布式锁的 配置

@Component
public class RedisTemplateUtil {

private static final Logger logger = LoggerFactory.getLogger(RedisTemplateUtil.class);

@Autowired
private RedisTemplate<String, Object> redisTemplate;

/**
 * 写入缓存
 * 
 * @param key
 * @param value
 * @return
 */
public boolean set(final String key, String value) {
	boolean result = false;
	try {
		redisTemplate.opsForValue().set(key, value);
		result = true;
	} catch (Exception e) {
		logger.error("RedisTemplateUtil.set error: ", e);
	}
	return result;
}

/**
 * 写入缓存设置时效时间
 * 
 * @param key
 * @param value
 * @return
 */
public boolean set(final String key, String value, Long expireTime) {
	boolean result = false;
	try {
		redisTemplate.opsForValue().set(key, value,expireTime, TimeUnit.SECONDS);
	//	redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
		result = true;
	} catch (Exception e) {
		logger.error("RedisTemplateUtil.set error: ", e);
	}
	return result;
}

/**
 * 批量删除对应的value
 * 
 * @param keys
 */
public void remove(final String... keys) {
	for (String key : keys) {
		remove(key);
	}
}

/**
 * 批量删除key
 * 
 * @param pattern
 */
public void removePattern(final String pattern) {
	Set<String> keys = redisTemplate.keys(pattern);
	if (keys.size() > 0) {
		redisTemplate.delete(keys);
	}

}

/**
 * 删除对应的value
 * 
 * @param key
 */
public void remove(final String key) {
	if (exists(key)) {
		redisTemplate.delete(key);
	}
}

/**
 * 判断缓存中是否有对应的value
 * 
 * @param key
 * @return
 */
public boolean exists(final String key) {
	return redisTemplate.hasKey(key);
}

/**
 * 读取缓存
 * 
 * @param key
 * @return
 */
public String get(final String key) {
	ValueOperations<String, Object> operations = redisTemplate.opsForValue();
	String result = (String) operations.get(key);
	return result;
}

/**
 * 将一个值插入到列表头部
 * 
 * @param k
 * @param v
 */
public <T> void lPush(String k, T v) {
	redisTemplate.opsForList().leftPush(k, v);
}

/**
 * 将一个值插入到列表的尾部(最右边)
 * 
 * @param key
 * @param value
 */
public <T> void rPush(String key, T value) {
	redisTemplate.opsForList().rightPush(key, value);
}

/**
 * 将多个值插入到列表头部
 * 
 * @param k
 * @param v
 */
public <T> void lPushAll(String k, Collection<T> v) {
	redisTemplate.opsForList().leftPushAll(k, v);
}
	
/**
 * 将多个值插入到列表的尾部(最右边)
 * 
 * @param key
 * @param value
 */
public void rPushAll(String key, Object... values) {
	redisTemplate.opsForList().rightPushAll(key, values);
}

/**
 * 返回列表中指定区间内的元素,区间以偏移量 start 和 end 指定
 * @param k
 * @param start
 * @param end
 * @return
 */
public <T> List<T> lRange(String k, long start, long end) {
	ListOperations<String, T> list = (ListOperations<String, T>) redisTemplate.opsForList();
	return list.range(k, start, end);
}

/**
 * 往集合Set中添加元素
 * @param k
 * @param v
 * @return
 */
public boolean sadd(String k, Object... v){
	boolean flag = false;
	try {
		redisTemplate.opsForSet().add(k, v);
		flag = true;
	} catch (Exception e) {
		logger.error("RedisTemplateUtil.sadd error: ", e);
	}
	return flag;
}

/**
 * 判断成员元素是否是集合Set的成员
 * @param k
 * @param v
 * @return
 */
public boolean sismember(String k, Object v){
	boolean flag = false;
	try {
		flag = redisTemplate.opsForSet().isMember(k, v);
	} catch (Exception e) {
		logger.error("RedisTemplateUtil.sismember error: ", e);
	}
	return flag;
}

public boolean sismember2(String k, Object v){
	return redisTemplate.opsForSet().isMember(k, v);
}

/**
 * 读取缓存
 *
 * @param key
 * @return
 */
public Object genValue(final String key) {
	Object result = null;
	ValueOperations<String, Object> operations = redisTemplate.opsForValue();
	result = operations.get(key);
	return result;
}

/**
 * 将一个成员元素及其分数值加入到有序集当中
 * @param key
 * @param member
 * @param score
 * @return
 */
public boolean zadd(String key, Object member, double score){
	boolean flag = false;
	try {
		redisTemplate.opsForZSet().add(key, member, score);
		flag = true;
	} catch (Exception e) {
		logger.error("RedisTemplateUtil.zadd error: ", e);
	}
	return flag;
}

/**
 * 返回有序集中,成员的分数值
 * @param key
 * @param member
 * @return
 */
public Double zscore(String key, Object member) {
	return redisTemplate.opsForZSet().score(key, member);
}

/**
 * 移除有序集中的一个或多个成员
 * @param key
 * @param member
 * @return
 */
public void zrem(String key, Object... member) {
	redisTemplate.opsForZSet().remove(key, member);
}

/**
 * 返回有序集合中指定分数区间的成员列表。有序集成员按分数值递增(从小到大)次序排列
 * @param key
 * @param min
 * @param max
 * @return
 */
public Set<Object> zrangeByScore(String key, double min, double max) {
	return redisTemplate.opsForZSet().rangeByScore(key, min, max);
}

/**
 * 返回有序集中,指定区间内的成员。其中成员的位置按分数值递增(从小到大)来排序
 * @param key
 * @param start
 * @param end
 * @return
 */
public Set<Object> zrange(String key, long start, long end) {
	return redisTemplate.opsForZSet().range(key, start, end);
}

/**
 *  如果key存在,写入缓存并设置时效时间;false:key已存在,true:写入成功
 * @param key
 * @param value
 * @param expireTime 单位:秒
 * @return
 */
public boolean setIfAbsent(final String key, String value, Long expireTime) {
	boolean result = false;
	try {
		result = redisTemplate.opsForValue().setIfAbsent(key, value);
		redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
	} catch (Exception e) {
		logger.error("RedisTemplateUtil.setnx error: ", e);
	}
	return result;
}

}

用代码配置redis信息

先准备实体类

@ConfigurationProperties(prefix = “spring.redis.cluster”)
@Component
public class RedisProperties {

private Integer database;

private String nodes;

private Integer connectTimeout;

private Integer readTimeout;

private Integer maxRedirects;

private Integer maxTotal;

private Integer maxWaitMillis;

private Integer maxIdle;

private Integer minIdle;

private boolean testOnBorrow;

private String password;

public String getNodes() {
	return nodes;
}

public void setNodes(String nodes) {
	this.nodes = nodes;
}

public Integer getMaxRedirects() {
	return maxRedirects;
}

public void setMaxRedirects(Integer maxRedirects) {
	this.maxRedirects = maxRedirects;
}

public Integer getMaxIdle() {
	return maxIdle;
}

public void setMaxIdle(Integer maxIdle) {
	this.maxIdle = maxIdle;
}

public Integer getMinIdle() {
	return minIdle;
}

public void setMinIdle(Integer minIdle) {
	this.minIdle = minIdle;
}

public boolean isTestOnBorrow() {
	return testOnBorrow;
}

public void setTestOnBorrow(boolean testOnBorrow) {
	this.testOnBorrow = testOnBorrow;
}

public Integer getMaxTotal() {
	return maxTotal;
}

public void setMaxTotal(Integer maxTotal) {
	this.maxTotal = maxTotal;
}

public Integer getMaxWaitMillis() {
	return maxWaitMillis;
}

public void setMaxWaitMillis(Integer maxWaitMillis) {
	this.maxWaitMillis = maxWaitMillis;
}

public Integer getDatabase() {
	return database;
}

public void setDatabase(Integer database) {
	this.database = database;
}

public Integer getConnectTimeout() {
	return connectTimeout;
}

public void setConnectTimeout(Integer connectTimeout) {
	this.connectTimeout = connectTimeout;
}

public Integer getReadTimeout() {
	return readTimeout;
}

public void setReadTimeout(Integer readTimeout) {
	this.readTimeout = readTimeout;
}

public String getPassword() {
	return password;
}

public void setPassword(String password) {
	this.password = password;
}

}

redis链接信息处理

@Configuration
//@ConditionalOnClass(JedisCluster.class)
public class RedisConfig {

private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);

@Resource
private RedisProperties redisProperties;

/**
 * 配置 Redis 连接池信息
 */
@Bean
public JedisPoolConfig getJedisPoolConfig() {
	JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
	jedisPoolConfig.setMaxTotal(redisProperties.getMaxTotal());
	jedisPoolConfig.setMaxWaitMillis(redisProperties.getMaxWaitMillis());
	jedisPoolConfig.setMaxIdle(redisProperties.getMaxIdle());
	jedisPoolConfig.setMinIdle(redisProperties.getMinIdle());
	jedisPoolConfig.setTestOnBorrow(redisProperties.isTestOnBorrow());
	return jedisPoolConfig;
}

/**
 * 配置 Redis 连接工厂
 * @param jedisPoolConfig
 * @return
 */
@Bean
public JedisConnectionFactory getJedisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
	logger.info("redis配置信息:nodes={}", redisProperties.getNodes());
	
	JedisConnectionFactory jedisConnectionFactory = null;
	
	JedisClientConfiguration.JedisClientConfigurationBuilder builder = JedisClientConfiguration.builder();
	builder.usePooling().poolConfig(jedisPoolConfig);
	builder.connectTimeout(Duration.ofMillis(redisProperties.getConnectTimeout()));
	builder.readTimeout(Duration.ofMillis(redisProperties.getReadTimeout()));
	JedisClientConfiguration jedisClientConfiguration = builder.build();
	
	String[] cNodes = redisProperties.getNodes().split(",");
	// 大于1,集群配置,否则单实例
	if(cNodes.length > 1){
		// 分割出集群节点
		List<RedisNode> nodeList = new ArrayList<>();
		for (String node : cNodes) {
			String[] hp = node.split(":");
			nodeList.add(new RedisNode(hp[0], Integer.parseInt(hp[1])));
		}

		RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();
		redisClusterConfiguration.setClusterNodes(nodeList);
		redisClusterConfiguration.setMaxRedirects(redisProperties.getMaxRedirects());
		if(StringUtils.isNotBlank(redisProperties.getPassword())){
			redisClusterConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword()));
		}
		
		jedisConnectionFactory = new JedisConnectionFactory(redisClusterConfiguration, jedisClientConfiguration);
		jedisConnectionFactory.getStandaloneConfiguration().setDatabase(redisProperties.getDatabase());
	}else{
		// 分割出IP和PORT
		String[] hp = cNodes[0].split(":");
		
		RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
		redisStandaloneConfiguration.setHostName(hp[0]);
		redisStandaloneConfiguration.setPort(Integer.parseInt(hp[1]));
		redisStandaloneConfiguration.setDatabase(redisProperties.getDatabase());
		if(StringUtils.isNotBlank(redisProperties.getPassword())){
			redisStandaloneConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword()));
		}
		
		jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
	}
	
	return jedisConnectionFactory;
}

/**
 * 设置数据存入redis 的序列化方式 redisTemplate序列化默认使用的jdkSerializeable
 * 存储二进制字节码,导致key会出现乱码,所以自定义序列化类
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
	logger.info("初始RedisTemplate Bean,修改默认序列化方式");
	// 使用Jackson2JsonRedisSerialize 替换默认序列化
	Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
	ObjectMapper objectMapper = new ObjectMapper();
	objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
	objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
	jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

	RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
	redisTemplate.setConnectionFactory(redisConnectionFactory);
	redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
	redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
	redisTemplate.setKeySerializer(new StringRedisSerializer());
	redisTemplate.setHashKeySerializer(new StringRedisSerializer());
	redisTemplate.afterPropertiesSet();
	return redisTemplate;
}

@Bean
public RedissonClient redisson() {
	Config config = null;
	String[] nodes = this.convert(Arrays.asList(this.redisProperties.getNodes().split(",")));
	config = new Config();
	((ClusterServersConfig) config.useClusterServers()
			.addNodeAddress(nodes)
			.setConnectTimeout(this.redisProperties.getConnectTimeout()))
			.setReadMode(ReadMode.MASTER_SLAVE)
			.setPassword(this.redisProperties.getPassword());
	return Redisson.create(config);
}



private String[] convert(List<String> nodesObject) {
	List<String> nodes = new ArrayList(nodesObject.size());
	Iterator var3 = nodesObject.iterator();

	while(true) {
		while(var3.hasNext()) {
			String node = (String)var3.next();
			if (!node.startsWith("redis://") && !node.startsWith("rediss://")) {
				nodes.add("redis://" + node);
			} else {
				nodes.add(node);
			}
		}

		return (String[])nodes.toArray(new String[nodes.size()]);
	}
}

}

Jedis 用作来做分布式锁

@Component
public class JedisDistributedLock {

private final Logger logger = LoggerFactory.getLogger(JedisDistributedLock.class);

private static String LOCK_PREFIX = "JedisDistributedLock_";

private static final long LOCK_EXPIRE = 60000;

private DefaultRedisScript<Boolean> lockScript;

@Resource
private RedisTemplate<Object, Object> redisTemplate;

public static final String UNLOCK_LUA;

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();
}

public boolean setLock(String key, long expire) {
    try {
        Boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.set(key.getBytes(), getHostIp().getBytes(), Expiration.seconds(expire) ,RedisStringCommands.SetOption.ifAbsent());
            }
        });
        return result;
    } catch (Exception e) {
        logger.error("set redis occured an exception", e);
    }
    return false;
}

/**
 * 删除锁
 *
 * @param key
 */
public void delete(String key) {
    redisTemplate.delete(key);
}

public String get(String key) {
    try {
        RedisCallback<String> callback = (connection) -> {
            JedisCommands commands = (JedisCommands) connection.getNativeConnection();
            return commands.get(key);
        };
        String result = redisTemplate.execute(callback);
        return result;
    } catch (Exception e) {
        logger.error("get redis occured an exception", e);
    }
    return "";
}

/**
 * 释放锁操作
 * @param key
 * @param value
 * @return
 */
private boolean releaseLock(String key, String value) {
    lockScript = new DefaultRedisScript<Boolean>();
    lockScript.setScriptSource(
            new ResourceScriptSource(new ClassPathResource("unlock.lua")));
    lockScript.setResultType(Boolean.class);
    // 封装参数
    List<Object> keyList = new ArrayList<Object>();
    keyList.add(key);
    keyList.add(value);
    Boolean result = (Boolean) redisTemplate.execute(lockScript, keyList);
    return result;
}

/**
 * 获取本机内网IP地址方法
 *
 * @return
 */
private static String getHostIp() {
    try {
        Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
        while (allNetInterfaces.hasMoreElements()) {
            NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
            Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
            while (addresses.hasMoreElements()) {
                InetAddress ip = (InetAddress) addresses.nextElement();
                if (ip != null
                        && ip instanceof Inet4Address
                        && !ip.isLoopbackAddress() //loopback地址即本机地址,IPv4的loopback范围是127.0.0.0 ~ 127.255.255.255
                        && ip.getHostAddress().indexOf(":") == -1) {
                    return ip.getHostAddress();
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

}

@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisLockHelper {

private static final String DELIMITER = "|";

/**
 * 如果要求比较高可以通过注入的方式分配
 */
private static final ScheduledExecutorService EXECUTOR_SERVICE = Executors.newScheduledThreadPool(10);

private RedisTemplate<String, Object> redisTemplate;

public RedisLockHelper(RedisTemplate<String, Object> redisTemplate) {
	this.redisTemplate = redisTemplate;
}

/**
 * 获取锁(存在死锁风险)
 *
 * @param lockKey
 *            lockKey
 * @param value
 *            value
 * @param time
 *            超时时间
 * @param unit
 *            过期单位
 * @return true or false
 */
public boolean tryLock(final String lockKey, final String value, final long time, final TimeUnit unit) {
	return redisTemplate.execute((RedisCallback<Boolean>) connection -> connection.set(lockKey.getBytes(),
			value.getBytes(), Expiration.from(time, unit), RedisStringCommands.SetOption.SET_IF_ABSENT));
}

/**
 * 获取锁
 *
 * @param lockKey
 *            lockKey
 * @param uuid
 *            UUID
 * @param timeout
 *            超时时间
 * @param unit
 *            过期单位
 * @return true or false
 */
public boolean lock(String lockKey, final String uuid, long timeout, final TimeUnit unit) {
	final long milliseconds = Expiration.from(timeout, unit).getExpirationTimeInMilliseconds();
	final String expiresStr = (System.currentTimeMillis() + milliseconds) + DELIMITER + uuid;
	boolean success = redisTemplate.opsForValue().setIfAbsent(lockKey, expiresStr);
	if (success) {
		redisTemplate.expire(lockKey, timeout, TimeUnit.SECONDS);
		return true;
	}
	
	String currentValue = (String) redisTemplate.opsForValue().get(lockKey);
	if(StringUtils.isNotEmpty(currentValue) && Long.parseLong(currentValue.split(Pattern.quote(DELIMITER))[0]) < System.currentTimeMillis()){
		String oldVal = (String) redisTemplate.opsForValue().getAndSet(lockKey, expiresStr);
		if(StringUtils.isNotEmpty(oldVal) && oldVal.equals(currentValue) ){
            return true;
        }
	}
	return false;
}

public void unlock(String lockKey, String value) {
	unlock(lockKey, value, 0, TimeUnit.MILLISECONDS);
}

/**
 * 延迟unlock
 *
 * @param lockKey
 *            key
 * @param uuid
 *            client(最好是唯一键的)
 * @param delayTime
 *            延迟时间
 * @param unit
 *            时间单位
 */
public void unlock(final String lockKey, final String uuid, long delayTime, TimeUnit unit) {
	if (StringUtils.isEmpty(lockKey)) {
		return;
	}
	if (delayTime <= 0) {
		doUnlock(lockKey, uuid);
	} else {
		EXECUTOR_SERVICE.schedule(() -> doUnlock(lockKey, uuid), delayTime, unit);
	}
}

/**
 * @param lockKey
 *            key
 * @param uuid
 *            client(最好是唯一键的)
 */
private void doUnlock(final String lockKey, final String uuid) {
	String val = (String) redisTemplate.opsForValue().get(lockKey);
	if(val == null){
		return;
	}
	final String[] values = val.split(Pattern.quote(DELIMITER));
	if (values.length <= 0) {
		return;
	}
	if (uuid.equals(values[1])) {
		redisTemplate.delete(lockKey);
	}
}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python Redis工具类封装Redis数据库操作的一组函数或方法,方便开发人员在Python中使用Redis进行数据存储、读取和修改等操作。它可以简化与Redis的交互流程,提高开发效率。 Python Redis工具类通常包含以下功能: 1. 连接Redis数据库:提供连接Redis数据库的方法,包括指定主机名、端口号和认证信息。 2. 数据保存和读取:提供将数据保存到Redis数据库和从数据库中读取数据的方法,支持多种数据类型(如字符串、哈希、列表、集合、有序集合等)。 3. 数据修改和删除:提供更新和删除数据的方法,可以更新单个键值对或批量操作。 4. 事务和管道支持:提供事务和管道操作的方法,可以提高多个Redis命令的执行效率。 5. 分布式锁支持:提供实现分布式锁的方法,用于并发控制和资源竞争场景。 6. 发布订阅功能:提供发布订阅功能的方法,支持在多个客户端之间发布和接收消息。 7. 集群支持:提供连接Redis集群的方法,支持在多个Redis节点之间进行数据分布和负载均衡。 通过使用Python Redis工具类,开发人员可以更方便地操作Redis数据库,无需手动处理与Redis的连接、事务管理和数据格式转换等细节。同时,Python Redis工具类还提供了一些高级功能,如分布式锁和发布订阅等,可以满足不同的业务需求。 总之,Python Redis工具类是一种简化Redis操作的工具,可以提高开发效率和代码可读性,使开发人员能够更好地利用Redis进行数据存储和处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值