场景
接口设计
在设计过程中需要这样的一个接口,获取该电子书参与的所有促销的活动(为了扩展限时抢活动),并且为了扩展满减需要设置满减池子,也就是把参与满减的书籍放到满减的池子中。
错误地方
在与之相关的业务逻辑,需要判断该书是否在满减书籍的池子中,当时没有过多的思考,满减池子中的书籍已经做了缓存,我直接从缓存中取出来,通过productIds.contains(productId),也就是每个书籍的id都要去判断一次,当把满减池子中的书籍加到不到19w的时候,性能上就出现了问题,也即是池子中的Id数量为19w,判断某一个Id是否在其中。
改版第一版本
由于上次的问题,所以把判断放到了db,通过书籍池子中的唯一标识和该本书的productId 来查找该电子书的内容,同时对该书籍添加了缓存,以及对该数据是否参与满减活动添加了缓存。通过测试,当满减书籍的池子19w的时候,测试结果:ELK监控数据hpi访问量每30秒访问数最高8000,最后稳定在7000左右,访问量为高峰期的2倍左右。 服务器监控cpu稳定在15%,服务器正常 ,服务器端平均每秒处理事务515.90。
改版第二版本
线上当满减的池子设置的非常小时,倒是出现了问题,报大量的数据库连接超时问题,问题所在一部分在于,添加缓存的时候,当获取满减池子书籍为空的时候没有添加缓存,也就是只有参与满减的活动才有缓存,而没有参与满减活动的电子书则没有缓存(CollectionUtils.isNotEmpty,添加了是否为空的判断,则丢了一部分缓存),在添加缓存之前判断了,造成大量的数据库访问。
之前设置的缓存失效时间为15min,当缓存大量同时失效的时候,会造成缓存同时构建,同时访问数据,造成对db访问的压力。
于是在缓存失效的时候添加一个随机数,这样就不会缓存同时失效,减少同时访问db的压力。
code如下
masterRedisTemplate.expire(columnMediaIdCacheKeyFlag,
Constans.CACHE_EXPIRE_TIME_OF_MEDIA_PROMOTION_FLAG
+ RandomUtils.nextInt(100), TimeUnit.SECONDS);
参考文章:http://blog.csdn.net/black_ox/article/details/28424371
总结:
不晓得错过了什么,不晓得得到了什么,人生的每个阶段都有舍得。继续go on