数据查询慢问题以及实现缓存预热
数据查询慢问题
解决办法:使用缓存技术,提前把数据从数据库中取出来,就可以更快的进行读写。
1. 缓存的实现
- Redis(分布式缓存)
- memcached(分布式)
- Etcd(云原生架构的一个分布式存储,存储配置,扩容能力)
- ehcache(单机)
- 本地缓存(Java 内存 Map)
- Caffeine(Java 内存缓存,高性能)
- Google Guava
Redis
NoSQL 数据库
key - value 存储系统(区别于 MySQL,他存储的是键值对)
Redis 数据结构
String 字符串类型: name: "yupi"
List 列表:names: ["yupi", "dogyupi", "yupi"]
Set 集合:names: ["yupi", "dogyupi"](值不能重复)
Hash 哈希:nameAge: { "yupi": 1, "dogyupi": 2 }
Zset 集合:names: { yupi - 9, dogyupi - 12 }(适合做排行榜)
bloomfilter(布隆过滤器,主要从大量的数据中快速过滤值,比如邮件黑名单拦截)
geo(计算地理位置)
hyperloglog(pv / uv)
pub / sub(发布订阅,类似消息队列)
BitMap (1001010101010101010101010101)
Jedis
独立于 Spring 操作 Redis 的 Java 客户端
要配合 Jedis Pool 使用
Lettuce
高阶 的操作 Redis 的 Java 客户端
异步、连接池
Redisson
分布式操作 Redis 的 Java 客户端,让你像在使用本地的集合一样操作 Redis(分布式 Redis 数据网格)
JetCache
对比
- 如果你用的是 Spring,并且没有过多的定制化要求,可以用 Spring Data Redis,最方便
- 如果你用的不是 SPring,并且追求简单,并且没有过高的性能要求,可以用 Jedis + Jedis Pool
- 如果你的项目不是 Spring,并且追求高性能、高定制化,可以用 Lettuce,支持异步、连接池
- 如果你的项目是分布式的,需要用到一些分布式的特性(比如分布式锁、分布式集合),推荐用 redisson
2. 设计缓存的key
不同的用户看到的数据不同,可能为节约资金,一个redis要给多个项目进行使用,所以缓存的key一定不能和其他项目的冲突
systemId:mouduleId:functinoId:objectId
redis内存不能无限增加,一定要设置过期时间!
缓存预热
为什么要进行缓存预热?
因为网站主页第一个用户访问还是很慢,也能一定程度上保护数据库
1. 优点:
解决上述问题,可以让用户始终访问的很快。
2. 缺点:
- 增加开发成本,需要额外的开发和设计
- 预热的时机和时间需要选择好,如果设置错了,有可能缓存的数据不对或很久之前的(比如你缓存的数据是七天之前的数据)
- 需要占用额外的空间(redis可能只有4个G,运行项目时可能需要3个G,但是你缓存的数据量太大,占用了2个G,那么服务会崩掉)
3. 怎么缓存预热?
- 定时
- 模拟触发(手动触发)
4. 实现
用定时任务实现,每天刷新所有用户的推荐列表
注意点:
- 缓存预热的意义(新增少,总用户多)
- 缓存的空间不能太大,要预留给其他缓存空间
- 缓存数据的周期