读写一致 && MySQL&&Redis

存储一致性&& CPU存储 && L1L2Cache等等 

不懂CPU如何读写内存还敢说自己是程序员? - 知乎 (zhihu.com)

 

 基础知识:

1. 什么是cache line :

cache line 位于 CPU 与内存之间,CPU想要获得数据的时候,先从CPU cache中获取。

若CPU cache中不存在,发生cache miss,那么,cache要从主存memory 中获取数据缓存到cache中并且返回给CPU。

由于局部性原理,CPU Cache每次不会只将需要的字节读取进来,而是会读走需要字节和该字节旁边的部分字节,这一组读取的大小就是 cache line 的大小=64Byte 

因此,可以说,CPU Cache 从 Memory 中取数据的最小单位就是64Byte,

                      而 Memory 从 磁盘中读取数据的最小单位是 4092Byte

2. CPU cache 分级 :L1 L2 L3 cache

L1 cache、L2 cache是每个CPU核独享,L3 cache是多个CPU核共享

L1 cache 分为 数据缓存 和 指令缓存

L2、L3 级别的cache 不区分 数据缓存或指令缓存

还有一种缓存是TLB,这个是专门用来存放页表,用于虚拟地址和真实地址映射的

3. CPU cache的性能优化:

当出现多核多线程对数据进行处理时,容易出现位于同一个cache line 上的2个不同变量 x 和 y被两个线程 A 和 B 所修改,而这个同时包含x 和 y 的 cache line 会被两个CPU核的cache 缓存,由于x 和 y被一个线程修改而导致 另一个线程上的 该行 cache line 失效,两个线程虽然在代码逻辑上修改的是不同的变量但是却会有着 一方修改x另一方的CPU cache中 y也失效,需要重新更新的情况。这种频繁更新的情况 called “伪共享”,若操作频繁会很消耗性能。

==》为了解决这个问题:使用填充技术,实现 cacheline 对齐

将例如先定义x变量占4Byte,那么填充60Byte无关字节,然后再定义y变量,这样x和y就不会存放在同一cacheline 中被获得。以此来避免伪共享。

数据一致性的含义:

它目的不是说==》两个线程并发读写,然后某个线程获得的数据是旧数据

而目的是==》过了一小段时间,缓存数据和数据库中的数据是不是一致的。或者说主从数据库中的数据是不是一致的。

==》为啥会不一致,我觉得主要原因就是过期策略导致的。若热点数据长时间不过期,里面一直放着旧数据,这不出问题了么

1. 缓存雪崩:缓存雪崩的关键在于在同一时间大规模的key失效。

出现原因:①Redis宕机 ② Redis中的大量数据采用同一过期时间

解决措施:①熔断机制,当请求流量达到阈值,就提示一会再进入,保证一部分用户可用,另一部分多刷新几次也能用

                  ②提高数据库容灾能力,读写分离,分库分表,提高数据库可靠性可用性

                  ③将Redis变成集群

2. 缓存击穿:热点数据过期,大量请求直接访问数据库

解决措施:①业务允许热点数据不设置过期时间

                  ②当热点数据过期时,使用互斥锁,降低同一时间访问数据库的请求数量

3. 缓存穿透:恶意攻击,访问不存在于数据库中的请求,那Redis中没缓存。自然要访问MySQL

解决措施:布隆过滤器

常见的缓存读写策略:旁路缓存、读写穿透、异步缓存

(一)旁路缓存:适合读请求多的情况

读:

数据先从cache里面读,如果有,读走;

如果没有,从MySQL中获取,写入Redis再返回。

写:

先更新DB,然后删除Redis中的缓存

(二)读写穿透:==》把Redis视作主要的数据存储空间,读和写都在对Redis

读:数据先从cache里面读,有就直接读走

如果没有,从MySQL中读取,写入缓存,然后再返回。

==》和旁路缓存的区别在于:旁路缓存是全由用户去做的,数据不存在就自己写代码从MySQL中读,load到Redis中;但是读写穿透则是:用户就直接和缓存交互,缓存和数据库的交互有缓存自己处理,不用用户操心。

写:

先查看该更新写数据在Cache中是否存在,若不存在直接写入数据库

若存在,那么,先更新Cache,而后Cache自己

(三)

延时双删:==》解决Redis和MySQL数据一致性

删除两次:写库前后都进行 Redis 的删除操作

实现逻辑:

在修改MySQL前删一次cache;

修改MySQL(数据库数据);

延迟等待一小段时间(避免此时的读操作 正在把 之前读到的旧数据写回到Cache的路上,等这个读操作把旧数据写回到cache,然后在删除,这样就避免了,我这边刚删完,写操作就带着旧数据写回到Cache中了,这不白删除了嘛);

再次删除cache中的数据

再读一读这些在总结整理:

ref:Redis和Mysql如何保证数据一致?面试可以这样说自己的看法 - 知乎 (zhihu.com)

缓存与数据库一致性问题深度剖析 (修订) (qq.com)

3种缓存读写策略都不了解?面试很难让你通过啊兄弟! (qq.com)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值