Skip to content

Commit 8f72d69

Browse files
committed
[docs improve]redis部分图片重新绘制
1 parent 26e92a4 commit 8f72d69

31 files changed

+53
-56
lines changed

docs/database/redis/3-commonly-used-cache-read-and-write-strategies.md

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,105 +12,106 @@ tag:
1212

1313
但是,搞懂3种常见的缓存读写策略对于实际工作中使用缓存以及面试中被问到缓存都是非常有帮助的!
1414

15-
下面我会简单介绍一下自己对于这 3 种缓存读写策略的理解。
16-
17-
另外,**这3 种缓存读写策略各有优劣,不存在最佳,需要我们根据具体的业务场景选择更适合的。**
18-
19-
*个人能力有限。如果文章有任何需要补充/完善/修改的地方,欢迎在评论区指出,共同进步!——爱你们的 Guide 哥*
15+
**下面介绍到的三种模式各有优劣,不存在最佳模式,根据具体的业务场景选择适合自己的缓存读写模式。**
2016

2117
### Cache Aside Pattern(旁路缓存模式)
2218

2319
**Cache Aside Pattern 是我们平时使用比较多的一个缓存读写模式,比较适合读请求比较多的场景。**
2420

25-
Cache Aside Pattern 中服务端需要同时维系 DB 和 cache,并且是以 DB 的结果为准。
21+
Cache Aside Pattern 中服务端需要同时维系 db 和 cache,并且是以 db 的结果为准。
2622

2723
下面我们来看一下这个策略模式下的缓存读写步骤。
2824

2925
****
3026

31-
- 先更新 DB
27+
- 先更新 db
3228
- 然后直接删除 cache 。
3329

3430
简单画了一张图帮助大家理解写的步骤。
3531

36-
![](https://img-blog.csdnimg.cn/img_convert/5687fe759a1dac9ed9554d27e3a23b6d.png)
32+
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/database/redis/cache-aside-write.png)
3733

3834
**** :
3935

4036
- 从 cache 中读取数据,读取到就直接返回
41-
- cache中读取不到的话,就从 DB 中读取数据返回
37+
- cache 中读取不到的话,就从 db 中读取数据返回
4238
- 再把数据放到 cache 中。
4339

4440
简单画了一张图帮助大家理解读的步骤。
4541

46-
![](https://img-blog.csdnimg.cn/img_convert/a8c18b5f5b1aed03234bcbbd8c173a87.png)
47-
42+
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/database/redis/cache-aside-read.png)
4843

4944
你仅仅了解了上面这些内容的话是远远不够的,我们还要搞懂其中的原理。
5045

51-
比如说面试官很可能会追问:“**在写数据的过程中,可以先删除 cache ,后更新 DB 么?**
46+
比如说面试官很可能会追问:“**在写数据的过程中,可以先删除 cache ,后更新 db 么?**
47+
48+
**答案:** 那肯定是不行的!因为这样可能会造成 **数据库(db)和缓存(Cache)数据不一致**的问题。
49+
50+
举例:请求 1 先写数据 A,请求 2 随后读数据 A 的话,就很有可能产生数据不一致性的问题。
51+
52+
这个过程可以简单描述为:
5253

53-
**答案:** 那肯定是不行的!因为这样可能会造成**数据库(DB)和缓存(Cache)数据不一致**的问题。为什么呢?比如说请求1 先写数据A,请求2随后读数据A的话就很有可能产生数据不一致性的问题。这个过程可以简单描述为:
54+
> 请求 1 先把 cache 中的 A 数据删除 -> 请求 2 从 db 中读取数据->请求 1 再把 db 中的 A 数据更新
5455
55-
> 请求1先把cache中的A数据删除 -> 请求2从DB中读取数据->请求1再把DB中的A数据更新。
56+
当你这样回答之后,面试官可能会紧接着就追问:“**在写数据的过程中,先更新 db,后删除 cache 就没有问题了么?**
5657

57-
当你这样回答之后,面试官可能会紧接着就追问:“**在写数据的过程中,先更新DB,后删除cache就没有问题了么?**
58+
**答案:** 理论上来说还是可能会出现数据不一致性的问题,不过概率非常小,因为缓存的写入速度是比数据库的写入速度快很多。
5859

59-
**答案:** 理论上来说还是可能会出现数据不一致性的问题,不过概率非常小,因为缓存的写入速度是比数据库的写入速度快很多!
60+
举例:请求 1 先读数据 A,请求 2 随后写数据 A,并且数据 A 在请求 1 请求之前不在缓存中的话,也有可能产生数据不一致性的问题。
6061

61-
比如请求1先读数据 A,请求2随后写数据A,并且数据A不在缓存中的话也有可能产生数据不一致性的问题。这个过程可以简单描述为:
62+
这个过程可以简单描述为:
6263

