package com.common.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisCommands; import java.util.Collections; /** * <p> * Redis 分佈式鎖 */ public class RedisLock { private static Logger logger = LoggerFactory.getLogger(RedisLock.class); private RedisTemplate<String, Object> redisTemplate; private String key; private String requestId; private long expire = 600 * 1000; private static final String UNLOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; /** * Detailed constructor. */ public RedisLock(RedisTemplate<String, Object> redisTemplate, String key, String requestId) { this.redisTemplate = redisTemplate; this.key = key; this.requestId = requestId; } /** * Detailed constructor. */ public RedisLock(RedisTemplate<String, Object> redisTemplate, String key, String requestId, long expire) { this(redisTemplate, key, requestId); this.expire = expire; } /** * Acquiring a lock. */ public boolean lock() { String result = redisTemplate.execute(new RedisCallback<String>() { @Override public String doInRedis(RedisConnection redisConnection) throws DataAccessException { JedisCommands commands = (JedisCommands) redisConnection.getNativeConnection(); //NX:只有當key不存在是才進行set ; XX:只有當key已經存在時才進行set //過時時間的單位(EX:秒 PX:毫秒) return commands.set(key, requestId, "NX", "PX", expire); } }); boolean isSuccess = StringUtils.isNotEmpty(result); logger.info("Acquiring a lock key = {} , result = {} , requestId = {}", key, isSuccess == true ? "成功" : "失敗", requestId); return isSuccess; } /** * Release a lock. */ public boolean unlock() { Long result = redisTemplate.execute(new RedisCallback<Long>() { @Override public Long doInRedis(RedisConnection redisConnection) throws DataAccessException { return (Long) ((Jedis) redisConnection.getNativeConnection()).eval(UNLOCK_SCRIPT, Collections.singletonList(key), Collections.singletonList(requestId)); } }); boolean isSuccess = result != null && result > 0; logger.info("Release a lock key = {} , result = {} requestId = {}", key, isSuccess == true ? "成功" : "失敗", requestId); return isSuccess; } }
xml配置信息java
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"> <!-- redis服務 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="${ilifecore.dmz.redis.maxIdle}" /> <property name="maxTotal" value="${ilifecore.dmz.redis.maxTotal}" /> <property name="maxWaitMillis" value="${ilifecore.dmz.redis.maxWaitMillis}" /> </bean> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg> <property name="hostName" value="${ilifecore.dmz.redis.host}"></property> <property name="port" value="${ilifecore.dmz.redis.port}"></property> <!-- <property name="password" value="${ilifecore.dmz.redis.password}"></property> --> </bean> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory"/> </bean> </beans>
使用方法redis
package com.biz.quartz; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.RedisTemplate; import javax.annotation.Resource; import java.net.InetAddress; import java.util.UUID; /** * * PCAP投連險價格和收益率同步 */ public class PcapInvestLinkedPriceYieldJob extends SimpleJob { private static Logger logger = LoggerFactory.getLogger(PcapInvestLinkedPriceYieldJob.class); private static final String SYNC_LOCK = "PCAP_INVEST_PRICE_YIELD"; /**定時任務禁用開關**/ private static final String SWITCH="disable"; @Resource(name = "redisTemplate") private RedisTemplate<String, Object> redisTemplate; @Override public void execute() { RedisLock lock = new RedisLock(redisTemplate, SYNC_LOCK, UUID.randomUUID().toString()); try { if (lock.lock()) { } else { logger.info("Acquire redis distributed locks fail, IP: {} LOCK: {} ", InetAddress.getLocalHost().getHostAddress(), SYNC_LOCK); } } catch (Exception e) { } finally { lock.unlock(); } } }