Redis 潜在问题
缓存故障
Redis 缓存技术常用于高并发情况下,有效减轻服务器和数据库负载。如果 Redis 出现问题导致无法均衡负载,就可能导致服务崩溃。
- 缓存预热
当系统刚启动时,由于 Redis 尚未保存数据导致无法命中,数据库被频繁请求数据,由于过载导致数据库崩溃。
数据库崩溃后, Redis 和应用服务器无法获取数据,请求积压会进一步导致 Redis 和服务器崩溃。
- 缓存雪崩
当流量激增时,如果 Redis 大量 key 过期导致无法命中,数据库被频繁请求数据,由于过载导致数据库崩溃。
数据库崩溃后, Redis 和应用服务器无法获取数据,请求积压会进一步导致 Redis 和服务器崩溃。
- 缓存击穿
当流量激增时,如果 Redis 某个极高热度的 key 过期导致无法命中,数据库被频繁请求数据,由于过载导致数据库崩溃。
数据库崩溃后, Redis 和应用服务器无法获取数据,请求积压会进一步导致 Redis 和服务器崩溃。
- 缓存穿透
当流量激增时,如果 Redis 收到大量非法访问导致无法命中,数据库被频繁请求数据,由于过载导致数据库崩溃。
数据库崩溃后, Redis 和应用服务器无法获取数据,请求积压会进一步导致 Redis 和服务器崩溃。
一致性问题
如果在缓存中存储数据库数据备份,以提高查询效率,就一定会出现一致性问题,导致脏读。比如数据库中数据从 1 更新到 10 ,但缓存还未更新时读取,就会读取到 1。这个问题难以避免。
- 缓存就是缓存,必须要设过期时间。
- 实时性要求比较高的(比如充值),直接读数据库。
- 数据库并发高需要分库分表。
Redis 客户端
我们在实际使用 Redis 时往往要通过 Redis 客户端,以便在程序中直接操作 Redis 。常使用的 Redis 客户端有 Jedis、 以及功能更为高级的 Redisson、Lettuce 等。
RedisTemplate 类
Spring Boot 提供了 RedisTemplate 工具类直接对 Redis 进行操作,也提供了 StringRedisTemplate 类继承 RedisTemplate 类,两者方法完全一致。
RedisTemplate
类:存储数据时序列化成字节数组保存,在 Redis 中数据为字节码。读取数据时自动转化为对象。StringRedisTemplate
类:存储数据直接以字符串形式保存,在 Redis 中数据直接可读。只适用于字符串类型的数据。
由于两种序列化方法不同导致的数据存储形式差异,两个类之间不能对另一方存储的 Redis 数据进行操作。
常用方法
/* 直接对 key 操作 */ redisTemplate.delete("key"); // 删除 key redisTemplate.delete(collection); // 批量删除 key redisTemplate.expire("key",10,TimeUnit.MINUTES); // 设置 key 失效时间 Long expire = redisTemplate.getExpire("key"); // 获取 key 失效时间 boolean flag = redisTemplate.hasKey("key"); // 判断 key 是否存在 /* 操作字符串 */ redisTemplate.opsForValue().set("key", "value"); // 设置键值对 String str = (String)redisTemplate.opsForValue().get("key"); // 获取键值 /* 操作 hash */ redisTemplate.opsForHash().put("HashKey", "SmallKey", "HashValue"); // 设置键值对 redisTemplate.boundHashOps("HashKey").putAll(hashMap); // 批量设置键值对 String value = (String) redisTemplate.opsForHash().get("HashKey", "SmallKey"); // 获取键值 Map entries = redisTemplate.opsForHash().entries("HashKey"); // 获取全部键值对 redisTemplate.boundHashOps("HashKey").delete("SmallKey"); // 删除键值对 Boolean isEmpty = redisTemplate.boundHashOps("HashKey").hasKey("SmallKey"); // 是否含有键值对 redisTemplate.opsForList(); // 操作 list redisTemplate.opsForSet(); // 操作 set redisTemplate.opsForZSet(); // 操作有序 set