一、基本逻辑
1、创建商品
a.创建商品数据到数据库
b.创建redis缓存
2、更新商品
a.更新数据库数据
b.更新redis缓存
3、查询商品
a.调用get方法(优先从缓存里面去找数据,如果不为空转成JSON数据,为空则从数据库查询,再往redis放一份)
二、高并发环境
问题1:如果商品数量太大,造成redis的存储问题
解决方案:我们可以在redis中创建商品的时候,设置一个过期时间(如一天),如果没什么访问的商品会在一天之内陆续过期。
问题2:缓存雪崩问题,大量的商品在同一时刻失效
解决方案:使用随机的过期时间 PRODUCT_CACHE_TIMEOUT +new Random().nextInt(30)*60
问题3:缓存穿透问题,大量请求请求不存在的数据
解决方案:如果数据库没查到,将redis中缓存一个空串(不是null),设置一个过期时间 60+new Random().nextInt(30),在查询redis的时候,如果发现返回的是一个空串,给提示。
问题4:大V直播间的带货,短时间某个冷门商品增加
解决方案:提前预热
问题5:某个不确定的时间,因为某些热点问题,某个商品变热,导致大量请求打向数据库。
解决方案:使用双重检测锁,在获取商品的时候添加synchronized锁。
提取方法后做一些修改
问题6:上述代码中的锁,synchronized是jvm级别的,锁对象是有问题的。
解决方案:引入redission的包,创建一个redisson的客户端,引入redisson客户端
问题7:缓存和数据库不一致问题
解决方案:更新方法、查询方法,添加一把锁。
问题8:加锁会导致效率问题,可以采用分布式锁的优化方案,比如分段锁、读写锁。
解决方案:查询用读锁,更新用写锁。
写锁:
读锁:
问题9:redis的并发其实也并不高,所以单个redis节点抗很高并发,会造成问题。
解决方案:采用多级缓存没让我们的系统能抗更多的并发,在jvm进程级别再加一个缓存,比如定义一个map,new concurrentHashmap,在添加redis缓存的时候,再添加一份map缓存,在查询的时候,先查询map,直接返回。
问题10:使用map缓存,如何管理?如何解决数据缓存同步问题。
使用缓存框架Ehcache,可以设置一些策略,做一些数据过期的处理。
解决缓存同步问题,使用mq去实现,或者使用京东热点缓存框架Guava Cache、hotkey
问题11:上述加锁问题,还可以实现串行转并行,具体实现有没有小伙伴解释一下如何实现?
这里补充思考:我们可以使用ReentrantLock去trylock,如果获取不到锁,就去执行其他操作,比如从缓存查的操作,查不到返回空串,查到了返回查到后的数据。
问题12:Ehcache、Guava Cache、hotkey有没有人贴一下具体的实现代码?