【业务场景】
项目部署在两台服务器上,现在要实现数据实时更新的功能,如何避免两台服务器高并发情况下重复更新数据的问题?
【解决办法】
使用redis分布式锁,一台服务器更新时,另一台被阻塞无法进行更新操作
【代码实现】
pom.xml导入redis依赖
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;
@Component
public class DateUpdateConfig {
private static final String LOCK_KEY = "data-update-lock";//锁名称
private static final String LOCK_VALUE = "locked";//值
private static final int LOCK_EXPIRE_SECONDS = 60;//时间
//创建锁
private Jedis jedis = new Jedis("localhost", 6379);
public boolean releaseLock() {
//高并发防止被误删
String releaseLock = "if redis.call('get',KEYS[1])==ARGV[1] then " + "return redis.call('del',KEYS[1])" + "else" + "return 0" + "end";
String lockHolder = jedis.get(LOCK_KEY);
if (LOCK_VALUE.equals(lockHolder)) {
Long code = (Long) jedis.eval(releaseLock, 1, LOCK_KEY, LOCK_VALUE);
return code == 1;
}
return false;
}
private void updateDataInDatabase() {
// 执行数据更新操作
}
public void updateData() {
// 获取分布式锁
String result = jedis.set(LOCK_KEY, LOCK_VALUE, SetParams.setParams().nx().ex(LOCK_EXPIRE_SECONDS));
// 判断是否成功获取到锁
if (result != null && result.equalsIgnoreCase("OK")) {
try {
// 执行数据更新操作
updateDataInDatabase();
} finally {
releaseLock();
}
} else {
// 锁已被其他服务器获取,跳过任务执行
System.out.println("获取锁失败");
}
}
}