一、缓存穿透的解决方案

为了演示缓存穿透,这里设置的redis是单机单实例。

二、缓存穿透之布隆过滤器

布隆过滤器能够迅速判断一个元素是否存在于集合里。

布隆过滤器缺点:

1.会有1%的误判率,误判概率越低,数组所占用的空间越长。

2.布隆过滤器的数据只能添加,不能移除,主要是由于多个数据可能存在于同一个位置,比如subCat:2、subCat:3。

3.维护起来比较麻烦,代码复杂。

三、缓存雪崩与预防

1.什么是缓存雪崩?

当在同一时刻缓存里有大量的key过期时间结束,此时有大量过期的key请求,这时就会有大量的请求落到数据库,数据库承载不了这么大的数据访问,就会宕机。

2.雪崩预防

对于雪崩来说,我们不可能完全解决,只能对它预防,缓解雪崩的现象

预防方法如下:

(1)永不过期

(2)过期时间错开

比如热点数据可以把过期时间设置久一点,或者永不过期;其他不长访问的数据的过期时间设置短一点;在设置过期时间时,比如设置1小时过期,精确到毫秒就是1*60*60*1000,那么就可以在1分钟之内(60*1000)取随机数,每次在1小时的基础上加或减随机数。

(3)多缓存结合(多级缓存)

Memcache中的key过期时间设置的比redis的过期时间长,这样的话,redis中的key过期了就会去查Memcache

 (4)采购第三方Redis

第三方服务还是很牛的,不用自己维护,减少运维成本。

阿里云Redis 

HA:就相当于哨兵形式,SlaveN:有很多slave节点,都是哨兵模式

四、缓存穿透和缓存雪崩的区别

 穿透是单个的key不存在于redis,雪崩是指大面积的key失效;两者都是由于超高流量的并发打在数据库上,造成数据库不可用。

五、multiGet 批量查询优化

每次get查询,其实就是建立一个连接,等get之后,再关闭连接。(socket通信),这样是会有IO损耗的,我们实现mget,这样对于批量查询,只建立一次连接。

/**
	 * 批量查询,对应mget
	 * @param keys
	 * @return
	 */
	public List<String> mget(List<String> keys) {
		return redisTemplate.opsForValue().multiGet(keys);
	}

六、pipeline 批量查询优化

除了用mget批量查询,还可以用管道。

就如keepalive对nginx的作用:建立一次连接,pipeline对redis的作用也是建立一次连接,可以在管道内部进行很多类型的操作,如get,mget,range,set,mset等

/**
	 * 批量查询,管道pipeline
	 * @param keys
	 * @return
	 */
	public List<Object> batchGet(List<String> keys) {

//		nginx -> keepalive
//		redis -> pipeline

		List<Object> result = redisTemplate.executePipelined(new RedisCallback<String>() {
			@Override
			public String doInRedis(RedisConnection connection) throws DataAccessException {
				StringRedisConnection src = (StringRedisConnection)connection;

				for (String k : keys) {
					src.get(k);
				}
				return null;
			}
		});

		return result;
	}

 为什么实现了mget方法,还要实现pipeline方法批量查询?

因为pipeline支持更多类型的操作,set,get,mget,mset,range等,不仅仅支持String类型,其他类型也支持。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