缓存可以建立在客户端也可以建立在服务端(注意这里是广义的客户端、服务端,服务A向服务B发请求,那么A就是客户端)
理论上来将每个服务端都应该给自己建立缓存,因为微服务要有一定的互不信任原则(请求先到你,你做过校验了,我不一定信)
最常用方式,就是先去看缓存有没有,有就返回,没有就去数据库读。
写的话直接写数据库去,然后删除缓存。
为啥不更新缓存而是删除缓存? 因为更新容易造成时序性问题:
thread1更新mysql为4 -> thread2更新mysql为2 -> thread2更新缓存为2 -> thread1更新缓存为4
起一个中间服务,客户端就查你这个代理,不知道查的是缓存还是数据库。一切和缓存、数据库的交道都由这个代理来做。
也是起了一个中间服务,只要发起写请求,代理就直接写数据库,然后同步更新redis。一般和read through搭配使用。
但这个对缓存压力比较大,只要更新了数据就得一同更新redis,对比旁路缓存是删除缓存数据的
和write through一样,只不过写完数据库不立即写缓存,而是异步的写缓存(找一个合适时间点,比如低负载时候;或者累计几个一并写入)。
缓存和数据库都没有这个数据,一般是被攻击了,有人频繁查询不存在的key。
解决方法:
缓存没有,数据库有。通常是某一时刻,一个热点数据过期,恰好此时并发用户特别多来访问这个数据,结果都打到数据库上了。
解决方法:
缓存没有数据库有。通常是缓存中大批数据同时过期了,而这时候大量查询过来了,让数据库压力过大甚至宕机。
解决方法:
就是redis和mysql数据不一致了,主要有三种方式。但其实兜兜转转说一堆假设产品对一致性要求极高,尽量别用缓存
实现起来成本低,但是这就得容忍一段时间的数据库和缓存不一致问题了。
操作分为两种一种是更新另一种是删除,更倾向于使用后一种。假设删除失败了,会退化成第一种方案。
redis作为mysql一个slave,订阅mysql的binlog日志,解析日志后更新回redis。这种方式要搭建一个同步服务,成本大一点,但是解耦了,更新mysql后不需要做额外的工作,比较适合数据过期时间长甚至是不过期的场景(这是原因,是因为这种场景,才会用到这种订阅binlog模式)。