markdown 缓存,本地,远程;

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了markdown 缓存,本地,远程;相关的知识,希望对你有一定的参考价值。

### 缓存client套路

1、缓存不能读到脏数据
2、缓存可能读到过期数据,是否可以容忍一段时间的不一致性,但是可以保证最终一致性(只是达到最终一致性的时间长短不一样)

client缓存套路及存在的问题:

* 先更新数据库,再更新缓存

存在的问题:可能读到脏数据
问题分析:有两个线程A和B进行更新操作

(1)、线程A更新了DB,key=1 value=2
(2)、线程B更新了DB,key=1 value=3
(3)、线程B更新了cache,key=1 value=3
(4)、线程A更新了cache,key=1 value=2

这样就导致了DB和缓存数据不一致的问题,因为DB里面key=1 value=3,而缓存里面是key=1 value=2

解决办法:时间戳 + 版本号(ABA问题)

* 先删除cache,再更新db

存在的问题:脏数据
问题分析:线程A执行更新操作,线程B执行查询操作
(1)、线程A进行写操作,key=1 value=2,先删除了缓存key=1 value=1
(2)、线程B查询缓存发现缓存不存在,然后去db查询得到key=1 value=1,线程B将key=1 value=1写到缓存
(3)、线程A此时将key=1 value=2写到db

这样就造成了db和缓存存储的不一致,db里面key=1 value=2,cache里面则是key=1 value=1
解决办法:
  (1)、先删除cache,再更新db,再回写cache(和第一种方案一样的问题)
  (2)、先删除cache,再更新db,再删除cache(双删,第二次可以异步执行)

* 先更新db,再删除cache

问题:脏数据(小概率)
问题分析:一个线程A做查询,一个线程B做更新
(1)、缓存刚好失效
(2)、线程A查询db,得到key=1 value=1
(3)、线程B将新值key=1 value=2写入db
(4)、线程B更新完db之后删除了cacahekey=1 value=1
(5)、线程A将查到的key=1 value=1写入缓存

这个时候,db和缓存存储的就是不一致的,db是key=1 value=2,cache是key=1 value=1

* 异步更新中间件

比如databus监听db binlog,然后更新缓存。

### 缓存穿透

查询肯定不存在的数据,缓存不命中,走到db,db挂

方案:
(1)、BloomFilter,布隆过滤器,将所有可能存在的key映射到一个足够大的bitmap中去,不存在的key会被bitmap拦截到;但是不存在的key也可能被映射到这块bitmap中去,但是很少;该方法非常高效。
(2)、缓存空结果 + 过期时间:将不存在的结果也缓存起来,设置一个可以容忍的过期时间;实现起来非常简单。

### 缓存雪崩

缓存的多个key设置了相同的过期时间,某一时刻多个缓存key同时失效,请求全部落到db,db奔溃。

方案:
(1)、加锁查db;一个请求查询key,如果miss,则先lock该key,其他请求在该key上等待,直到被唤醒,然后再check一下key是否存在(double check);这种策略下就是说只可能有一个线程会去db加载数据缓存起来。
(2)、错开过期时间,这是最好实现的方式,别让大多数缓存一起失效
(3)、预先加载,当发现缓存快到期的时候异步加载


### 热点击穿

某些时间点,某些Key会被高并发地访问,形成热点Key;热点Key恰好在这时过期了,大量并发打到DB;或是超高并发单Key(一般是hash到单台机上),打满单机的网卡/cpu。


(1)、预判:在value内部设置一个过期时间t1,t1比实际缓存失效时间t2要小,当发现t1已过期,那么就通知重新加载缓存,这样就可以无缝切换新旧值了。
(2)、预热:将热数据提前加载到缓存系统,所有请求直接请求缓存,后台异步线程更新缓存

总结:都是为了让请求直接请求到缓存,而没有到db,异步线程来做db->cache的工作

以上是关于markdown 缓存,本地,远程;的主要内容,如果未能解决你的问题,请参考以下文章

markdown 在本地和远程删除Git分支

markdown 将现有本地上传到远程

markdown 将远程克隆到现有本地

markdown git从本地推送到远程服务器

markdown 将远程git仓库添加到现有本地项目

markdown 从本地分支推送到另一个远程分支(如果不退出则在远程创建新分支)