ProblemScenario在促销系统中,为某个产品配置了多个促销活动,这些活动已经在进行中。此时创建了一个新的promotion,状态为未启动。价格计算查询促销活动时,只获取未来开始的活动,不获取已经开始的活动,导致产品价格不打折。后台促销系统为了提高价格计算的性能,以产品sku为key,促销活动的集合为value,存储在redis中guava中guava的过期时间为48小时。如果sku在48小时内没有被查询到,本地缓存会使用过期查询策略优先查询guava。如果guava中有数据,则直接返回。如果guava中没有数据,就会去查询redis,然后分析数据存入Guava的问题查询sku的促销活动时,系统获取正在进行的活动存入Guava。48小时后,因为没有请求定价,此时sku对应的本地缓存失效。SKU创建一个新的促销活动,B端触发保存策略将新创建的活动保存到redis和guava,但是这里保存到guava实际上是增量保存,而不是通过sku获取全量活动,导致在guava中只有新增时,会计算活动的价格来查询sku的促销活动,只获取到没有生效的活动,导致价格没有优惠的问题。调整Guava的写法。在创建新的推广活动时,拉取sku对应的全量活动,并将问题放入Guava思考本地缓存这个关键问题时,需要考虑缓存读写的方案是否合理,或者你需要考虑缓存一致性的问题。如果一定要用guava,就必须把所有的数据都写入到DB中,重新获取受影响的数据,而不是增量的形式。比如在写数据到DB之前删除redis中的数据,写到DB之后加锁,从DB中获取全量数据存储到redis中(避免高并发压垮DB)。然后通知所有实例删除guava缓存,所有请求在查询时都会重新从redis中读取数据。当然,具体的数据删除和写入逻辑需要结合具体场景进行讨论。这里重点讲解的是受影响的数据需要全量更新上面的案例中,价格计算查询业务其实应该理解为强一致性场景,guava很难解决一致性问题。在后续的优化中,应该考虑去掉本地缓存,统一从redis中获取数据,并使用读写锁的概念,write数据不能同时读取,否则极端场景下,计算用户对同一时刻的感知结果可能不同
