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的keyString key = "data";
//设置key的默认值String value = "default";
// 开启watchredisTemplate.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中读取的值能够符合预期,就必须做好相关的解决办法,否则会对应用产生不良影响。