63-
> 请求1从DB读数据A->请求2写更新数据 A 到数据库并把删除cache中的A数据->请求1将数据A写入cache。
64+
> 请求 1 从 db 读数据 A-> 请求 2 更新 db 中的数据 A(此时缓存中无数据 A ,故不用执行删除缓存操作 ) -> 请求 1 将数据 A 写入 cache
6465
6566
现在我们再来分析一下 **Cache Aside Pattern 的缺陷**
6667

67-
**缺陷1:首次请求数据一定不在 cache 的问题**
68+
**缺陷 1:首次请求数据一定不在 cache 的问题**
6869

69-
解决办法:可以将热点数据可以提前放入cache 中。
70+
解决办法:可以将热点数据可以提前放入 cache 中。
7071

71-
**缺陷2:写操作比较频繁的话导致cache中的数据会被频繁被删除,这样会影响缓存命中率 。**
72+
**缺陷 2:写操作比较频繁的话导致 cache 中的数据会被频繁被删除,这样会影响缓存命中率 。**
7273

7374
解决办法:
7475

75-
- 数据库和缓存数据强一致场景 :更新DB的时候同样更新cache,不过我们需要加一个锁/分布式锁来保证更新cache的时候不存在线程安全问题
76-
- 可以短暂地允许数据库和缓存数据不一致的场景 :更新DB的时候同样更新cache,但是给缓存加一个比较短的过期时间,这样的话就可以保证即使数据不一致的话影响也比较小。
76+
- 数据库和缓存数据强一致场景 :更新 db 的时候同样更新 cache,不过我们需要加一个锁/分布式锁来保证更新 cache 的时候不存在线程安全问题
77+
- 可以短暂地允许数据库和缓存数据不一致的场景 :更新 db 的时候同样更新 cache,但是给缓存加一个比较短的过期时间,这样的话就可以保证即使数据不一致的话影响也比较小。
7778

7879
### Read/Write Through Pattern(读写穿透)
7980

80-
Read/Write Through Pattern 中服务端把 cache 视为主要数据存储,从中读取数据并将数据写入其中。cache 服务负责将此数据读取和写入 DB,从而减轻了应用程序的职责。
81+
Read/Write Through Pattern 中服务端把 cache 视为主要数据存储,从中读取数据并将数据写入其中。cache 服务负责将此数据读取和写入 db,从而减轻了应用程序的职责。
8182

82-
这种缓存读写策略小伙伴们应该也发现了在平时在开发过程中非常少见。抛去性能方面的影响,大概率是因为我们经常使用的分布式缓存 Redis 并没有提供 cache 将数据写入DB的功能
83+
这种缓存读写策略小伙伴们应该也发现了在平时在开发过程中非常少见。抛去性能方面的影响,大概率是因为我们经常使用的分布式缓存 Redis 并没有提供 cache 将数据写入 db 的功能
8384

8485
**写(Write Through):**
8586

86-
- 先查 cache,cache 中不存在,直接更新 DB
87-
- cache 中存在,则先更新 cache,然后 cache 服务自己更新 DB**同步更新 cache 和 DB**)。
87+
- 先查 cache,cache 中不存在,直接更新 db
88+
- cache 中存在,则先更新 cache,然后 cache 服务自己更新 db**同步更新 cache 和 db**)。
8889

8990
简单画了一张图帮助大家理解写的步骤。
9091

91-
![](https://img-blog.csdnimg.cn/20210201100340808.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MzM3Mjcy,size_16,color_FFFFFF,t_70)
92+
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/database/redis/write-through.png)
9293

93-
**读(Read Through):**
94+
**读(Read Through):**
9495

9596
- 从 cache 中读取数据,读取到就直接返回 。
96-
- 读取不到的话,先从 DB 加载,写入到 cache 后返回响应。
97+
- 读取不到的话,先从 db 加载,写入到 cache 后返回响应。
9798

9899
简单画了一张图帮助大家理解读的步骤。
99100

100-
![](https://img-blog.csdnimg.cn/img_convert/9ada757c78614934aca11306f334638d.png)
101+
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/database/redis/read-through.png)
101102

102-
Read-Through Pattern 实际只是在 Cache-Aside Pattern 之上进行了封装。在 Cache-Aside Pattern 下,发生读请求的时候,如果 cache 中不存在对应的数据,是由客户端自己负责把数据写入 cache,而 Read-Through Pattern 则是 cache 服务自己来写入缓存的,这对客户端是透明的。
103+
Read-Through Pattern 实际只是在 Cache-Aside Pattern 之上进行了封装。在 Cache-Aside Pattern 下,发生读请求的时候,如果 cache 中不存在对应的数据,是由客户端自己负责把数据写入 cache,而 Read Through Pattern 则是 cache 服务自己来写入缓存的,这对客户端是透明的。
103104

104105
和 Cache Aside Pattern 一样, Read-Through Pattern 也有首次请求数据一定不再 cache 的问题,对于热点数据可以提前放入缓存中。
105106

106107
### Write Behind Pattern(异步缓存写入)
107108

