缓存优化思路梳理
使用Redis做一级缓存
首先对接口进行压测。无缓存的情况下QPS只有80.
优化步骤
首先考虑所有请求都直接读写mysql肯定是不行的。那么第一想到的是加redis缓存商品数据。查询请求进来首先查询redis缓存,缓存不存在再去读数据库,最后更新缓存。
修改日志级别到warn,减少无效日志 性能提升10%。日志也会影响性能。
不走网关直接走原始服务器,性能提升。(网关处理也会影响性能)
进行三个优化步骤后达到1000QPS。
进一步思考
请求Redis会走网络请求网卡也是影响性能瓶颈的原因。而且存入redis会有序列化和反序列化的开销。会对性能产生影响。此时考虑加入本地缓存,在高并发环境下使用ConcurrentHashMap做缓存。此时考虑缓存不能无限增长的,要对缓存加入淘汰策略。此时采用经典的LRU作为淘汰策略。
缓存击穿问题
使用缓存时,会出现大量缓存失效的问题,此时会有大量的请求去读取数据库。大量的请求同时请求数据库会导致数据库宕机。此种情况下要对数据的读取操作进行同步操作,阻塞大量的数据库请求。考虑到服务时集群形式,此时采用分布式锁来同步读取操作。
可以实现分布式锁的有:
- Redis
- Redssion
- Zookeeper
最后选取了Zookeeper,Redis和Redssion会有死锁问题。
缓存穿透问题
当大量id不存在的请求过去会导致瞬时大量的读取数据库请求。这就是缓存穿透问题。
解决该问题的解决方案会有三个特性:
- 快:处理要快
- 准:判断要准确
- 省:可以压缩数据
redis方案
首先,快这个特性就要求数据要存储到内存中,此时可以考虑将所有的id存到redis中,可以实现快速准确的判断,但是在数据量很大的情况下会占用大量内存。此时可以考虑对数据进行压缩,但是要保证依然可以判断出id是否存在。
布隆过滤器
可以用布隆过滤器,布隆过滤器实际上就是一种压缩数据的方案,可以对数据是否存在进行判断。此时布隆过滤器放到redis。不需要每个实例维护一份布隆过滤器。
布隆过滤器原理
布隆过滤器的组成:
- 多个hash函数
- 位数组
布隆过滤器启动时使用多个hash函数对id进行计算。然后将计算出的多个值在位数组中位置标为1。当要判断的时候就会重复该过程,同时去判断得出的结果的对应位置是不是都为1,主要有一个不为0就说明不存在。
布隆过略器准确性影响因素:
- 哈希函数的个数
- 位数组的长度