Redis中读取的值非预期(redis读回来的值不对)

  当在Redis中读取的值和预期的不一致时,就会出现一定问题。具体问题可以分为两类:一是缓存击穿,二是数据脏读。在遇到这些情况时,如何处理是我们必须面临的难题。

### 1.缓存击穿

  缓存击穿是指当某个被缓存的数据,因为某些原因(例如数据库、缓存等数据源改变),出现了缓存失效,导致大量涉及到这些被缓存数据的请求直接打到数据库中,大量应用系统访问流量,从而导致数据库连接数及其瓶颈,出现雪崩效应。

  解决方案:为了解决缓存击穿,通常可以采取的措施如下:

1.给缓存数据设置过期时间;

2.缓存访问加锁,避免对相同缓存数据发出多条请求,减轻数据库压力;

//先设定一个null值
String value = null;

// 加锁
synchronized {
// 从redis中获取值
value = redisTemplate.opsForValue().get(“key”);
// 如果获取的值是空,则从数据库中获取
if (value == null){
value = getValueFromDB();
}
// 设置锁的过期时间
redisTemplate.opsForValue().set(“lock”,“locked”,10,TimeUnit.SECONDS);
}

//获取数据库中的值
private String getValueFromDB(){
String value = db.queryValue();

// 将数据库的值保存到redis中
redisTemplate.opsForValue().set(key, value);
return value;
}

### 2.数据脏读

  数据脏读指的是从数据库中读取数据时,在数据库中某行数据正在被事务处理,但客户端仍然可以读到,这种数据被称为脏数据,导致以上现象即脏读。

  解决办法:Redis中解决数据脏读有以下办法:

1.在新增,修改,删除操作时使用watch机制;

2.利用redis的锁原子操作来确保数据的一致性;

//定义一个随机数
Random random = new Random();

//设置一个Redis的key
String key = "data";
//设置key的默认值
String value = "default";
// 开启watch
redisTemplate.watch(key);
//随机等待几秒
int sleepTime = random.nextInt(1000);
Thread.sleep(sleepTime);

//获取key的值
String currentValue = redisTemplate.opsForValue().get(key);
//给key设置新的值
String newValue = “new”;
redisTemplate.opsForValue().set(key, newValue);

//进行乐观锁处理
if (currentValue.equals(value)){
System.out.println("数据正常更新");
}else {
System.out.println("发现数据被更改,回滚更新");
redisTemplate.unwatch();
}

  以上就是在Redis中读取的值非预期的情况下处理缓存击穿和数据脏读的具体步骤,要确保Redis中读取的值能够符合预期,就必须做好相关的解决办法,否则会对应用产生不良影响。


数据运维技术 » Redis中读取的值非预期(redis读回来的值不对)