108-
Write Behind Pattern 和 Read/Write Through Pattern 很相似,两者都是由 cache 服务来负责 cache 和 DB 的读写。
109+
Write Behind Pattern 和 Read/Write Through Pattern 很相似,两者都是由 cache 服务来负责 cache 和 db 的读写。
109110

110-
但是,两个又有很大的不同:**Read/Write Through 是同步更新 cache 和 DB,而 Write Behind Caching 则是只更新缓存,不直接更新 DB,而是改为异步批量的方式来更新 DB**
111+
但是,两个又有很大的不同:**Read/Write Through 是同步更新 cache 和 db,而 Write Behind 则是只更新缓存,不直接更新 db,而是改为异步批量的方式来更新 db**
111112

112-
很明显,这种方式对数据一致性带来了更大的挑战,比如cache数据可能还没异步更新DB的话,cache服务可能就就挂掉了
113+
很明显,这种方式对数据一致性带来了更大的挑战,比如 cache 数据可能还没异步更新 db 的话,cache 服务可能就就挂掉了
113114

114-
这种策略在我们平时开发过程中也非常非常少见,但是不代表它的应用场景少,比如消息队列中消息的异步写入磁盘、MySQL 的 InnoDB Buffer Pool 机制都用到了这种策略。
115+
这种策略在我们平时开发过程中也非常非常少见,但是不代表它的应用场景少,比如消息队列中消息的异步写入磁盘、MySQL 的 Innodb Buffer Pool 机制都用到了这种策略。
115116

116-
Write Behind Pattern 下 DB 的写性能非常高,非常适合一些数据经常变化又对数据一致性要求没那么高的场景,比如浏览量、点赞量。
117+
Write Behind Pattern 下 db 的写性能非常高,非常适合一些数据经常变化又对数据一致性要求没那么高的场景,比如浏览量、点赞量。
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<mxfile host="Electron" modified="2021-12-30T08:24:33.950Z" agent="5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.4.5 Chrome/83.0.4103.122 Electron/9.1.0 Safari/537.36" etag="Lm2Jg2WpdHU34XBpseqz" version="13.4.5" type="device"><diagram id="q0Jyj2iPy4cPDLKcUkni" name="Page-1">7VdNc9owEP01OtLBNhj5aBOSTmbaaSeHpL10hC1sTWSLCvHVX9+VvQb8QZs0bWlmOhyQ3sq7631vF0G8ab670WyZvVMJl8QdJjviXRHXdZyhD18W2VdIEEwqINUiwUNH4E584wgOEV2LhK8aB41S0ohlE4xVUfDYNDCmtdo2jy2UbEZdspR3gLuYyS56LxKTVSh1J0f8LRdpVkd2/KCy5Kw+jG+yyliitieQNyPeVCtlqlW+m3Jpi1fXpXru+oz1kJjmhXnKA/l7Z//5y+2nj/cmH6zmi83jgz9ALxsm1/jCxPUl+ItWS1bYrM0eS+F/XdtUo4UqzGBVEhXCAYcugezoaIdVar8pmY1JeEWA8BklNCT04BuSrNxXJ7E+h0iuVusi4TZvB8zbTBh+t2SxtW5BZoBlJpdotvmgbhxq90LKqZJKl768hHG6iO0LGa0e+YnFjymfL6ylZmZoN4/cxBn6TiVbrdCAleLa8N1ZCpwDsdARXOXc6D0cwQfcCWoBm8H1cL89Ssup9ZKdyMpHjKGa04PrI+GwQM6fwb/7e/i/HPmviOzg0mR7/8n+W2R740uTPXrlZF+MupFzaeomPdS1SsmLJLS3G9jFthwi/vGPIt8J84A2u/5k6/dmjLurHZaz3Oz7il5lwJPObalVZshSrXXMf6bMLh0n5R73VLvGNJfMiE0zjT4KMMIHJSDBA9ujYYvtNotV+vjU6XWq7Yi2HI1ajgzTKTcdR6UiDq/96yKhXZFAY1Kf0HHdodCqExK6hM7sggaETjpCgr4xrcZrTNNCFbw1ehFiUqSF1R8IgAMe2S4UcHMO0ZCLJLFheju9OQvacm00f93vTr8mX9T8HRafeiNz/1TzB/28AqNTMhuRaFpOXkCuSQSL6xIJb9mG3di/SvUsnusnjXj/zOW9DAUSmpZDfliKCkNVYSCDwCPh+B8UlNWMZHMuIxY/piXeDn4iNx/3J9eHqPyUPg3MGmVjD7wzI/FF8vOC1rWh77eH9sjPeb78YHv8s1lNoeNfdm/2HQ==</diagram></mxfile>
-6.37 KB
Binary file not shown.

docs/database/redis/images/redis-all/redis-list.drawio

Lines changed: 0 additions & 1 deletion
This file was deleted.
-5.45 KB
Binary file not shown.
-86.2 KB
Binary file not shown.
-42.7 KB
Binary file not shown.
-117 KB
Binary file not shown.
-21.2 KB
Binary file not shown.
-108 KB
Binary file not shown.

0 commit comments

Comments
 (0)