前几日做了一个类似论坛的功能实现,话不多说,上代码
工具类 JedisUtil
@Component public class JedisUtil { private static JedisPool jedisPool; private static String prefix = ""; private static String redisHost; private static Integer redisPort; private static final String LOCK_SUCCESS = "OK"; private static final Long RELEASE_SUCCESS = 1L; @Value("${jedisPrefix}") public void setJedisClusterPrefix(String jedisClusterPrefix) { if (ToolUtil.isNotEmpty(jedisClusterPrefix)) { prefix = jedisClusterPrefix + "_"; } } @Value("${jedisHostList}") private void initRedisHostInfo(String hosts) { String[] split = hosts.split(":"); redisHost = split[0]; redisPort = Convert.toInt(split[1]); redisPoolFactory(); } /** * Jedis初始化 * * @since 2020-02-26 */ public static void redisPoolFactory() { //连接超时 //读取数据超时 Integer timeout = 10000; //最大连接数 Integer maxTotal = 50; //连接阻塞时间-1为无限等待 Long maxWait = -1L; //最大空闲连接 Integer maxIdle = 10; //最小空闲连接 Integer minIdle = 5; JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); jedisPoolConfig.setMaxIdle(maxIdle); jedisPoolConfig.setMaxWaitMillis(maxWait); jedisPoolConfig.setMaxTotal(maxTotal); jedisPoolConfig.setMinIdle(minIdle); jedisPool = new JedisPool(jedisPoolConfig, redisHost, redisPort, timeout, pwd); } /** * 获取字符串 * * @since 202-02-26 */ public static String getString(String key, int... second) { Jedis jedis = jedisPool.getResource(); String res = ""; key = prefix + key; try { res = jedis.get(key); expireInside(jedis, key, second); return res; } catch (Exception e) { e.printStackTrace(); return null; } finally { jedis.close(); } } /** * 写入字符串 * * @since 2020-02-26 */ public static void setString(String key, String data, int... second) { Jedis jedis = jedisPool.getResource(); try { key = prefix + key; jedis.set(key, data); expireInside(jedis, key, second); } catch (Exception e) { e.printStackTrace(); } finally { jedis.close(); } } /** * 设置key的时间 * * @since 2020-02-26 */ public static Long expire(String key, Integer second) { Jedis jedis = jedisPool.getResource(); key = prefix + key; try { return jedis.expire(key, second); } catch (Exception e) { e.printStackTrace(); return null; } finally { jedis.close(); } } /** * Redis分布式锁判定 * * @since 2020-02-26 */ public static Object eval(String key, List<String> keys, List<String> args) { Jedis jedis = jedisPool.getResource(); key = prefix + key; try { return jedis.eval(key, keys, args); } catch (Exception e) { e.printStackTrace(); return null; } finally { jedis.close(); } } /** * 延长key的时间 * * @since 2020-02-26 */ private static void expireInside(Jedis jedis, String key, int... second) { if (ToolUtil.isNotEmpty(key) && second.length > 0) { Integer temp = 1800; temp = second[0]; jedis.expire(key, (int) (temp + Math.random() * (temp * 2))); } } /** * 尝试获取分布式锁 * * @param lockKey 锁 * @param requestId 请求标识 * @param expireTime 超期时间 * @return 是否获取成功 */ public static boolean tryGetLock(String lockKey, String requestId, int expireTime) { Jedis jedis = jedisPool.getResource(); try { lockKey = prefix + lockKey; SetParams setParams = new SetParams(); String result = jedis.set(lockKey, requestId, setParams.nx().px(expireTime)); if (LOCK_SUCCESS.equals(result)) { return true; } return false; } catch (Exception e) { e.printStackTrace(); return false; } finally { jedis.close(); } } /** * 释放分布式锁 * * @param lockKey 锁 * @param requestId 请求标识 * @return 是否释放成功 */ public static boolean releaseLock(String lockKey, String requestId) { Jedis jedis = jedisPool.getResource(); try { lockKey = prefix + lockKey; String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return " + "0 end"; Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList (requestId)); if (RELEASE_SUCCESS.equals(result)) { return true; } else { return false; } } catch (Exception e) { e.printStackTrace(); return false; } finally { jedis.close(); } } }
实际代码调用
//uuid String requestId = UuidUtils.getUUID(); //分布式锁 String topicLock = "topicLock_" + topicId; boolean flag = true; if (条件) { //循环获取锁 次数自己定义 for (int i = 0; i < 3; i++) { //传入参数 key uuid 存活时间 boolean keySuccess = JedisUtil.tryGetLock(topicLock, requestId, 10); //如果获取到锁 if (keySuccess) { //进行逻辑操作 xxxzzzzxxxxx //释放锁 或者超过10秒自己释放 JedisUtil.releaseLock(topicLock, requestId); break; } Thread.sleep(300L); } }
这是在jedis基础上自己封装的分布式锁,跟redistemplate分布式锁一样存在集群中锁异常关闭导致重复获取锁的问题,简单业务可以应用,如果业务庞大且服务器不稳定,建议选择zk做分布式锁