linux redis maxwait,redis连接拥塞。我不知道这样说对不对?

问题:

在实际项目中,我采用redis做资源锁。获取锁的线程才允许执行。然后再最后释放锁的时候。线程堵塞了16分钟后才能释放资源。

尝试解决:

我试着加大redispool的数量也无法解决。然后又查看了jedispool 的部分源码。查看默认属性中无法找到 16 分钟 或 960 秒 或 960000 毫秒 965或965000的配置。

我释放资源的地方

try {

xxxxxxxxxxx

}

} catch (Exception e) {

} finally {

//释放锁

log.info(targetPar + "." + methodPar + ":释放资源锁");

if (StringUtil.isNotEmpty(userId)) {

redisLock.unLock(userId);

}

}

加锁的代码

/**

*

* @Description

* @author lxlong

* @param lockKey 键

* @param expiretime 超时时间,默认为 30*1000 (单为毫秒)

* @return

* @throws LockOccupiedException 加锁失败

*/

public boolean lockKey(String lockKey, Integer expiretime) throws LockOccupiedException {

//添加锁前缀,避免相同key 被误删。

key = LOCK_PREFIX.concat(lockKey);

//设置默认超时时间

if(expiretime == null || expiretime <= 0){

expiretime = defaultExpireTime;

}

String expiresStr = String.valueOf(System.currentTimeMillis() + expiretime);

if(redisService.setNX(key, expiresStr)){

log.info("---------------" + key + "加锁成功-------------------");

myExpireTime = expiresStr;

isLock = true;

return true;

}

String currentValueStr = redisService.get(key); //redis里的时间

if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {

log.info("===================前一锁已超时========================");

//判断是否为空,不为空的情况下,如果被其他线程设置了值,则第二个条件判断是过不去的

//锁超时,设置新锁

String oldValueStr = redisService.getAndSet(key, expiresStr);

//获取上一个锁到期时间,并设置现在的锁到期时间,

//只有一个线程才能获取上一个线上的设置时间,因为jedis.getSet是同步的

if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {

myExpireTime = expiresStr;

isLock = true;

log.info("---------------" + key + "加锁成功-------------------");

return true;

}

}

throw new LockOccupiedException();

}

释放资源的代码如下

/**

* 释放锁

* @Description

* @author lxlong

* @param lockKey

*/

public void unLock(String lockKey) {

if(isLock){

lockKey = LOCK_PREFIX.concat(lockKey);

String expiresStr = redisService.get(lockKey);

//判断是否超时,若时间值不一致说明锁已被其他线程获取,不用释放

if(expiresStr.equals(myExpireTime)){

redisService.delete(lockKey);

log.info("---------------" + lockKey + "释放成功-------------------");

} else {

log.info("---------------" + lockKey + "已被其他线程获取/未获取到锁-------------------");

}

}

}

/**

* 删除 (non-Javadoc)

*

* @see com.leyizhu.dao.redis.RedisDao#delete(java.lang.String)

*/

public boolean delete(final String key) {

boolean result = redisTemplate.execute(new RedisCallback() {

public Boolean doInRedis(RedisConnection connection) throws DataAccessException {

RedisSerializer serializer = getRedisSerializer();

byte[] jkey = serializer.serialize(key);

if (connection.exists(jkey)) {

connection.del(jkey);

return true;

} else {

return false;

}

}

});

return result;

}

实际中出现的问题如下:

[INFO] 2019-01-23 06:20:32 ---> ---------------LOCK_PREFIX_7170e8b3ed2144b48bf9ac8bebd29733加锁成功-------------------

[INFO] 2019-01-23 06:20:32 ---> =====================用户签到=====================

[INFO] 2019-01-23 06:20:32 ---> ------------------sign-----end

[INFO] 2019-01-23 06:20:32 ---> apiUserInfoTokenControl.sign:释放资源锁

[INFO] 2019-01-23 06:36:37 ---> ---------------LOCK_PREFIX_7170e8b3ed2144b48bf9ac8bebd29733释放成功-------------------

apiUserInfoTokenControl.sign:释放资源锁

-LOCK_PREFIX_7170e8b3ed2144b48bf9ac8bebd29733释放成功

之间时间差为 16分05秒,965 millisecond。这段时间不知到发生了什么?

而且这段时间之内,对其他线程没有影响,可以正常操作redis。

这种问题基本上2-3天出现一次,没有规律可循。

环境配置

服务器配置

CPU: 2核

内存: 16 GB

实例类型: I/O优化

操作系统: Aliyun Linux 17.1 64位

redis配置

redis 4.0

redis.host=127.0.0.1

redis.port=6379

redis.pass=123456

redis.minIdle=5

redis.maxIdle=10

redis.maxTotal=50

redis.timeout=2000

redis.maxWait=6000

redis.testOnBorrow=true

spring-redis.xml

然后现在我删除key的方法改了一下下 然后效果还是一样。删除的时候会拥塞16分钟零4秒

/**

* 删除 (non-Javadoc)

*

* @see com.leyizhu.dao.redis.RedisDao#delete(java.lang.String)

*/

public boolean delete(final String key) {

redisTemplate.delete(key);

return true;

// boolean result = redisTemplate.execute(new RedisCallback() {

// public Boolean doInRedis(RedisConnection connection) throws DataAccessException {

// RedisSerializer serializer = getRedisSerializer();

// byte[] jkey = serializer.serialize(key);

// if (connection.exists(jkey)) {

// connection.del(jkey);

// return true;

// } else {

// return false;

// }

// }

// });

// return result;

}

这是现在的日志,我在删除之前加了一段日志 准备释放 XXXXXXX 。用于确定是删除的时候拥塞的

[INFO] 2019-01-29 04:00:48 ---> ---------------LOCK_PREFIX_c3372edaae224b409ce87684d6abc125加锁成功-------------------

[INFO] 2019-01-29 04:00:48 ---> -----------------------------准备释放LOCK_PREFIX_c3372edaae224b409ce87684d6abc125

[INFO] 2019-01-29 04:16:52 ---> ---------------LOCK_PREFIX_c3372edaae224b409ce87684d6abc125释放成功-------------------

最近发现只要有调用redis删除key的地方都有可能出现拥塞。拥塞时间也是在16分钟左右。基本上可确定是 redis.delete(key) 这一块的问题。但是还是不知道具体原因,以及解决办法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值