[docs improve]redis部分图片重新绘制
@ -12,55 +12,56 @@ tag:
|
|||||||
|
|
||||||
但是,搞懂3种常见的缓存读写策略对于实际工作中使用缓存以及面试中被问到缓存都是非常有帮助的!
|
但是,搞懂3种常见的缓存读写策略对于实际工作中使用缓存以及面试中被问到缓存都是非常有帮助的!
|
||||||
|
|
||||||
下面我会简单介绍一下自己对于这 3 种缓存读写策略的理解。
|
**下面介绍到的三种模式各有优劣,不存在最佳模式,根据具体的业务场景选择适合自己的缓存读写模式。**
|
||||||
|
|
||||||
另外,**这3 种缓存读写策略各有优劣,不存在最佳,需要我们根据具体的业务场景选择更适合的。**
|
|
||||||
|
|
||||||
*个人能力有限。如果文章有任何需要补充/完善/修改的地方,欢迎在评论区指出,共同进步!——爱你们的 Guide 哥*
|
|
||||||
|
|
||||||
### Cache Aside Pattern(旁路缓存模式)
|
### Cache Aside Pattern(旁路缓存模式)
|
||||||
|
|
||||||
**Cache Aside Pattern 是我们平时使用比较多的一个缓存读写模式,比较适合读请求比较多的场景。**
|
**Cache Aside Pattern 是我们平时使用比较多的一个缓存读写模式,比较适合读请求比较多的场景。**
|
||||||
|
|
||||||
Cache Aside Pattern 中服务端需要同时维系 DB 和 cache,并且是以 DB 的结果为准。
|
Cache Aside Pattern 中服务端需要同时维系 db 和 cache,并且是以 db 的结果为准。
|
||||||
|
|
||||||
下面我们来看一下这个策略模式下的缓存读写步骤。
|
下面我们来看一下这个策略模式下的缓存读写步骤。
|
||||||
|
|
||||||
**写** :
|
**写** :
|
||||||
|
|
||||||
- 先更新 DB
|
- 先更新 db
|
||||||
- 然后直接删除 cache 。
|
- 然后直接删除 cache 。
|
||||||
|
|
||||||
简单画了一张图帮助大家理解写的步骤。
|
简单画了一张图帮助大家理解写的步骤。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**读** :
|
**读** :
|
||||||
|
|
||||||
- 从 cache 中读取数据,读取到就直接返回
|
- 从 cache 中读取数据,读取到就直接返回
|
||||||
- cache中读取不到的话,就从 DB 中读取数据返回
|
- cache 中读取不到的话,就从 db 中读取数据返回
|
||||||
- 再把数据放到 cache 中。
|
- 再把数据放到 cache 中。
|
||||||
|
|
||||||
简单画了一张图帮助大家理解读的步骤。
|
简单画了一张图帮助大家理解读的步骤。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
你仅仅了解了上面这些内容的话是远远不够的,我们还要搞懂其中的原理。
|
你仅仅了解了上面这些内容的话是远远不够的,我们还要搞懂其中的原理。
|
||||||
|
|
||||||
比如说面试官很可能会追问:“**在写数据的过程中,可以先删除 cache ,后更新 DB 么?**”
|
比如说面试官很可能会追问:“**在写数据的过程中,可以先删除 cache ,后更新 db 么?**”
|
||||||
|
|
||||||
**答案:** 那肯定是不行的!因为这样可能会造成**数据库(DB)和缓存(Cache)数据不一致**的问题。为什么呢?比如说请求1 先写数据A,请求2随后读数据A的话就很有可能产生数据不一致性的问题。这个过程可以简单描述为:
|
**答案:** 那肯定是不行的!因为这样可能会造成 **数据库(db)和缓存(Cache)数据不一致**的问题。
|
||||||
|
|
||||||
> 请求1先把cache中的A数据删除 -> 请求2从DB中读取数据->请求1再把DB中的A数据更新。
|
举例:请求 1 先写数据 A,请求 2 随后读数据 A 的话,就很有可能产生数据不一致性的问题。
|
||||||
|
|
||||||
当你这样回答之后,面试官可能会紧接着就追问:“**在写数据的过程中,先更新DB,后删除cache就没有问题了么?**”
|
这个过程可以简单描述为:
|
||||||
|
|
||||||
**答案:** 理论上来说还是可能会出现数据不一致性的问题,不过概率非常小,因为缓存的写入速度是比数据库的写入速度快很多!
|
> 请求 1 先把 cache 中的 A 数据删除 -> 请求 2 从 db 中读取数据->请求 1 再把 db 中的 A 数据更新
|
||||||
|
|
||||||
比如请求1先读数据 A,请求2随后写数据A,并且数据A不在缓存中的话也有可能产生数据不一致性的问题。这个过程可以简单描述为:
|
当你这样回答之后,面试官可能会紧接着就追问:“**在写数据的过程中,先更新 db,后删除 cache 就没有问题了么?**”
|
||||||
|
|
||||||
> 请求1从DB读数据A->请求2写更新数据 A 到数据库并把删除cache中的A数据->请求1将数据A写入cache。
|
**答案:** 理论上来说还是可能会出现数据不一致性的问题,不过概率非常小,因为缓存的写入速度是比数据库的写入速度快很多。
|
||||||
|
|
||||||
|
举例:请求 1 先读数据 A,请求 2 随后写数据 A,并且数据 A 在请求 1 请求之前不在缓存中的话,也有可能产生数据不一致性的问题。
|
||||||
|
|
||||||
|
这个过程可以简单描述为:
|
||||||
|
|
||||||
|
> 请求 1 从 db 读数据 A-> 请求 2 更新 db 中的数据 A(此时缓存中无数据 A ,故不用执行删除缓存操作 ) -> 请求 1 将数据 A 写入 cache
|
||||||
|
|
||||||
现在我们再来分析一下 **Cache Aside Pattern 的缺陷**。
|
现在我们再来分析一下 **Cache Aside Pattern 的缺陷**。
|
||||||
|
|
||||||
@ -72,45 +73,45 @@ Cache Aside Pattern 中服务端需要同时维系 DB 和 cache,并且是以 D
|
|||||||
|
|
||||||
解决办法:
|
解决办法:
|
||||||
|
|
||||||
- 数据库和缓存数据强一致场景 :更新DB的时候同样更新cache,不过我们需要加一个锁/分布式锁来保证更新cache的时候不存在线程安全问题。
|
- 数据库和缓存数据强一致场景 :更新 db 的时候同样更新 cache,不过我们需要加一个锁/分布式锁来保证更新 cache 的时候不存在线程安全问题。
|
||||||
- 可以短暂地允许数据库和缓存数据不一致的场景 :更新DB的时候同样更新cache,但是给缓存加一个比较短的过期时间,这样的话就可以保证即使数据不一致的话影响也比较小。
|
- 可以短暂地允许数据库和缓存数据不一致的场景 :更新 db 的时候同样更新 cache,但是给缓存加一个比较短的过期时间,这样的话就可以保证即使数据不一致的话影响也比较小。
|
||||||
|
|
||||||
### Read/Write Through Pattern(读写穿透)
|
### Read/Write Through Pattern(读写穿透)
|
||||||
|
|
||||||
Read/Write Through Pattern 中服务端把 cache 视为主要数据存储,从中读取数据并将数据写入其中。cache 服务负责将此数据读取和写入 DB,从而减轻了应用程序的职责。
|
Read/Write Through Pattern 中服务端把 cache 视为主要数据存储,从中读取数据并将数据写入其中。cache 服务负责将此数据读取和写入 db,从而减轻了应用程序的职责。
|
||||||
|
|
||||||
这种缓存读写策略小伙伴们应该也发现了在平时在开发过程中非常少见。抛去性能方面的影响,大概率是因为我们经常使用的分布式缓存 Redis 并没有提供 cache 将数据写入DB的功能。
|
这种缓存读写策略小伙伴们应该也发现了在平时在开发过程中非常少见。抛去性能方面的影响,大概率是因为我们经常使用的分布式缓存 Redis 并没有提供 cache 将数据写入 db 的功能。
|
||||||
|
|
||||||
**写(Write Through):**
|
**写(Write Through):**
|
||||||
|
|
||||||
- 先查 cache,cache 中不存在,直接更新 DB。
|
- 先查 cache,cache 中不存在,直接更新 db。
|
||||||
- cache 中存在,则先更新 cache,然后 cache 服务自己更新 DB(**同步更新 cache 和 DB**)。
|
- cache 中存在,则先更新 cache,然后 cache 服务自己更新 db(**同步更新 cache 和 db**)。
|
||||||
|
|
||||||
简单画了一张图帮助大家理解写的步骤。
|
简单画了一张图帮助大家理解写的步骤。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**读(Read Through):**
|
**读(Read Through):**
|
||||||
|
|
||||||
- 从 cache 中读取数据,读取到就直接返回 。
|
- 从 cache 中读取数据,读取到就直接返回 。
|
||||||
- 读取不到的话,先从 DB 加载,写入到 cache 后返回响应。
|
- 读取不到的话,先从 db 加载,写入到 cache 后返回响应。
|
||||||
|
|
||||||
简单画了一张图帮助大家理解读的步骤。
|
简单画了一张图帮助大家理解读的步骤。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Read-Through Pattern 实际只是在 Cache-Aside Pattern 之上进行了封装。在 Cache-Aside Pattern 下,发生读请求的时候,如果 cache 中不存在对应的数据,是由客户端自己负责把数据写入 cache,而 Read-Through Pattern 则是 cache 服务自己来写入缓存的,这对客户端是透明的。
|
Read-Through Pattern 实际只是在 Cache-Aside Pattern 之上进行了封装。在 Cache-Aside Pattern 下,发生读请求的时候,如果 cache 中不存在对应的数据,是由客户端自己负责把数据写入 cache,而 Read Through Pattern 则是 cache 服务自己来写入缓存的,这对客户端是透明的。
|
||||||
|
|
||||||
和 Cache Aside Pattern 一样, Read-Through Pattern 也有首次请求数据一定不再 cache 的问题,对于热点数据可以提前放入缓存中。
|
和 Cache Aside Pattern 一样, Read-Through Pattern 也有首次请求数据一定不再 cache 的问题,对于热点数据可以提前放入缓存中。
|
||||||
|
|
||||||
### Write Behind Pattern(异步缓存写入)
|
### Write Behind Pattern(异步缓存写入)
|
||||||
|
|
||||||
Write Behind Pattern 和 Read/Write Through Pattern 很相似,两者都是由 cache 服务来负责 cache 和 DB 的读写。
|
Write Behind Pattern 和 Read/Write Through Pattern 很相似,两者都是由 cache 服务来负责 cache 和 db 的读写。
|
||||||
|
|
||||||
但是,两个又有很大的不同:**Read/Write Through 是同步更新 cache 和 DB,而 Write Behind Caching 则是只更新缓存,不直接更新 DB,而是改为异步批量的方式来更新 DB。**
|
但是,两个又有很大的不同:**Read/Write Through 是同步更新 cache 和 db,而 Write Behind 则是只更新缓存,不直接更新 db,而是改为异步批量的方式来更新 db。**
|
||||||
|
|
||||||
很明显,这种方式对数据一致性带来了更大的挑战,比如cache数据可能还没异步更新DB的话,cache服务可能就就挂掉了。
|
很明显,这种方式对数据一致性带来了更大的挑战,比如 cache 数据可能还没异步更新 db 的话,cache 服务可能就就挂掉了。
|
||||||
|
|
||||||
这种策略在我们平时开发过程中也非常非常少见,但是不代表它的应用场景少,比如消息队列中消息的异步写入磁盘、MySQL 的 InnoDB Buffer Pool 机制都用到了这种策略。
|
这种策略在我们平时开发过程中也非常非常少见,但是不代表它的应用场景少,比如消息队列中消息的异步写入磁盘、MySQL 的 Innodb Buffer Pool 机制都用到了这种策略。
|
||||||
|
|
||||||
Write Behind Pattern 下 DB 的写性能非常高,非常适合一些数据经常变化又对数据一致性要求没那么高的场景,比如浏览量、点赞量。
|
Write Behind Pattern 下 db 的写性能非常高,非常适合一些数据经常变化又对数据一致性要求没那么高的场景,比如浏览量、点赞量。
|
||||||
|
1
docs/database/redis/images/memory-fragmentation.drawio
Normal file
@ -0,0 +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>
|
Before Width: | Height: | Size: 6.4 KiB |
@ -1 +0,0 @@
|
|||||||
<mxfile host="Electron" modified="2020-07-27T06:27:52.340Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.4.5 Chrome/83.0.4103.122 Electron/9.1.0 Safari/537.36" etag="dsqbsLB26jrO3YkREjOb" version="13.4.5" type="device"><diagram id="tTBfL0GptSJyUtbD2ZoE" name="Page-1">7VlNc5swFPw1PiaDENjmmNjpx6Gdjt1J2lNHAzKoEYgRcmzn11cYyRgJT1w3DnScU3grIaHd5b2HM4CTdP2Rozz5wiJMB64TrQdwOnBdEEAo/5TIpkICx6mAmJNITaqBOXnGCtTTliTCRWOiYIwKkjfBkGUZDkUDQ5yzVXPagtHmrjmKsQXMQ0Rt9IFEIqnQsTuq8U+YxIneGQyDaiRFerI6SZGgiK32IHg3gBPOmKiu0vUE05I8zUt134cDo7sH4zgTx9wwu/+V/H4g/myezsD35/vZ56/ulVrlCdGlOrB6WLHRDHC2zCJcLgIG8HaVEIHnOQrL0ZXUXGKJSKkaLh6xCBMVLFgmlKJgJGO1F+YCrw8eAuyokZ7CLMWCb+QUdcOVp9hUdnKhile1OL62WLInzEhhSPkh3i1dUyYvFGt/waBrMbi9BD3lUfPm2bwFLbT556INttPWc/sB035d0+i10wj7TaM77hmNw5fTIM6im7KeyCikqChI2ORMHp1vfsjA0cHPMrh2fR1P1/uj042KjiAbR1aRMqiWVRHxGIuXUr0tSSNxHqacY4oEeWo+RpsOaodvjMgHrPM2gKbk4+YaBVvyEKvb9suYuZLpHdcwRUWEtdDWF7tzn26V0f9ula4s4A0N4cbOtX+aB3zfWupNPaCb01cxAXjPF0cofGq68AJjIT8wXXdusxzRY/fbLJ0VDbPbOj1j2PXnrVOG/Z3A82WRWFaQXZUwujHB2SOeMMq4RDKW4VJLQqkBIUrirHSQVA9L/Lbs0Yj8lL1RAymJonKb1vavbhCP9M0/dYA+OFDF95zltTjLLPav1gECu5PmOcvf5aloD7qWx7fkoRf8+siiYggEuhbI/oSil/v+2Pp0/gLZ3y18u20/BTqDJp5O8VoSp2tJxvYrgxcXpIjV351PERnWv7RXPV39/wp49wc=</diagram></mxfile>
|
|
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 118 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 3.8 KiB |
1
docs/database/redis/images/redis-event-handler.drawio
Normal file
@ -0,0 +1 @@
|
|||||||
|
<mxfile host="Electron" modified="2022-08-21T12:40:37.540Z" 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="lr4caBKy7jjWoYtJBxep" version="13.4.5" type="device"><diagram id="9BE8MdjfxC0TaVaDFPY0" name="Page-1">7Vrbcuo2FP0aPSbjq2w9YnDSezPNQ9unjmILcGIsakSAfn0lWcYXiQROIJwMzJk5sbZu9l57SUsbAXc4W9+XeD79laYkB46VroE7Ao5j2xbkf4RlU1kQCirDpMxS1agxPGb/EWW0lHWZpWTRacgozVk27xoTWhQkYR0bLku66jYb07w76xxPiGZ4THCuW//MUjatvwuipuIHkk2m9dTQ96qaGa5bq09ZTHFKVy2TGwN3WFLKqqfZekhy4b3aMVW/ux212zcrScH26UAWz8U/Nw9/4FFK2f08uik3P9+oUV5xvlRfrF6WbWoXlHRZpEQMYgM3Wk0zRh7nOBG1Kw46t03ZLFfVKV5Mt23V2KRkZL3zpe2tK3gQETojrNzwJnWHUHlPxY/tqfKqhUbt4WkLCM9SRqwiYLIdu/ERf1BuOsBlju6y2AcDH/DQjiEIY/EsLCNQB3vLm9wVrOuyBSvpCxnSnJbcUtCCt4zGWZ73TDjPJgUvJtx1hNsj4diMh+pAVcyyNBXTGDFqULT6MI1pwRTzHOs4sDlWDzaowxYaUHNOBpqlIUFSznRVpCWb0gktcB431p7Pmja/UDpXvnsmjG2U8/CS0S603Fvl5i/VXxb+FoVbvy6O1u3K0UaVWojYcIuIeOG38eDfR5dlQt5whKsWUVxOCHujXWDGtyQ5Ztlr9z2OjparUWxBkxfCbB3EPOdbwa6gb0HRd2mbYMBxU0zCcaKxkdfAJCRP4yOtZsjv0GJLkzYtfJ0WwcloYfDoRdLC+wq08HbQQt+zvzYt3LPTwuDR09PihOHtfzBsVdcHmvGZt7h5vV3edXuAVHRSvRpMBmWJN61mc9FgsXse1+vO4wV+e7h329fv1YRE9QZNgGx98u0x4+8g529fnJx9KecZFPinkhNqjtY9XKQDcfhrxHNH8PbOKw+YcUFdSItjuVuH1gc+Z6dGfp+bultbbvMNCri2fZCajotuu4uq1ydntWho5NxjKDfcj+fHopbjXlVKoz72UCnhOVVKoPHzRz7O79wkT8UeQAMQhyAKwOBOWcIRiAOAPDAIxQP/P4xEVTQA4Z2G/UEJiT5xe2voeExgYlxD0wA9WUc6DmsbpUHg2KbzMDzVIhrqi2gMAYIgDEDsgSgCEZSWQD4g+eAJTEIOjqzixSgWFoQEYqdFaezsQAk+QR8eByWIvjeU0Ptb3Vmzcwj20jyOwWPQ4DHvZOqgThx3ItuTK0nUiuxq2fHksmPJgN4Vx5eRsENhd4s3Jexs24DkyTJ2tn7aveo8TZzZlqbO/L4621fomcba80R3LKVn66coyUwbRCPFXs5brh64dIhkuj2yQegcwudv3ZdMJzBipz4JTPsSgoGLj7QvoaCfNfR1brqfuS/ZhjOYASZuiQCKWyLvomBChiX0c2HSpbhU3ncSlNZPVXx3RBIU8ZuVd1kwucHZYTKJcU6iUPCoYhNHygjc5cDk+eeGyfF0/XGRWQgVXu9mIeyPZp0/Bpd/heswuOBZ4YJXuA6D66w/RTr6zZYrXG/CddacrGOQGA7MmfJNB0j475LWFTcL6bUBb2DD+bqp5E8T+VdkBLkOGUqhMpR3oHyRtBWnsztpGfyEX/G9uMdXT/lUNt0DcWTgBwchPiOhXupez7yXvP13mxR1R/7t1euq3t9nribHTySPcPIykfb+5K1YDFW5paEi+U+OyXhg0EINunghLJnWhfoq4ZGyP9tjfn10Md2yM2U+7cPFFi82dx6rvEFzddSN/wc=</diagram></mxfile>
|
1
docs/database/redis/images/redis-list.drawio
Normal file
@ -0,0 +1 @@
|
|||||||
|
<mxfile host="Electron" modified="2022-08-21T12:47:30.896Z" 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="ZRkvMtSIqMZPTfHNopgk" version="13.4.5" type="device"><diagram id="tTBfL0GptSJyUtbD2ZoE" name="Page-1">7VlNc9owFPw1HJPBlg32MYE07aGdDnSS5tRR7YetRrY8sgiQX18Zy9iWYEIpXy05Ya3kJ2l3rfc0dNAgmd9znMWfWQi0Y3fDeQcNO7Zt+QjJnwJZlIjv90sg4iRUg2pgTF5BgV2FTkkIeWugYIwKkrXBgKUpBKKFYc7ZrD1swmh71gxHYADjAFMTfSShiEvUs/s1/hFIFFczWz2/7ElwNVjtJI9xyGYNCN110IAzJsqnZD4AWpBX8VK+92FD72phHFKxzQujhx/xr0fijsbJyPr2+jD69MW+UlFeMJ2qDavFikXFAGfTNIQiiNVBt7OYCBhnOCh6Z1JzicUioao7fwYRFPvuysaEpUIpavVl21xxNT1wAfMGpHZwDywBwRdyiOq9chSbyk42Uu1ZLY7bVVjcEKavMKz8EK1C15TJB8XaHzBoGwwuH60D8jghlA4YZXwZGIUYvElQvCQ4e4ZGTy/w4OfkL5mvmHZMpv01RLuHIhqtJ/qQhj0u0VWvbvFTE++sJx79b8Tb3pkR33v7cIY0vCmynGwFFOc5CdosSzb44rtiedl4KhrXtlu1h/Nm73ChWrsd5ALzCMTb+QbCVtY1JWkd55sp50CxIC/tXL1OBzXDV0bkiutsYiFdcq8dI2dTHoB6rZlc9Ui6d2zNFCUzRqClL1b73t0q/X/OKmdiAaenCed1r93dPOC6RqijeqAqmfdiAuv9vNhC4V2PC8fXArm+7rpDm2WLyv/MzHImJjCuILufGGb+OfaRYd5eeDbNY8MKsoQSWv3WKsVSloJWtykIUxKlhYOknCDx26IgI/KCfaM6EhKGxTRrC8a6pNzdN9tXgK61IYs3nOWscZae7PdWAVpm7c0zlr3LU9Lun1oe15CHXvDnI5OKJpB1aoHMKxS93O/H1OfkH5B5b+HLac9TIF2TlmB7EMipzvtKn+6p9fHM7wcmlyqPUfkdTh7ZrP8ZKKu9+v8VdPcb</diagram></mxfile>
|
@ -1 +0,0 @@
|
|||||||
<mxfile host="Electron" modified="2020-12-19T10:09:54.115Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/13.4.5 Chrome/83.0.4103.122 Electron/9.1.0 Safari/537.36" etag="ouO_wanaVWn605JgN_9b" version="13.4.5" type="device"><diagram id="3s-LqK6m4lkifnhmqHE2" name="Page-1">7Vpbc+o2EP41ekzHl/j2iAmk02nmdA6dpn3qCFsYTWSLY0Qg/fWVbMnYluE4B4jTQh4Se6WVVt+32pU2BvY43T3mcLV8ojEiwDLiHbAfgGWZluPzP0LyVkoCwygFSY5j2WkvmOF/kBSqbhsco3WjI6OUMLxqCiOaZShiDRnMc7ptdltQ0px1BROkCWYRJLr0GcdsWUp9y9vLf0Y4WaqZTTcoW1KoOsuVrJcwptuayJ4Ae5xTysqndDdGRICncCn1pgdaK8NylLE+Ck/Pf/xthHPraf7NePliLeLZ1+c7OcorJBu5YGkse1MI5HSTxUgMYgI73C4xQ7MVjETrlnPOZUuWEtm8wISMKaF5oWsvFgsrirh8zXL6gmotsTt3HVe0KFiEekRTzLs/GPw5IXC9ls/SSpQztDu4fLMClXsjoili+RvvIhVs5VHSEX3fKd+3e1pNxdWyRqkrZVB6UlINvQebP0i834G9db3YW0Njb2vYx5BBDX++ZNYEuQlmRjN0BHlIcJJxWcRxQrwxFChiHlxGsiHFcSzm6qR2T75RTaxiUME3zZgMmFbQIq1O5jkIvG8RqN5rBLod/NmX4u9e4y8TVN3468dflYWH4s+5mtjnGJ8t77jXi/3gece75Z13EWi3845OYFfcUjyfnT//lndO4W/wvBNcTexzg8+Wd9Ql4BrBHzzxmPpN/5Z5jjDoWZ/sxmPq5YJb6nkHgYOnHlOvOfxfw5/vf7rcoxcMrgb84XOPftu/5Z4jDAbtcunguUcvGdxyzzsIHD736HUHjTyUxSPxDzNBgIBGANKIeC38mgjbXIJ2mP0pe4vnvwSiPzny7WEnAS5e3hpoo1j7L1wLa24q3eQROrbIbk5qmDsdmCtZjghk+LVpRhcRcobfKOYGHiw1BSrjqCFK86XWns4eA7VqGQzmCWLaQIVfVMs+wVX0Esd/zFWGcgG/vevbzPV1gXYG/3AX6FElublAF3Nu+9Lxo1GgXUDQBrqwC6h1NFzAJUV2t/bK7reN+HwhBJN7EPrAD8DEAf4U+GPxwNcQmGASgMAG4QRMfDAywcivqdVdSgmF59ytC9cZ8Q62vdrVNdyknJDP8wACp3N4UnadClNlfymM8esJk8pB5vnpY3DrCluU9PSTlBSd9RBVv7IcOi/Vdrptn+f8ZPt+w/s9Vz8/OeZHHqAsvXz2PZcSFN5JNoQ/ELRgh/1hvYJZH68yne7twPcf3w5jsQt49uD37ckUhGMQjGYZxGRMcDrnnWEqSM7m61XTFcvZj3toKRXmnGDnBTCrBQQHjMYFFHzhngxFoVetu/z9iNlyM6/w+QW+wkfxkdkPwcGlJSK99/HF92e9vNDOxEKJ8hExEzsrEK8EzhEJYfSSFGO3AwxXrl3VjOKn0qJ5jPIOjSlMMREzPMIcpjSLlRkSGENS/aUyxTNKPiOcJb/TlTwiSMGvwgsakpAyRtOm7KsMA2eKQZ6qWakM7OhlFKsrBt1fLAbpFeDbsazXscw0vnep6nsuMw1v2LO5pVeRs41Q+9jAM2R1RefgcuUV/rr/QrfkcP+dsz35Fw==</diagram></mxfile>
|
|
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 11 KiB |
@ -172,7 +172,7 @@ Redis 中的 List 其实就是链表数据结构的实现。我在 [线性数据
|
|||||||
|
|
||||||
我专门画了一个图方便大家理解 `RPUSH` , `LPOP` , `lpush` , `RPOP` 命令:
|
我专门画了一个图方便大家理解 `RPUSH` , `LPOP` , `lpush` , `RPOP` 命令:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**通过 `LRANGE` 查看对应下标范围的列表元素** :
|
**通过 `LRANGE` 查看对应下标范围的列表元素** :
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ Redis 提供了多种数据类型来支持不同的业务场景。Redis 还支
|
|||||||
|
|
||||||
你可以自己本机安装 Redis 或者通过 Redis 官网提供的[在线 Redis 环境](https://try.redis.io/)来实际体验 Redis。
|
你可以自己本机安装 Redis 或者通过 Redis 官网提供的[在线 Redis 环境](https://try.redis.io/)来实际体验 Redis。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### 分布式缓存常见的技术选型方案有哪些?
|
### 分布式缓存常见的技术选型方案有哪些?
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ Memcached 是分布式缓存最开始兴起的那会,比较常用的。后来
|
|||||||
|
|
||||||
作为暖男一号,我给大家画了一个草图。
|
作为暖男一号,我给大家画了一个草图。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
简单来说就是:
|
简单来说就是:
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ _简单,来说使用缓存主要是为了提升用户体验以及应对更多
|
|||||||
|
|
||||||
下面我们主要从“高性能”和“高并发”这两点来看待这个问题。
|
下面我们主要从“高性能”和“高并发”这两点来看待这个问题。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**高性能** :
|
**高性能** :
|
||||||
|
|
||||||
@ -247,15 +247,13 @@ Redis 通过**IO 多路复用程序** 来监听来自客户端的大量连接(
|
|||||||
- 文件事件分派器(将 socket 关联到相应的事件处理器)
|
- 文件事件分派器(将 socket 关联到相应的事件处理器)
|
||||||
- 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
|
- 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
<p style="text-align:right; font-size:14px; color:gray">《Redis设计与实现:12章》</p>
|
|
||||||
|
|
||||||
### Redis6.0 之前为什么不使用多线程?
|
### Redis6.0 之前为什么不使用多线程?
|
||||||
|
|
||||||
虽然说 Redis 是单线程模型,但是,实际上,**Redis 在 4.0 之后的版本中就已经加入了对多线程的支持。**
|
虽然说 Redis 是单线程模型,但是,实际上,**Redis 在 4.0 之后的版本中就已经加入了对多线程的支持。**
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
不过,Redis 4.0 增加的多线程主要是针对一些大键值对的删除操作的命令,使用这些命令就会使用主处理之外的其他线程来“异步处理”。
|
不过,Redis 4.0 增加的多线程主要是针对一些大键值对的删除操作的命令,使用这些命令就会使用主处理之外的其他线程来“异步处理”。
|
||||||
|
|
||||||
@ -323,7 +321,7 @@ OK
|
|||||||
|
|
||||||
Redis 通过一个叫做过期字典(可以看作是 hash 表)来保存数据过期的时间。过期字典的键指向 Redis 数据库中的某个 key(键),过期字典的值是一个 long long 类型的整数,这个整数保存了 key 所指向的数据库键的过期时间(毫秒精度的 UNIX 时间戳)。
|
Redis 通过一个叫做过期字典(可以看作是 hash 表)来保存数据过期的时间。过期字典的键指向 Redis 数据库中的某个 key(键),过期字典的值是一个 long long 类型的整数,这个整数保存了 key 所指向的数据库键的过期时间(毫秒精度的 UNIX 时间戳)。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
过期字典是存储在 redisDb 这个结构里的:
|
过期字典是存储在 redisDb 这个结构里的:
|
||||||
|
|
||||||
@ -435,7 +433,7 @@ Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,可以通
|
|||||||
|
|
||||||
官方文档地址:https://redis.io/topics/persistence
|
官方文档地址:https://redis.io/topics/persistence
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 参考
|
## 参考
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ ERR EXEC without MULTI
|
|||||||
|
|
||||||
Redis 官网相关介绍 [https://redis.io/topics/transactions](https://redis.io/topics/transactions) 如下:
|
Redis 官网相关介绍 [https://redis.io/topics/transactions](https://redis.io/topics/transactions) 如下:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Redis 支持原子性吗?
|
### Redis 支持原子性吗?
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ Redis 事务在运行错误的情况下,除了执行过程中出现错误的
|
|||||||
|
|
||||||
Redis 官网也解释了自己为啥不支持回滚。简单来说就是 Redis 开发者们觉得没必要支持回滚,这样更简单便捷并且性能更好。Redis 开发者觉得即使命令执行错误也应该在开发过程中就被发现而不是生产过程中。
|
Redis 官网也解释了自己为啥不支持回滚。简单来说就是 Redis 开发者们觉得没必要支持回滚,这样更简单便捷并且性能更好。Redis 开发者觉得即使命令执行错误也应该在开发过程中就被发现而不是生产过程中。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
你可以将 Redis 中的事务就理解为 :**Redis 事务提供了一种将多个命令请求打包的功能。然后,再按顺序执行打包的所有命令,并且不会被中途打断。**
|
你可以将 Redis 中的事务就理解为 :**Redis 事务提供了一种将多个命令请求打包的功能。然后,再按顺序执行打包的所有命令,并且不会被中途打断。**
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ Biggest string found '"ballcat:oauth:refresh_auth:f6cdb384-9a9d-4f2f-af01-dc3f28
|
|||||||
|
|
||||||
如下图所示,用户的请求最终都要跑到数据库中查询一遍。
|
如下图所示,用户的请求最终都要跑到数据库中查询一遍。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### 有哪些解决办法?
|
#### 有哪些解决办法?
|
||||||
|
|
||||||
@ -228,7 +228,7 @@ public Object getObjectInclNullById(Integer id) {
|
|||||||
|
|
||||||
加入布隆过滤器之后的缓存处理流程图如下。
|
加入布隆过滤器之后的缓存处理流程图如下。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
但是,需要注意的是布隆过滤器可能会存在误判的情况。总结来说就是: **布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。**
|
但是,需要注意的是布隆过滤器可能会存在误判的情况。总结来说就是: **布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。**
|
||||||
|
|
||||||
|