1.前言
如果缓存服务在本地的ehcache中都读取不到数据,这个时候就意味着,需要重新到源头的服务中去拉去数据,拉取到数据之后,赶紧先给nginx的请求返回,同时将数据写入ehcache和redis中。
2.缓存服务更新问题
2.1 多个缓存服务实例分布式重建的并发冲突问题![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/b10b8be237793ee2d4c3eee492533fce.png)
一般会部署多个cache实例,同一个商品,多次请求时,可能会到达不同的cache实例上,会造成生成多个缓存,上次已缓存了,还需要缓存,失去缓存的意义了。还有个问题,当拉取12:00的商品数据时,但未更新到redis,此时另外一个请求,拉取到12:01的商品数据,并更新到redis了,然后前面一个请求,在更新redis,此时redis的商品数据为12:00。
解决思路:在应用层nginx编写lua脚本,使同一个商品分发到同个cache实例。
2.2 数据变更缓存重建以及空缓存请求重建并发问题
有二个业务场景,可能会导致同时更新cache服务。商品数据发生变更时,cache能监听到此事件,从而更新本地缓存和redis,然而来了一个请求,也会促使cache更新缓存。如果第二个事件,先更新本地缓存,并没有及时更新redis缓存
,第一个事件更新本地缓存和redis后,第二个事件才更新redis,会导致redis的数据不是最新的。
解决方案:基于zookeeper分布式锁的解决方案。
-
分布式锁,如果你有多个机器在访问同一个共享资源,那么这个时候,如果你需要加个锁,让多个分布式的机器在访问共享资源的时候串行起来
-
那么这个时候,那个锁,多个不同机器上的服务共享的锁,就是分布式锁
-
分布式锁当然有很多种不同的实现方案,redis分布式锁,zookeeper分布式锁
-
zk,做分布式协调这一块,还是很流行的,大数据应用里面,hadoop,storm,都是基于zk去做分布式协调
-
zk分布式锁的解决并发冲突的方案:
(1)数据变更缓存重建以及空缓存请求重建,更新redis之前,都需要先获取对应商品id的分布式锁
(2)拿到分布式锁之后,需要根据时间版本去比较一下,如果自己的版本新于redis中的版本,那么就更新,否则就不更新
(3)如果拿不到分布式锁,那么就等待,不断轮询等待,直到自己获取到分布式的锁