踩坑修BugRedis项目实践之路(redis 项目 坑)

2023-05-12 14:19:17 实践 项目 之路

Bug修复是软件开发中必不可少的一环,特别是在分布式项目中,更要注意数据处理和通信的安全性。接下来本文分享一个具体的Redis实践项目中的踩坑Bug修复的过程。

我们需要在Redis中存储一些数据,代码如下:

“`java

String keyKey = String.format(KEYS_KEY_PATTERN, condition.getKey());

try {

Set keySet = Sets.newHashSet(JsonUtils.parseAsListString(

jRedisClient.get(keyKey, condition.getAppId())));

keySet.add(condition.getValue());

jRedisClient.set(keyKey, JsonUtils.toString(keySet), condition.getAppId());

} catch (Exception e) {

LOGGER.error(“fled to set keys to redis.”, e);

}

该代码用于从Redis中获取一个Set并更新新的内容,然而在多线程环境下却常会发生竞态条件,即在取得内容后新内容又更新,再次更新的结果无法理解原有的内容,我们该如何解决?
为此,我们可以采用redis中的watch功能,代码如下:
```java
String keyKey = String.format(KEYS_KEY_PATTERN, condition.getKey());
boolean canSet = false;
try {
jRedisClient.watch(keyKey, condition.getAppId());
Set valueSet = Sets.newHashSet(JsonUtils.parseAsListString(
jRedisClient.get(keyKey, condition.getAppId())));
valueSet.add(condition.getValue());
Transaction transaction = jRedisClient.multi();
transaction.set(keyKey, JsonUtils.toString(valueSet), condition.getAppId());
List result = transaction.exec();
if (null != result) {
canSet = true;
}
} catch (Exception e) {
LOGGER.error("fled to set keys to redis.", e);
}
if (!canSet) {
LOGGER.info("Data changed by concurrent! Parameter: " + condition.toString());
}

即在执行操作之前,先调用watch对指定key对value进行监控,当watch发现value的值发生变化时,所有的事务命令将被取消,最终exec返回null,否则canSet = true,一切正常。

至此,使用redis watch功能可以解决Redis分布式多线程环境中数据变更冲突的问题,从而更有效地保护Redis数据安全性。

相关文章