99 |
100 | 相信是个开发同学都对这个画面一点都不陌生吧,懂点行的仔都可以打开谷歌的**开发者模式**,然后看看你的网页代码,有的就有URL,但是我写VUE的时候是事件触发然后去调用文件里面的接口看源码看不到,但是我可以点击一下**查看你的请求地址**啊,不过你好像可以对按钮在秒杀前置灰。
101 |
102 | 不管怎么样子都有危险,撇开外面的所有的东西你都挡住了,你卖这个东西实在便宜得过分,有诱惑力,你能保证**开发不动心**?开发知道地址,在秒杀的时候自己提前请求。。。(开发:怎么TM又是我)
103 |
104 |
105 | 
106 |
107 | #### 数据库:
108 |
109 | 每秒上万甚至十几万的**QPS**(每秒请求数)直接打到**数据库**,基本上都要把库打挂掉,而且你服务不单单是做秒杀的还涉及其他的业务,你没做**降级、限流、熔断**啥的,别的一起挂,小公司的话可能**全站崩溃404**。
110 |
111 | 反正不管你秒杀怎么挂,你别把别的搞挂了对吧,搞挂了就不是杀一个程序员能搞定的。
112 |
113 | 程序员:我TM好难啊!
114 |
115 | ### 问题都列出来了,那怎么设计,怎么解决这些问题就是接下去要考虑的了,我们对症下药。
116 |
117 | #### 服务单一职责:
118 |
119 | 设计个能抗住高并发的系统,我觉得还是得**单一职责**。
120 |
121 | 什么意思呢,大家都知道现在设计都是**微服务的设计思想**,然后再用**分布式的部署方式**
122 |
123 | 也就是我们下单是有个订单服务,用户登录管理等有个用户服务等等,那为啥我们不给秒杀也开个服务,我们把秒杀的代码业务逻辑放一起。
124 |
125 | 单独给他建立一个数据库,现在的互联网架构部署都是**分库**的,一样的就是订单服务对应订单库,秒杀我们也给他建立自己的秒杀库。
126 |
127 | 至于表就看大家怎么设计了,该设置索引的地方还是要设置索引的,建完后记得用**explain**看看**SQL**的执行计划。(不了解的小伙伴也没事,MySQL章节我会说的)
128 |
129 | 单一职责的好处就是就算秒杀没抗住,秒杀库崩了,服务挂了,也不会影响到其他的服务。(强行高可用)
130 |
131 | #### 秒杀链接加盐:
132 |
133 | 我们上面说了链接要是提前暴露出去可能有人直接访问url就提前秒杀了,那又有小伙伴要说了我做个时间的校验就好了呀,那我告诉你,知道链接的地址比起页面人工点击的还是有**很大优势**。
134 |
135 | 我知道url了,那我通过程序不断获取最新的北京时间,可以达到**毫秒级别**的,我就在00毫秒的时候请求,我敢说绝对比你人工点的成功率大太多了,而且我可以一毫秒发送N次请求,搞不好你卖100个产品我全拿了。
136 |
137 |
138 |
139 | **那这种情况怎么避免?**
140 |
141 | 简单,把**URL动态化**,就连写代码的人都不知道,你就通过MD5之类的加密算法加密随机的字符串去做url,然后通过前端代码获取url后台校验才能通过。
142 |
143 | 暖男我呢,又准备了一个简单的url加密给大家尝尝鲜,还不**点个赞**?
144 |
145 |
152 |
153 | #### Nginx:
154 |
155 | **Nginx**大家想必都不陌生了吧,这玩意是**高性能的web服务器**,并发也随便顶几万不是梦,但是我们的**Tomcat**只能顶几百的并发呀,那简单呀**负载均衡**嘛,一台服务几百,那就多搞点,在秒杀的时候多租点**流量机**。
156 |
157 | Tip:据我所知国内某大厂就是在去年春节活动期间租光了亚洲所有的服务器,小公司也很喜欢在双十一期间买流量机来顶住压力。
158 |
159 |
160 |
161 | **这样一对比是不是觉得你的集群能顶很多了。**
162 |
163 | **恶意请求拦截**也需要用到它,一般单个用户请求次数太夸张,不像人为的请求在网关那一层就得拦截掉了,不然请求多了他抢不抢得到是一回事,服务器压力上去了,可能占用网络带宽或者把**服务器打崩、缓存击穿**等等。
164 |
165 | #### 资源静态化:
166 |
167 | 秒杀一般都是特定的商品还有页面模板,现在一般都是前后端分离的,所以页面一般都是不会经过后端的,但是前端也要自己的服务器啊,那就把能提前放入**cdn服务器**的东西都放进去,反正把所有能提升效率的步骤都做一下,减少真正秒杀时候服务器的压力。
168 |
169 | #### 按钮控制:
170 |
171 | 大家有没有发现没到秒杀前,一般按钮都是**置灰**的,只有时间到了,才能点击。
172 |
173 | 这是因为怕大家在时间快到的最后几秒秒疯狂请求服务器,然后还没到秒杀的时候基本上服务器就挂了。
174 |
175 | 这个时候就需要前端的配合,定时去请求你的后端服务器,获取最新的北京时间,到时间点再给按钮可用状态。
176 |
177 | 按钮可以点击之后也得给他置灰几秒,不然他一样在开始之后一直点的。**你敢说你们秒杀的时候不是这样的?**
178 |
179 |
180 |
181 | #### 限流:
182 |
183 | 限流这里我觉得应该分为**前端限流**和**后端限流**。
184 |
185 | **前端限流**:这个很简单,一般秒杀不会让你一直点的,一般都是点击一下或者两下然后几秒之后才可以继续点击,这也是保护服务器的一种手段。
186 |
187 | **后端限流**:秒杀的时候肯定是涉及到后续的订单生成和支付等操作,但是都只是成功的幸运儿才会走到那一步,那一旦100个产品卖光了,return了一个false,前端直接秒杀结束,然后你后端也关闭后续无效请求的介入了。
188 |
189 | Tip:真正的限流还会有限流组件的加入例如:阿里的Sentinel、Hystrix等。我这里就不展开了,就说一下物理的限流。
190 |
191 | #### 库存预热:
192 |
193 | **秒杀的本质,就是对库存的抢夺**,每个秒杀的用户来你都去数据库查询库存校验库存,然后扣减库存,撇开性能因数,你不觉得这样好繁琐,对业务开发人员都不友好,而且数据库顶不住啊。
194 |
195 | **开发:你tm总算为我着想一次了。**
196 |
197 | 
198 |
199 | #### 那怎么办?
200 |
201 | 我们都知道数据库顶不住但是他的兄弟非关系型的数据库**Redis**能顶啊!
202 |
203 | 那不简单了,我们要开始秒杀前你通过定时任务或者运维同学**提前把商品的库存加载到Redis中**去,让整个流程都在Redis里面去做,然后等秒杀介绍了,再异步的去修改库存就好了。
204 |
205 | 但是用了Redis就有一个问题了,我们上面说了我们采用**主从**,就是我们会去读取库存然后再判断然后有库存才去减库存,正常情况没问题,但是高并发的情况问题就很大了。
206 |
207 | 这里我就不画图了,我本来想画图的,想了半天我觉得语言可能更好表达一点。
208 |
209 | **多品几遍!!!**就比如现在库存只剩下1个了,我们高并发嘛,4个服务器一起查询了发现都是还有1个,那大家都觉得是自己抢到了,就都去扣库存,那结果就变成了-3,是的只有一个是真的抢到了,别的都是超卖的。咋办?
210 |
211 | ### Lua:
212 |
213 | 之前的文章就简单的提到了他,我今天就多一定点篇幅说一下吧。
214 |
215 | > **Lua** 脚本功能是 Reids在 2.6 版本的最大亮点, 通过内嵌对 Lua 环境的支持, Redis 解决了长久以来不能高效地处理 **CAS** (check-and-set)命令的缺点, 并且可以通过组合使用多个命令, 轻松实现以前很难实现或者不能高效实现的模式。
216 |
217 | **Lua脚本是类似Redis事务,有一定的原子性,不会被其他命令插队,可以完成一些Redis事务性的操作。**这点是关键。
218 |
219 | 知道原理了,我们就写一个脚本把判断库存扣减库存的操作都写在一个脚本丢给Redis去做,那到0了后面的都Return False了是吧,一个失败了你修改一个开关,直接挡住所有的请求,然后再做后面的事情嘛。
220 |
221 | #### 限流&降级&熔断&隔离:
222 |
223 | 这个为啥要做呢,不怕一万就怕万一,万一你真的顶不住了,**限流**,顶不住就挡一部分出去但是不能说不行,**降级**,降级了还是被打挂了,**熔断**,至少不要影响别的系统,**隔离**,你本身就独立的,但是你会调用其他的系统嘛,你快不行了你别拖累兄弟们啊。
224 |
225 | 
226 |
227 | #### 削峰填谷:
228 |
229 | 一说到这个名词,很多小伙伴就知道了,对的**MQ**,你买东西少了你直接100个请求改库我觉得没问题,但是万一秒杀一万个,10万个呢?服务器挂了,**程序员又要背锅的**。
230 |
231 | Tip:**可能小伙伴说我们业务达不到这个量级,没必要。但是我想说我们写代码,就不应该写出有逻辑漏洞的代码,至少以后公司体量上去了,别人一看居然不用改代码,一看代码作者是敖丙?有点东西!**
232 |
233 | 你可以把它放消息队列,然后一点点消费去改库存就好了嘛,不过单个商品其实一次修改就够了,我这里说的是**某个点多个商品**一起秒杀的场景,像极了双十一零点。
234 |
235 | ## 总结
236 |
237 | 到这里我想我已经基本上把该考虑的点还有对应的解决方案也都说了一下,不知道还有没有没考虑到的,但是就算没考虑到我想我这个设计,应该也能撑住一个完整的秒杀流程。
238 |
239 | (有大佬的话给敖丙点多的思路,去GitHub [https://github.com/JavaFamily](https://github.com/AobingJava/JavaFamily) 上给我提,也有我的联系)
240 |
241 | 最后我就画个完整的流程图给大家收个尾吧!
242 |
243 | 
244 | Tip:这个链路还是比较简单的,很多细节的点全部画出来就太复杂了,我上面已经提到了所有的注意点了,大家都看看,真正的秒杀有比我这个简单的,也有比我这个复杂N倍的,之前的电商老东家就做的很高级,有机会也可以跟你们探讨,不过是面试嘛,我就给思路,让你理解比较关键的点。
245 |
246 | 秒杀这章我脑细胞死了很多,考虑了很多个点,最后还是出来了,忍不住给自己**点赞**!
247 |
248 | (**这章是真的不要白嫖,每次都看了不点赞,你们想白嫖我么?你们好坏喲,不过我好喜欢**)
249 |
250 | ## 总结
251 |
252 | 我们玩归玩,闹归闹,别拿面试开玩笑。
253 |
254 | 秒杀不一定是每个同学都会问到的,至少肯定没**Redis基础**那样常问,但是一旦问到,大家一定要回答到点上。
255 |
256 | 至少你得说出**可能出现的情况**,**需要注意的情况**,以及对于的**解决思路和方案**。
257 |
258 | 最后就是需要对整个链路比较熟悉,注意是一个完整的链路,前端怎么设计的呀,网关的作用呀,怎么**解决Redis的并发竞争**啊,**数据的同步方式**呀,**MQ的作用**啊。
259 |
260 | (提到MQ又是一整条的知识链路,什么异步、削峰、解耦等等,所以面试,我们还是不打没有把握的胜仗)
261 |
262 | ### 流着泪说再见
263 |
264 | **Redis系列**到此是真的要跟大家说再见了,写了7篇文章,其实很多大佬的思路和片段真心赞,其实大家看出来了我的文章个人风格色彩特别浓厚,我个人在生活中就是这么说话的,也希望用这种风格把原本枯燥乏味的知识点让大家都像看小说一样津津有味的看下去,不知道大家什么感受,好的不好的都请给我留言。
265 |
266 | 我这个系列的我会写到我**GitHub** [https://github.com/JavaFamily](https://github.com/AobingJava/JavaFamily) 图中所有的知识点,以后就麻烦大家多多关照了,我写作的时间都是业余时间,基本上周末和晚上的时间都贡献出来了,我也是个新人很多点也没接触到,也要看书看资料才能写出来,所以有时候还是希望大家多多包涵。
267 |
268 | 那我们下期见!
269 |
270 | 下期写________________?
271 |
272 | 不告诉你,哈哈!
273 |
274 | ## 日常求赞
275 |
276 | 好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是**人才**。
277 |
278 | 我后面会每周都更新几篇《吊打面试官》系列和互联网常用技术栈相关的文章,非常感谢**人才**们能看到这里,如果这个文章写得还不错,觉得「敖丙」我**有点东西**的话 **求点赞👍** **求关注❤️** **求分享👥** 对暖男我来说真的 **非常有用**!!!
279 |
280 | 创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!
281 |
282 | 敖丙 | 文 【原创】【转载请联系本人】 如果本篇博客有任何错误,请批评指教,不胜感激 !
283 |
284 | ------
285 |
286 | > 《吊打面试官》系列每周持续更新,可以关注我的公众号「**JavaFamily**」第一时间阅读和催更(公众号比博客早一到两篇哟),本文**GitHub**上已经收录[https://github.com/JavaFamily](https://github.com/AobingJava/JavaFamily),有一线大厂面试点思维导图,欢迎Star和完善,里面也有我个人联系方式有什么问题也可以直接找我,也有人才交流群,我们一起有点东西。
287 |
288 | 
--------------------------------------------------------------------------------
/docs/all/缓存/redis/集群高可用、哨兵、持久化、LRU.md:
--------------------------------------------------------------------------------
1 | > 你知道的越多,你不知道的越多
2 |
3 | > 点赞再看,养成习惯
4 |
5 | ## 前言
6 |
7 | **Redis**在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在**Redis**的使用和原理方面对小伙伴们进行360°的刁难。作为一个在互联网公司面一次拿一次offer的面霸(**请允许我使用一下夸张的修辞手法**),打败了无数竞争对手,每次都只能看到无数落寞的身影失望的离开,略感愧疚,在一个寂寞难耐的夜晚,我痛定思痛,决定开始写**《吊打面试官》**系列,希望能帮助各位读者以后面试势如破竹,对面试官进行360°的反击,吊打问你的面试官,让一同面试的同僚瞠目结舌,疯狂收割大厂**Offer**!
8 |
9 | ## 絮叨
10 |
11 | 写这期其实比较纠结,我之前的写的比较通俗易懂,一是我都知道这些点,二是之前我在所在的电商公司对雪崩,击穿啥的还算有场景去接触。但是线上的Redis集群我实际操作经验很少,总不能在公司线上环境实践那些操作吧,所以最后看了下官网,还有一些资料(文章后面我都会贴出来),强行怼了这么篇出来。
12 |
13 | 最近双十一小忙,周末双十一值班目测没时间写,那我是暖男呀,我不能鸽啊,就有了这一篇,下一篇迟到你们不要喷我哈,而且下一篇还是**Redis**的终章还是得构思下,不熟悉的知识点我怕漏洞多,特意让以前的大牛同事看了下,所以有啥不对的地方大家及时留言**Diss**我,写这篇是真的难,诺下面就是我本人某天凌晨两点的拍的视频,多动症的仔。
14 |
15 | 
16 |
17 | 之前说过系列第二篇到300赞我就发第三篇
18 |
19 | 
20 |
21 | 
22 |
23 | 咋样没骗你们吧,就很枯竭,不BB了,开搞。
24 |
25 | **不点个赞对不起我,这次不要白嫖我!**
26 |
27 | ----
28 |
29 | ##正文
30 |
31 | 上几期**《吊打面试官》**还没看的小伙伴可以回顾一下(明明就写了两期说的好像很多一样)!
32 |
33 | - [《吊打面试官》系列-Redis基础](https://juejin.im/post/5db66ed9e51d452a2f15d833)
34 | - [《吊打面试官》系列-缓存雪崩、击穿、穿透](https://juejin.im/post/5dbef8306fb9a0203f6fa3e2)
35 |
36 | 大家都知道一个技术的引入方便了开发,解决了各种问题,但是也会带来对应的问题,**技术是把双刃剑**嘛,集群的引入也会带来很多问题,如:集群的高可用怎么保证,数据怎么同步等等,我们话不多说,有请下一位受害者为我们展示。
37 |
38 | ### 面试开始
39 |
40 | > 三个大腹便便,穿着格子衬衣的中年男子,拿着三个满是划痕的mac向你走来,看着快秃顶的头发,心想着肯定是尼玛顶级架构师吧!而且还是三个,但是还好我看过敖丙写的《吊打面试官》系列,腹有诗书气自华,根本虚都不虚好伐。
41 |
42 | 
43 |
44 | #### 小伙子你好,之前问过了你基础知识以及一些缓存的常见几个大问题了,那你能跟我聊聊为啥Redis那么快么?
45 |
46 | 哦,帅气迷人的面试官您好,我们可以先看一下关系型数据库跟Redis本质上的区别。
47 |
48 | 
49 |
50 | **Redis**采用的是基于内存的采用的是单进程单线程模型的 KV 数据库,由C语言编写,官方提供的数据是可以达到100000+的**QPS(每秒内查询次数)**。
51 |
52 | - 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。它的,数据存在内存中,类似于**HashMap**,**HashMap**的优势就是查找和操作的时间复杂度都是O(1);
53 | - 数据结构简单,对数据操作也简单,**Redis**中的数据结构是专门进行设计的;
54 | - 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 **CPU**,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
55 |
56 | - 使用多路I/O复用模型,非阻塞IO;
57 | - 使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,**Redis**直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;
58 |
59 | ### 我可以问一下啥是上下文切换么?
60 |
61 | 我可以打个比方么:我记得有过一个小伙伴微信问过我上下文切换是啥,为啥可能会线程不安全,我是这么说的,就好比你看一本英文书,你看到第十页发现有个单词不会读,你加了个书签,然后去查字典,过了一会你又回来继续从书签那里读,ok到目前为止没啥问题。
62 |
63 | 如果是你一个人读肯定没啥问题,但是你去查的时候,别的小伙伴好奇你在看啥他就翻了一下你的书,然后溜了,哦豁,你再看的时候就发现书不是你看的那一页了。不知道到这里为止我有没有解释清楚,以及为啥会线程不安全,就是因为你一个人怎么看都没事,但是人多了换来换去的操作一本书数据就乱了。可能我的解释很粗糙,但是道理应该是一样的。
64 |
65 | ### 那他是单线程的,我们现在服务器都是多核的,那不是很浪费?
66 |
67 | 是的他是单线程的,但是,我们可以通过在单机开多个**Redis实例**嘛。
68 |
69 | ### 既然提到了单机会有瓶颈,那你们是怎么解决这个瓶颈的?
70 |
71 | 我们用到了集群的部署方式也就是**Redis cluster**,并且是主从同步读写分离,类似**Mysql**的主从同步,**Redis cluster** 支撑 N 个 **Redis master node**,每个**master node**都可以挂载多个 **slave node**。
72 |
73 | 这样整个 **Redis** 就可以横向扩容了。如果你要支撑更大数据量的缓存,那就横向扩容更多的 **master** 节点,每个 **master** 节点就能存放更多的数据了。
74 |
75 | ### 哦?那问题就来了,他们之间是怎么进行数据交互的?以及Redis是怎么进行持久化的?Redis数据都在内存中,一断电或者重启不就木有了嘛?
76 |
77 | 是的,持久化的话是**Redis**高可用中比较重要的一个环节,因为**Redis**数据在内存的特性,持久化必须得有,我了解到的持久化是有两种方式的。
78 |
79 | - RDB:**RDB** 持久化机制,是对 **Redis** 中的数据执行**周期性**的持久化。
80 | - AOF:**AOF** 机制对每条写入命令作为日志,以 **append-only** 的模式写入一个日志文件中,因为这个模式是只追加的方式,所以没有任何磁盘寻址的开销,所以很快,有点像Mysql中的**binlog**。
81 |
82 | 两种方式都可以把**Redis**内存中的数据持久化到磁盘上,然后再将这些数据备份到别的地方去,**RDB**更适合做**冷备**,**AOF**更适合做**热备**,比如我杭州的某电商公司有这两个数据,我备份一份到我杭州的节点,再备份一个到上海的,就算发生无法避免的自然灾害,也不会两个地方都一起挂吧,这**灾备**也就是**异地容灾**,地球毁灭他没办法。
83 |
84 | **tip:两种机制全部开启的时候,Redis在重启的时候会默认使用AOF去重新构建数据,因为AOF的数据是比RDB更完整的。**
85 |
86 | ### 那这两种机制各自优缺点是啥?
87 |
88 | 我先说**RDB**吧
89 |
90 | #### 优点:
91 |
92 | 他会生成多个数据文件,每个数据文件分别都代表了某一时刻**Redis**里面的数据,这种方式,有没有觉得很适合做**冷备**,完整的数据运维设置定时任务,定时同步到远端的服务器,比如阿里的云服务,这样一旦线上挂了,你想恢复多少分钟之前的数据,就去远端拷贝一份之前的数据就好了。
93 |
94 | **RDB**对**Redis**的性能影响非常小,是因为在同步数据的时候他只是**fork**了一个子进程去做持久化的,而且他在数据恢复的时候速度比**AOF**来的快。
95 |
96 | #### 缺点:
97 |
98 | **RDB**都是快照文件,都是默认五分钟甚至更久的时间才会生成一次,这意味着你这次同步到下次同步这中间五分钟的数据都很可能全部丢失掉。**AOF**则最多丢一秒的数据,**数据完整性**上高下立判。
99 |
100 | 还有就是**RDB**在生成数据快照的时候,如果文件很大,客户端可能会暂停几毫秒甚至几秒,你公司在做秒杀的时候他刚好在这个时候**fork**了一个子进程去生成一个大快照,哦豁,出大问题。
101 |
102 | 我们再来说说**AOF**
103 |
104 | ####优点:
105 |
106 | 上面提到了,**RDB**五分钟一次生成快照,但是**AOF**是一秒一次去通过一个后台的线程`fsync`操作,那最多丢这一秒的数据。
107 |
108 | **AOF**在对日志文件进行操作的时候是以`append-only`的方式去写的,他只是追加的方式写数据,自然就少了很多磁盘寻址的开销了,写入性能惊人,文件也不容易破损。
109 |
110 | **AOF**的日志是通过一个叫**非常可读**的方式记录的,这样的特性就适合做**灾难性数据误删除**的紧急恢复了,比如公司的实习生通过**flushall**清空了所有的数据,只要这个时候后台重写还没发生,你马上拷贝一份**AOF**日志文件,把最后一条**flushall**命令删了就完事了。
111 |
112 | **tip:我说的命令你们别真去线上系统操作啊,想试去自己买的服务器上装个Redis试,别到时候来说,敖丙真是个渣男,害我把服务器搞崩了,Redis官网上的命令都去看看,不要乱试!!!**
113 |
114 | ####缺点:
115 |
116 | 一样的数据,**AOF**文件比**RDB**还要大。
117 |
118 | **AOF**开启后,**Redis**支持写的**QPS**会比**RDB**支持写的要低,他不是每秒都要去异步刷新一次日志嘛**fsync**,当然即使这样性能还是很高,我记得**ElasticSearch**也是这样的,异步刷新缓存区的数据去持久化,为啥这么做呢,不直接来一条怼一条呢,那我会告诉你这样性能可能低到没办法用的,大家可以思考下为啥哟。
119 |
120 | ###那两者怎么选择?
121 |
122 | 
123 |
124 | 小孩子才做选择,**我全都要**,你单独用**RDB**你会丢失很多数据,你单独用**AOF**,你数据恢复没**RDB**来的快,真出什么时候第一时间用**RDB**恢复,然后**AOF**做数据补全,真香!冷备热备一起上,才是互联网时代一个高健壮性系统的王道。
125 |
126 | ### 看不出来年纪轻轻有点东西的呀,对了我听你提到了高可用,Redis还有其他保证集群高可用的方式么?
127 |
128 | !!!晕 自己给自己埋个坑(其实是明早就准备好了,故意抛出这个词等他问,就怕他不问)。
129 |
130 | 假装思考一会(**不要太久,免得以为你真的不会**),哦我想起来了,还有哨兵集群**sentinel**。
131 |
132 | 哨兵必须用三个实例去保证自己的健壮性的,哨兵+主从并**不能保证数据不丢失**,但是可以保证集群的**高可用**。
133 |
134 | 为啥必须要三个实例呢?我们先看看两个哨兵会咋样。
135 |
136 | 
137 |
138 |
139 |
140 | master宕机了 s1和s2两个哨兵只要有一个认为你宕机了就切换了,并且会选举出一个哨兵去执行故障,但是这个时候也需要大多数哨兵都是运行的。
141 |
142 | 那这样有啥问题呢?M1宕机了,S1没挂那其实是OK的,但是整个机器都挂了呢?哨兵就只剩下S2个裸屌了,没有哨兵去允许故障转移了,虽然另外一个机器上还有R1,但是故障转移就是不执行。
143 |
144 | 经典的哨兵集群是这样的:
145 |
146 | 
147 |
148 | M1所在的机器挂了,哨兵还有两个,两个人一看他不是挂了嘛,那我们就选举一个出来执行故障转移不就好了。
149 |
150 | 暖男我,小的总结下哨兵组件的主要功能:
151 |
152 | - 集群监控:负责监控 Redis master 和 slave 进程是否正常工作。
153 |
154 | - 消息通知:如果某个 **Redis** 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
155 |
156 | - 故障转移:如果 master node 挂掉了,会自动转移到 slave node 上。
157 |
158 | - 配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址。
159 |
160 | ### 我记得你还提到了主从同步,能说一下主从之间的数据怎么同步的么?
161 |
162 | 面试官您的记性可真是一级棒呢,我都要忘了你还记得,我特么谢谢你,提到这个,就跟我前面提到的数据持久化的**RDB**和**AOF**有着比密切的关系了。
163 |
164 | 我先说下为啥要用主从这样的架构模式,前面提到了单机**QPS**是有上限的,而且**Redis**的特性就是必须支撑读高并发的,那你一台机器又读又写,**这谁顶得住啊**,不当人啊!但是你让这个master机器去写,数据同步给别的slave机器,他们都拿去读,分发掉大量的请求那是不是好很多,而且扩容的时候还可以轻松实现水平扩容。
165 |
166 | 
167 |
168 | **回归正题,他们数据怎么同步的呢?**
169 |
170 | 你启动一台slave 的时候,他会发送一个**psync**命令给master ,如果是这个slave第一次连接到master,他会触发一个全量复制。master就会启动一个线程,生成**RDB**快照,还会把新的写请求都缓存在内存中,**RDB**文件生成后,master会将这个**RDB**发送给slave的,slave拿到之后做的第一件事情就是写进本地的磁盘,然后加载进内存,然后master会把内存里面缓存的那些新命名都发给slave。
171 |
172 | ###数据传输的时候断网了或者服务器挂了怎么办啊?
173 |
174 | 传输过程中有什么网络问题啥的,会自动重连的,并且连接之后会把缺少的数据补上的。
175 |
176 | **大家需要记得的就是,RDB快照的数据生成的时候,缓存区也必须同时开始接受新请求,不然你旧的数据过去了,你在同步期间的增量数据咋办?是吧?**
177 |
178 | ### 那说了这么多你能说一下他的内存淘汰机制么,来手写一下LRU代码?
179 |
180 | 
181 |
182 | #### 手写LRU?你是不是想直接跳起来说一句:Are U F**k Kidding me?
183 |
184 | 这个问题是我在蚂蚁金服三面的时候亲身被问过的问题,不知道大家有没有被怼到过这个问题。
185 |
186 | **Redis**的过期策略,是有**定期删除+惰性删除**两种。
187 |
188 | 定期好理解,默认100s就随机抽一些设置了过期时间的key,去检查是否过期,过期了就删了。
189 |
190 | ### 为啥不扫描全部设置了过期时间的key呢?
191 |
192 | 假如Redis里面所有的key都有过期时间,都扫描一遍?那太恐怖了,而且我们线上基本上也都是会设置一定的过期时间的。全扫描跟你去查数据库不带where条件不走索引全表扫描一样,100s一次,Redis累都累死了。
193 |
194 | ###如果一直没随机到很多key,里面不就存在大量的无效key了?
195 |
196 | 好问题,**惰性删除**,见名知意,惰性嘛,我不主动删,我懒,我等你来查询了我看看你过期没,过期就删了还不给你返回,没过期该怎么样就怎么样。
197 |
198 | ### 最后就是如果的如果,定期没删,我也没查询,那可咋整?
199 |
200 | **内存淘汰机制**!
201 |
202 | 官网上给到的内存淘汰机制是以下几个:
203 |
204 | - **noeviction**:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)
205 |
206 | - **allkeys-lru**: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
207 |
208 | - **volatile-lru**: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
209 |
210 | - **allkeys-random**: 回收随机的键使得新添加的数据有空间存放。
211 |
212 | - **volatile-random**: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
213 |
214 | - **volatile-ttl**: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
215 |
216 | 如果没有键满足回收的前提条件的话,策略**volatile-lru**, **volatile-random**以及**volatile-ttl**就和noeviction 差不多了。
217 |
218 | 至于**LRU**我也简单提一下,手写实在是太长了,大家可以去**Redis官网**看看,我把**近视LUR**效果给大家看看
219 |
220 | **tip:Redis为什么不使用真实的LRU实现是因为这需要太多的内存。不过近似的LRU算法对于应用而言应该是等价的。使用真实的LRU算法与近似的算法可以通过下面的图像对比。**
221 |
222 | 
223 |
224 | 你可以看到三种点在图片中, 形成了三种带.
225 |
226 | - 浅灰色带是已经被回收的对象。
227 | - 灰色带是没有被回收的对象。
228 | - 绿色带是被添加的对象。
229 | - 在**LRU**实现的理论中,我们希望的是,在旧键中的第一半将会过期。**Redis**的**LRU**算法则是概率的过期旧的键。
230 |
231 | 你可以看到,在都是五个采样的时候Redis 3.0比Redis 2.8要好,Redis2.8中在最后一次访问之间的大多数的对象依然保留着。使用10个采样大小的Redis 3.0的近似值已经非常接近理论的性能。
232 |
233 | 注意LRU只是个预测键将如何被访问的模型。另外,如果你的数据访问模式非常接近幂定律,大部分的访问将集中在一个键的集合中,LRU的近似算法将处理得很好。
234 |
235 | 其实在大家熟悉的**LinkedHashMap**中也实现了Lru算法的,实现如下:
236 |
237 | 
238 |
239 | 当容量超过100时,开始执行**LRU**策略:将最近最少未使用的 **TimeoutInfoHolder** 对象 **evict** 掉。
240 |
241 | 真实面试中会让你写LUR算法,你可别搞原始的那个,那真TM多,写不完的,你要么怼上面这个,要么怼下面这个,找一个数据结构实现下Java版本的LRU还是比较容易的,知道啥原理就好了。
242 |
243 | 
244 |
245 | ## 面试结束
246 |
247 | ### 小伙子,你确实有点东西,HRBP会联系你的,请务必保持你的手机畅通好么?
248 |
249 | 好的谢谢面试官,面试官真好,我还想再面几次,噗此。
250 |
251 | 能回答得这么全面这么细节还是忍不住点赞
252 |
253 | **(暗示点赞,每次都看了不点赞,你们想白嫖我么?你们好坏喲,不过我好喜欢)**
254 |
255 | ## 总结
256 |
257 | 好了,我们玩归玩,闹归闹,别拿面试开玩笑,我这么写是为了节目效果,大家面试请认真对待。
258 |
259 | 这一期是这期没前面好理解了对吧,我就在自己的服务器上启动了,然后再去官网看看命令一顿瞎操作的,查阅了部分资料,这里给大家推荐几本经典的Redis入门的书籍和我参考的资料。
260 |
261 | - [Redis中文官网](http://www.redis.cn/)
262 |
263 | - 《Redis入门指南(第2版)》
264 |
265 | - 《Redis实战》
266 |
267 | - 《Redis设计与实现》
268 |
269 | - 《[大型网站技术架构](https://github.com/doocs/technical-books#architecture)——李智慧》
270 |
271 | - 《[Redis 设计与实现](https://github.com/doocs/technical-books#database)——黄健宏》
272 |
273 | - 《[Redis 深度历险](https://github.com/doocs/technical-books#database)——钱文品》
274 |
275 | - 《[亿级流量网站架构核心技术](https://github.com/doocs/technical-books#architecture)——张开涛》
276 | - 《[中华石杉](https://github.com/doocs/advanced-java)——石杉》
277 |
278 | 不出意外的话这是Redis的倒数第二期,最后一期不知道写啥还没想好,我得好好想想,加上最近不是双十一嘛得加加班,**你看看开头的我,多可怜,那还不点个赞?买个服务器**?不确定下一期多久出,想早点看到更新的小伙伴可以去公众号**催更**,公众号提前一到两天更新。
279 |
280 |
281 | ### END
282 |
283 | 好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是**人才**,我后面会每周都更新几篇《**吊打面试官**》系列和**Java技术栈**相关的文章。如果你有什么想知道的,也可以**留言**给我,我一有时间就会写出来,我们共同进步。
284 |
285 | 非常感谢**靓仔/靓女**您能看到这里,如果这个文章写得还不错,觉得敖丙有点东西 **求点赞** **求关注** **求分享** **求留言** **(对我非常有用)**各位的支持和认可,就是我创作的最大动力,我们下篇文章见!
286 |
287 | 敖丙 | 文 【原创】
288 |
289 | ------
290 |
291 | > 每周都会持续更新《吊打面试官》系列可以关注我的公众号第一时间阅读和催更,公众号比博客提前一到两天更新,也可以在公众号回复【人才】加入人才交流群,里面都是人才长得好看说话还好听,进去就像回家了一样,就业和工作上有什么问题也可以直接滴滴我,我也是个新人,不过不影响我们一起进步。
292 |
293 | 
--------------------------------------------------------------------------------
/docs/all/mq/重复消费、顺序消费、分布式事务.md:
--------------------------------------------------------------------------------
1 | > 你知道的越多,你不知道的越多
2 |
3 | > 点赞再看,养成习惯
4 |
5 | > **GitHub**上已经开源 [https://github.com/JavaFamily](https://github.com/AobingJava/JavaFamily) 有一线大厂面试点脑图、个人联系方式和人才交流群,欢迎Star和完善
6 |
7 | ## 前言
8 |
9 | **消息队列**在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在**消息队列**的使用和原理方面对小伙伴们进行360°的刁难。
10 |
11 | 作为一个在互联网公司面一次拿一次Offer的面霸,打败了无数竞争对手,每次都只能看到无数落寞的身影失望的离开,略感愧疚(**请允许我使用一下夸张的修辞手法**)。
12 |
13 | 于是在一个寂寞难耐的夜晚,**暖男**我痛定思痛,决定开始写**《吊打面试官》**系列,希望能帮助各位读者以后面试势如破竹,对面试官进行360°的反击,吊打问你的面试官,让一同面试的同僚瞠目结舌,疯狂收割大厂Offer!
14 |
15 | ## 捞一下
16 |
17 | 上一期,简单的介绍了一下**消息队列**的基础知识,里面有消息队列的应用场景,以及使用之后可能带来的问题,但是上期没对怎么解决这些问题做回答,因为要控制篇幅嘛(明明是自己觉得MQ写不了多少期,要多怼一期出来!渣男)
18 |
19 | 咳咳,我们言归正传,没看的朋友去看一下,有助于这期的阅读:
20 |
21 | [《吊打面试官》系列-消息队列基础](https://juejin.im/post/5dd3ff85e51d453fe34dfcc5)
22 |
23 | ## 面试开始
24 |
25 | >一个风度翩翩,穿着格子衬衣的中年男子,拿着一个满是划痕的mac向你走来,看着铮亮的头,心想着肯定是尼玛顶级架构师吧!但是我们看过暖男敖丙的系列,腹有诗书气自华,虚都不虚。
26 |
27 | 
28 |
29 | ### 没错小伙子还是我,上次话说一半你就溜了,这次我非得好好的问问你。
30 |
31 | 好的面试官,因为上次着急,敖丙的系列更新了所以赶回家去看了!
32 |
33 | ### 我信你个鬼,我们开始吧,上次说到了消息队列的消息重复消费,你能跟我介绍这是怎么样子的场景么?
34 |
35 | 消息**重复消费**是使用消息队列之后,必须考虑的一个问题,也是比较严重和常见的问题,**帅丙**我在开发过程中,但凡用到了消息队列,我第一时间考虑的就是**重复消费**的问题。
36 |
37 | 就比如有这样的一个场景,用户下单成功后我需要去一个活动页面给他加**GMV**(销售总额),最后根据他的GMV去给他发奖励,这是电商活动很常见的玩法。
38 |
39 | 类似累计下单金额到哪个梯度给你返回什么梯度的奖励这样。
40 |
41 | 
42 |
43 | 我只能告诉你这样的活动页面**10000%**是用**异步**去加的(别问我为什么,因为这个活动的后端是敖丙我做的😂),不然你想,你一个用户下一单就给他加一下,那就意味着对那张表就要操作一下,你考虑下双十一当天多少次对这个表的操作?这数据库或者缓存都顶不住吧。
44 |
45 | 而且大家应该也有这样的体会,你下单了马上去看一些活动页面,有时候马上就有了,有时候却延迟有很久,为啥?这个速度**取决于消息队列的消费速度**,消费慢堵塞了就迟点看到呗。
46 |
47 | 你下个单**支付成功**你就发个消息出去,我们上面那个活动的开发人员就**监听**你的**支付成功消息**,我监听到你这个订单成功支付的消息,那我就去我活动GMV表里给你加上去,听到这里大家可能**觉得顺理成章**。
48 |
49 | 
50 |
51 | **但是**我告诉大家一般消息队列的使用,我们都是有**重试机制**的,就是说我下游的业务发生异常了,我会抛出异常并且要求你**重新发一次**。
52 |
53 | 我这个活动这里发生错误,你要求重发肯定没问题。但是大家**仔细想一下**问题在哪里?
54 |
55 | 是的,不止你一个人监听这个消息啊,**还有别的服务也在监听**,他们也会失败啊,他一失败他也要求重发,但是你这里其实是成功的,重发了,你的钱不就加了两次了?
56 |
57 | **对不对???是不是这个道理???**
58 |
59 | 还不理解?看下面 **↓**
60 |
61 | 
62 |
63 | 就好比上面的这样,我们的**积分系统处理失败**了,他这个系统肯定要求你**重新发送**一次这个消息对吧,积分的系统重新接收并且处理成功了,但是别人的活动,优惠券等等服务**也监听了这个消息**呀,那不就可能出现活动系统给他加GMV加两次,优惠券扣两次这种情况么?
64 |
65 | 真实的情况其实重试是很正常的,服务的**网络抖动**,**开发人员代码Bug**,还有**数据问题**等都可能处理失败要求重发的。
66 |
67 | ### 嗯小伙子分析得很仔细嘛,那你在开发过程中是怎么去保证的呀?
68 |
69 | 一般我们叫这样的处理叫接口**幂等**。
70 |
71 | > **幂等(idempotent、idempotence)**是一个数学与计算机学概念,常见于抽象代数中。
72 | >
73 | > 在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。
74 | >
75 | > 幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。
76 | >
77 | > 例如,“setTrue()”函数就是一个幂等函数,**无论多次执行,其结果都是一样的.**更复杂的操作幂等保证是利用唯一交易号(流水号)实现.
78 |
79 | 通俗了讲就是你**同样的参数调用我这个接口,调用多少次结果都是一个**,你加GMV同一个订单号你加一次是多少钱,你加N次都还是多少钱。
80 |
81 | 但是如果**不做幂等**,你一个订单调用多次钱不就加多次嘛,同理你退款调用多次钱也就减多次了。
82 |
83 | 大致处理流程如下:
84 |
85 | 
86 |
87 | ### 那怎么保证呢?
88 |
89 | 一般**帅丙**我是这么回答的:
90 |
91 | 帅气面试官您好,一般**幂等**,我会**分场景去考虑**,看是**强校验**还是**弱校验**,比如跟金钱相关的场景那就很关键呀,就做强校验,别不是很重要的场景做弱校验。
92 |
93 | #### 强校验:
94 |
95 | 比如你监听到用户支付成功的消息,你监听到了去加GMV是不是要调用加钱的接口,那加钱接口下面再调用一个加流水的接口,**两个放在一个事务,成功一起成功失败一起失败**。
96 |
97 | 每次消息过来都要拿着**订单号+业务场景这样的唯一标识**(比如天猫双十一活动)去流水表查,看看有没有这条流水,有就直接return不要走下面的流程了,没有就执行后面的逻辑。
98 |
99 | 之所以用**流水表**,是因为涉及到金钱这样的活动,有啥问题后面也可以去流水表**对账**,还有就是帮助开发人员定位问题。
100 |
101 | 有的小伙伴可能还是有点懵,然后**人才交流群**的小伙伴也说有些例子可以放一点伪代码,那这期开始能用代码将的我也写点。
102 |
103 | 
104 |
105 | **Tip**:**GItHub** [https://github.com/JavaFamily](https://github.com/AobingJava/JavaFamily) 上有进群方式和个人联系方式,说实话在这个群,哪怕您不说话,光看聊天记录,都能学到东西(美团王炸,三歪(Java3y),并夕夕等的大佬都在)。
106 |
107 | #### 弱校验:
108 |
109 | 这个简单,一些不重要的场景,比如给谁发短信啥的,我就把这个id+场景唯一标识作为**Redis**的key,放到缓存里面失效时间看你场景,**一定时间内**的这个消息就去Redis判断。
110 |
111 | 用KV就算消息丢了可能这样的场景也没关系,反正丢条**无关痛痒**的通知短信嘛(你敢说你没验证码短信丢失的情况?)。
112 |
113 |
114 | 还有很多公司的弱校验用**token**啊什么的,反正花样很多,但是**重要的场景一定要强校验**,真正查问题的时候没有在磁盘持久化的数据,心里还是空空的,就像你和女朋友分开的时候的心里状态一样。(我单身的怎么知道这种感觉?猜的)
115 |
116 | ### 你们有接触过消息顺序消费这样的场景么?你怎么保证的?
117 |
118 | 没有!over!
119 |
120 | 乖,你肯定不能说没有啊,就是算真的没有,你看过**敖帅丙**的文章都要说有!
121 |
122 | **Tip**:但是说实话**顺序消费**这里很难介绍,我上周到这周问了很多身边的师兄开发过程中这样的场景不多,我跟三歪也讨论了几次,网上更多的都是介绍binlog的同步,好像更多的场景就没了。
123 |
124 | 一般都是**同个业务场景下不同几个操作的消息同时过去**,本身顺序是对的,但是你发出去的时候同时发出去了,消费的时候却乱掉了,这样就有问题了。
125 |
126 | 我之前做电商活动也是有这样的例子,我们都知道数据量大的时候数据同步压力还是很大的,有时候数据量大的表需要同步几个亿的数据。(并不是主从同步,主从延迟大的话会有问题,可能是从数据库或者主数据库同步到**备库**)
127 |
128 | 这种情况我们都是怼到队列里面去,然后慢慢消费的,那问题就来了呀,我们在数据库同时对一个Id的数据进行了增、改、删三个操作,但是你消息发过去消费的时候变成了改,删、增,这样数据就不对了。
129 |
130 | 本来一条数据应该删掉了,结果在你那却还在,这不是**出大问题**!
131 |
132 | 
133 |
134 | 两者的结果是不是完全不一样了 **↑**
135 |
136 | ### 那你怎么解决呢?
137 |
138 | 我简单的说一下我们使用的**RocketMQ**里面的一个简单实现吧。
139 |
140 | **Tip**:为啥用**RocketMQ**举例呢,这玩意是阿里开源的,我问了下身边的朋友很多公司都有使用,所以读者大概率是这个的话我就用这个举例吧,具体的细节我后面会在**RocketMQ**和**Kafka**各自章节说到。
141 |
142 | 生产者消费者一般需要保证顺序消息的话,可能就是一个业务场景下的,比如订单的创建、支付、发货、收货。
143 |
144 | 那这些东西是不是一个订单号呢?一个订单的肯定是一个订单号的说,那简单了呀。
145 |
146 | **一个topic下有多个队列**,为了保证发送有序,**RocketMQ**提供了**MessageQueueSelector**队列选择机制,他有三种实现:
147 |
148 | 
149 |
150 | 我们可使用**Hash取模法**,让同一个订单发送到同一个队列中,再使用同步发送,只有同个订单的创建消息发送成功,再发送支付消息。这样,我们保证了发送有序。
151 |
152 | **RocketMQ**的topic内的队列机制,可以保证存储满足**FIFO**(First Input First Output 简单说就是指先进先出),剩下的只需要消费者顺序消费即可。
153 |
154 | **RocketMQ**仅保证顺序发送,顺序消费由消费者业务保证!!!
155 |
156 | 这里很好理解,一个订单你发送的时候放到一个队列里面去,你同一个的订单号Hash一下是不是还是一样的结果,那肯定是一个消费者消费,那顺序是不是就保证了?
157 |
158 | 真正的顺序消费不同的中间件都有自己的不同实现我这里就举个例子,大家思路理解下。
159 |
160 | **Tip**:我写到这点的时候人才群里也有人问我,一个队列有序出去,一个消费者消费不就好了,我想说的是**消费者是多线程**的,你消息是有序的给他的,你能保证他是有序的处理的?还是一个消费成功了再发下一个**稳妥**。
161 |
162 | ### 你能跟我聊一下分布式事务么?
163 |
164 | **分布式事务**在现在遍地都是分布式部署的系统中几乎是必要的。
165 |
166 | 我们先聊一下啥是**事务**?
167 |
168 | **分布式事务**、**事务隔离级别**、**ACID**我相信大家这些东西都耳熟能详了,那什么是事务呢?
169 |
170 | #### 概念:
171 |
172 | > **一般是指要做的或所做的事情。**
173 | >
174 | > 在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。
175 | >
176 | > 事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序用户程序的执行所引起,并用形如**begin transaction**和**end transaction**语句(或函数调用)来界定。
177 | >
178 | > 事务由事务开始(**begin transaction**)和事务结束(**end transaction**)之间执行的全体操作组成。
179 |
180 | #### 特性:
181 |
182 | > 事务是恢复和并发控制的基本单位。
183 | >
184 | > 事务应该具有4个属性:**原子性、一致性、隔离性、持久性**。这四个属性通常称为**ACID特性**。
185 | >
186 | > **原子性(atomicity)**:一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
187 | >
188 | > **一致性(consistency)**:事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
189 | >
190 | > **隔离性(isolation)**:一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
191 | >
192 | > **持久性(durability)**:**持久性也称永久性(permanence)**,指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
193 |
194 | 那有同学还是不理解,敖丙我总结了一下就是:**事务就是一系列操作,要么同时成功,要么同时失败。**然后会从事务的 **ACID** 特性**(原子性、一致性、隔离性、持久性)展开叙述**。
195 |
196 | 事务就是为了保证一系列操作可以正常执行,它必须同时满足 **ACID** 特性。
197 |
198 | ### 那什么是分布式事务呢?
199 |
200 | 大家可以想一下,你下单流程可能涉及到10多个环节,你下单付钱都成功了,但是你优惠券扣减失败了,积分新增失败了,前者公司会被薅羊毛,后者用户会不开心,但是**这些都在不同的服务怎么保证大家都成功呢**?
201 |
202 | 聪明,**分布式事务**,你看你都会抢答了!
203 |
204 | **Tip**:真实的应用场景可能比我介绍的场景复杂数倍,我只是为了举例方便一下大家理解所以用了很简单的例子。
205 |
206 | 我接触和了解到的分布式事务大概分为:
207 |
208 | - 2pc(两段式提交)
209 | - 3pc(三段式提交)
210 | - TCC(Try、Confirm、Cancel)
211 | - 最大努力通知
212 | - XA
213 | - 本地消息表(ebay研发出的)
214 | - 半消息/最终一致性(RocketMQ)
215 |
216 | 这里我就介绍下最简单的**2pc(两段式)**,以及大家以后可能比较常用的**半消息事务**也就是**最终一致性**,目的是让大家理解下分布式事务里面**消息中间件的作用**,别的事务都大同小异,都有很多优点。
217 |
218 | 当然也都有**种种弊端**:
219 |
220 | 例如**长时间锁定数据库资源**,导致系统的**响应不快**,**并发上不去**。
221 |
222 | 网络抖动出现**脑裂**情况,导致事物参与者,不能很好地执行协调者的指令,导致**数据不一致**。
223 |
224 | **单点故障**:例如事物协调者,在某一时刻宕机,虽然可以通过选举机制产生新的Leader,但是这过程中,必然出现问题,而TCC,只有强悍的技术团队,才能支持开发,**成本太高**。
225 |
226 | 不多BB了,我们开始介绍这个两个事物吧。
227 |
228 | **2pc(两段式提交)** :
229 |
230 | 
231 |
232 | **2pc(两段式提交)**可以说是分布式事务的最开始的样子了,像极了**媒婆**,就是通过消息中间件协调多个系统,在两个系统操作事务的时候都锁定资源但是不提交事务,等两者都准备好了,告诉消息中间件,然后再分别提交事务。
233 |
234 | **但是我不知道大家看到问题所在没有?**
235 |
236 | 是的你可能已经发现了,如果A系统事务提交成功了,但是B系统在提交的时候网络波动或者各种原因提交失败了,其实还是会失败的。
237 |
238 | **最终一致性**:
239 |
240 | 
241 |
242 | 整个流程中,我们能保证是:
243 |
244 | - 业务主动方本地事务提交失败,业务被动方不会收到消息的投递。
245 |
246 | - 只要业务主动方本地事务执行成功,那么消息服务一定会投递消息给下游的业务被动方,并最终保证业务被动方一定能成功消费该消息(消费成功或失败,即最终一定会有一个最终态)。
247 |
248 | 不过呢技术就是这样,**各种极端的情况我们都需要考虑**,也很难有完美的方案,所以才会有这么多的方案**三段式**、**TCC**、**最大努力通知**等等分布式事务方案,大家只需要知道为啥要做,做了有啥好处,有啥坏处,在实际开发的时候都注意下就好好了,**系统都是根据业务场景设计出来的,离开业务的技术没有意义,离开技术的业务没有底气**。
249 |
250 | 还是那句话:**没有最完美的系统,只有最适合的系统。**
251 |
252 | ##面试结束
253 |
254 | ### 小伙子看不出来啊,还是有点东西的嘛,这几个点都回答的不错,明天你能跟我聊一下RocketMQ么?
255 |
256 | 敖丙这章花了这么多时间,不确定他写不写的完,心疼他。好想给他**点赞**啊,**消息回溯**也在单独介绍消息中间件的时候介绍吧,这章篇幅有点长了。
257 |
258 | ## 总结
259 |
260 | 这章其实我写的时间**比之前的秒杀还要久**,因为**顺序消息这个场景**我不知道怎么讲出来大家容易懂一点,最后就参考了网上的,顺序消息的实际应用场景没别的那么广泛,跟3y也聊了好几次,最后定了这个binlog的场景。
261 |
262 | 总之就是**这期创作源泉有点枯竭**,这章是真的难写,包括分布式事务在实际开发过程中也是很复杂的环节,需要用的时候光是做设计都要很久,反正我的流程图长得一匹。
263 |
264 | 我每次都想着写得**通俗易懂**一点,这篇即使是这样我觉得还是不够通俗易懂,但是消息的场景就是这样,还有大家加我也不要一上来就问我很多扣细节的点,**自己多点思考我觉得可能帮助比我告诉你答案好很多吧**?
265 |
266 | ## 絮叨
267 |
268 | 敖丙我呀,这周**有牌面**哟,上了**CSDN**的原力计划榜单,而且奖金高达50块!!!
269 |
270 | 
271 |
272 | 钱不多但是很开心,跟老妈聊到她也觉得我出息了,刚好她生日,以前我们这一家人就是那种不过生日的,不过呀今年我工作了,而且**有牌面**的我拿了的奖金就很关键,偷偷叫表弟悄悄去给她买了蛋糕和礼物🎁,嘻嘻,开心。🎂
273 |
274 | ### DISS
275 |
276 | 
277 |
278 | 这是**博客园的一个网友**在我文章下面的评论,说实话不知道**大家怎么看**的,我只想说:呵呵!傻*
279 |
280 | 我不知道这个多年的经验到底是怎么样子的多年的经验,我本来其实不准备说出来的,因为我发现我群里很多都是还没毕业的**大学生**或者**应届生**,那就假设我读者还有很多这样的学生,他们都**没社会经验**我怕他们被这样的人给误导了。
281 |
282 | 我记得我在群里说过:
283 |
284 | 
285 |
286 | 我可以80%肯定的告诉大家他这个观点就是扯淡,还有那20%我是**认同他的谦虚那个观点**,但是**谦虚难道不应该是我们对待事物最基本的态度嘛?**
287 |
288 | 但是**面试装傻**这个观点?还有什么**不会要比你强的人**这个观点?技术人我相信也有面试官也在看我的文章,你们在面试的时候,我想遇到厉害的人巴不得招入麾下,为自己冲锋陷阵吧。
289 |
290 | 而且**正常面试**的时候你是1-3年的经验,面试你的基本上都是3年以上的,然后依次顺推,当然也有很多很厉害的Leader(我前东家Leader95年的,字节跳动某产品线很强的Leader96的等等)等大家工作了你就会发现有些东西**没有时间积累**是学不到的,你要做的只是一步一个脚印踏实走好就好了。
291 |
292 | 那些人不管年轻与否能坐在那面试你**肯定有他的原因**,那你有什么才华,你**尽情施展**,他没那个度量包容你的优秀,这样的公司不去也罢,但是技术人这样的真的很少,程序员是一群很崇拜能力的人。
293 |
294 | 所以**面试你有啥都秀出来,把你的才华尽情的展示出来,风就在那,你只管飞翔。**
295 |
296 | ## 鸣谢
297 |
298 | 涉及到分布式事务的环节我参考了前大神同事:**鲁班**(花名)的技术分享,很感谢他的文章给的思路,还有问题的解析!
299 |
300 | 
301 |
302 | 每次写我都会在群里问大家,下次大家都在我的交流群里面也可以多给我点意见,谢谢了。
303 |
304 | 
305 |
306 | 看到没,就很民主。(敖丙你个渣男,呸,自己不会就不写!)
307 |
308 | **Tip**: **GItHub** [https://github.com/JavaFamily](https://github.com/AobingJava/JavaFamily) 上有进群方式和个人联系方式,说实话在这个群,哪怕您不说话,光看聊天记录,都能学到东西(美团王炸,三歪(Java3y),并夕夕等的大佬都在)。
309 |
310 | ## 日常求赞
311 |
312 | 好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是**人才**。
313 |
314 | 我每周都会更新几篇《吊打面试官》系列和互联网常用技术栈相关的文章,非常感谢**人才**们能看到这里,如果这个文章写得还不错,觉得「敖丙」我**有点东西**的话 **求点赞👍** **求关注❤️** **求分享👥** 对暖男我来说真的 **非常有用**!!!
315 |
316 | 创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!
317 |
318 | 敖丙 | 文 【原创】【转载请联系本人】 如果本篇博客有任何错误,请批评指教,不胜感激 !
319 |
320 | ------
321 |
322 | > 《吊打面试官》系列每周持续更新,可以关注我的公众号「 **JavaFamily** 」第一时间阅读和催更(公众号比博客早一到两篇哟),本文**GitHub**上已经收录[https://github.com/JavaFamily](https://github.com/AobingJava/JavaFamily),有一线大厂面试点思维导图,欢迎Star和完善,里面也有我个人联系方式有什么问题也可以直接找我,也有人才交流群,我们一起有点东西。
323 |
324 | 
--------------------------------------------------------------------------------
/docs/coderLife/记一次差点害敖丙丢工作的的线上P0事故.md:
--------------------------------------------------------------------------------
1 | > 你知道的越多,你不知道的越多
2 |
3 | > 点赞再看,养成习惯
4 |
5 | > **GitHub** [https://github.com/JavaFamily](https://github.com/AobingJava/JavaFamily)上已经收录有一线大厂面试点脑图、个人联系方式和技术交流群,欢迎Star和指教
6 |
7 | ## 前言
8 |
9 | 这是帅丙真实事件,大家都知道很多公司都是有故障等级这么一说的,这就是敖丙在公司背的P0级故障,敖丙差点因此**被解雇**,事情经过**十分惊心动魄**,我的**心脏病都差点复发**。
10 |
11 | > 事故等级主要针对生产环境,划分依据类似于bug等级。
12 | >
13 | > P0属于最高级别事故,比如崩溃,页面无法访问,主流程不通,主功能未实现,或者在影响面上影响很大(即使bug本身不严重)。
14 | >
15 | > P1事故属于高级别事故,一般属于主功能上的分支,支线流程,核心次功能等,后面还有P2,P3等,主要根据企业实际情况划分。
16 |
17 |
18 |
19 | ### 正文
20 |
21 | 敖丙之前也负责公司的商品搜索业务,因为业务体量增速太快了,商品表中的商品数据也很快跃入千万级别,查询的RT(response time 响应时间)也越来越高了,而且产品说需要根据**更多维度去查询商品**。
22 |
23 | 因为之前我们都是根据商品的名称去查询的,但是电商其实都会根据很多个维度去查询商品。
24 |
25 | 就比如大家去淘宝的查询的时候就会发现,你搜商品名称、颜色、标签等等多个维度都可以找到这个商品,就比如下图的搜索,我只是搜了【**帅丙**】你会发现,名字里面也没有连续的帅丙两个字,有帅和丙的出来了
26 |
27 | 
28 |
29 | 大家知道的传统的关系型数据库都是用什么 name like %帅丙% 这样的方式查询的,而且查询出来的结果肯定只能是name里面带帅丙的对吧。
30 |
31 | 那你还想搜别的字段比如什么尺寸、关键词、价格等等,都能搜到帅丙,这相当于是多个维度的了,传统的关系型数据库做不到呀。
32 |
33 | 做技术选型的时候,帅丙第一时间想到了搜索引擎。
34 |
35 | 当时市面是比较流行的有:**Apache Lucene**、**Elasticsearch**、**Solr**
36 |
37 | 搜索引擎我后面会讲**ELK(Elasticsearch、Logstash、Kibana)**和**Canal**,我呀真的是太宠你们了,这样会不会把你们惯坏了。
38 |
39 | 帅丙我呀,噼里啪啦一顿操作,最后得出结论:
40 |
41 | > 相对来讲,如果考虑静态搜索,Sorl相对更合适。
42 | >
43 | > 如果考虑实时,涉及到分布式,Elasticsearch相对合适。
44 |
45 | 那我们商品还是要实时的呀,你后台改了价格啥的,是不是都要实时同步出去,不然不是炸了嘛。
46 |
47 | 看到这,我想**可爱的你**和帅丙心中都有了答案:Elasticsearch这是个神一样的引擎。
48 |
49 | 我这里就做一个简单的介绍就好了,细节的点我们后面去他的章节讲,啥都写了,敖丙哪里有这么多素材写文章?
50 |
51 | > ElasticSearch是一个基于Lucene的搜索服务器。
52 | >
53 | > 它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。
54 | >
55 | > Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。
56 | >
57 | > ElasticSearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和许多其他语言中都是可用的。
58 | >
59 | > 根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。
60 |
61 | 看过敖丙之前文章的朋友都知道,我们做技术选型之前,要做什么呀,**设计**!
62 |
63 | 我们要去了解这玩意的**好处**、**坏处**、**常见的坑**、**出了问题的应急预案**等等,还有他的**数据同步机制**啊,**持久化机制啥**的,就是高可用嘛。
64 |
65 | 同样的我不大篇幅介绍了,以后都会写的嘛,我就给大家看看我当时做的设计吧。
66 |
67 | 
68 |
69 | 
70 |
71 | **这个只是最初的demo,详细的终稿我就不给大家看了,因为有很多公司内部的逻辑。**
72 |
73 | **不过大家还是可以看到敖丙真的考虑了很多,还是那句话,不打没把握的仗!**
74 |
75 | 设计做好敖丙就**卡卡卡**的用起来了。
76 |
77 | 说实话,**真香**,这玩意真的好用,学习成本也很低,查询语句分分钟掌握了,官网文档把功能介绍得清晰无比。
78 |
79 | > https://www.elastic.co/cn/
80 |
81 | 用着用着重头戏来了,你们都知道敖丙我是做电商活动的,都是什么很高的流量打进来这样,还是如往常一样上线了一个活动。
82 |
83 | **这是一个月飞风高的夜晚,丝丝凉风迎面吹来,敖丙悠闲的坐在椅子上,手里拿着破旧的茶杯,喝着外婆炒的苦荆茶,享受着这惬意的时光。**
84 |
85 | 突然,说时迟那时快,运维打来了紧急电话ES集群CPU打到了99%要挂了,**我的心蓦然一痛**,心里还在庆幸还是集群没崩。
86 |
87 | 然后他接着说了一句,不好集群挂了!
88 |
89 | 敖丙卒,本篇完....
90 |
91 | 
92 |
93 | 开玩笑的哈,不过当时敖丙真的**要死的心真的都要有了**,就在崩掉的1分钟内,就有用户反馈搜索未响应,我第一时间想到的就是重启,于是我一个健步冲出去,开启电脑,进机器,输入了重启命令。
94 |
95 | 好了,是的好了,还好有惊无险,不过只过了10秒,集群又99%了,呐呢?
96 |
97 | 
98 |
99 | 我又只能重启了,这次没挂,过了很久很久,直到活动结束,还是没挂。
100 |
101 | ### 查找问题
102 |
103 | 但是这次影响到线上,3分钟的搜索未响应,我想我估计明天是要去财务领工资,提前回家过年了。
104 |
105 | **还好Leader说没事**,先找到问题,把他修复掉。
106 |
107 | 你们都知道敖丙天才来的,我第一时间想到的就是看日志,我登上去看es没报错,再看本身的服务,除了超时的错误啥都没有,卧槽,是的当时我脑袋嗡嗡响。
108 |
109 | 不过我继续想为啥是我的搜索挂了,**会不会是有人搜了什么奇怪的东西?**
110 |
111 | 我打开了我的搜索日志!!!
112 |
113 | 卧槽这不是吧,哪个坑爹玩意搜这么长的一串中文,差不多250个字吧。
114 |
115 | 但是我一想,搜这么长也不应该打挂服务啊,**会不会是我写了bug**!
116 |
117 | 我脸颊流下一滴汗水💦,我看了看周围,发现没人注意到我的紧张,我**故作镇定**的把它擦掉。
118 |
119 | 我仔细一想,别人查询虽然长,就算查数据库也没事啊,为啥es就报错了?会不会?
120 |
121 | 
122 |
123 |
124 |
125 | **Es有Bug!没错肯定是Es的锅。**
126 |
127 | 那为啥会这样呢,我直接跟老大这样解释也好像不行啊,**还是要被开除的吧!**
128 |
129 | 于是我去看看看代码,我在关键词使用了通配符,我当时是为了匹配更多内容才这么做的,类似数据库的like,Es的通配符就是: * 帅丙 * 这样**在关键词前后加“*”号去查询**。
130 |
131 | 后面我发现就是通配符的锅,那**柯南丙**就说一下为啥会这样的问题出现。
132 |
133 | 许多有RDBMS/SQL背景的开发者,在初次踏入ElasticSearch世界的时候,很容易就想到使用通配符(Wildcard Query)来实现模糊查询(比如用户输入补全),因为这是和SQL里like操作最相似的查询方式,用起来感觉非常舒适。
134 |
135 | 然而帅丙的故障就揭示了,**滥用Wildcard query可能带来灾难性的后果**。
136 |
137 | 我当时首先复现了问题
138 |
139 | ### 复现方法
140 |
141 | 1. 创建一个只有一条文档的索引
142 |
143 | > POST test_index/type1/?refresh=true
144 | >
145 | > {
146 | >
147 | > "foo": "bar"
148 | >
149 | > }
150 |
151 | 2.使用wildcard query执行一个首尾带有通配符*的长字符串查询
152 |
153 | > POST /test_index/_search
154 | >
155 | > {
156 | >
157 | > "query": {
158 | >
159 | > "wildcard": {
160 | >
161 | > "foo": {
162 | >
163 | > "value": "轻轻的我走了,正如我轻轻的来;我轻轻的招手,作别西天的云彩。那河畔的金柳,是夕阳中的新娘;波光里的艳影,在我的心头荡漾。软泥上的青荇,油油的在水底招摇;在康河的柔波里,我甘心做一条水草!那榆荫下的一潭,不是清泉,是天上虹;揉碎在浮藻间,沉淀着彩虹似的梦。寻梦?撑一支长篙,向青草更青处漫溯;满载一船星辉,在星辉斑斓里放歌。但我不能放歌,悄悄是别离的笙箫;夏虫也为我沉默,沉默是今晚的康桥!悄悄的我走了,正如我悄悄的来;我挥一挥衣袖,不带走一片云彩。"
164 | >
165 | > }
166 | >
167 | > }
168 | >
169 | > }
170 | >
171 | > }
172 |
173 | 3. 查看结果
174 |
175 | > {
176 | >
177 | > "took": 3445,
178 | >
179 | > "timed_out": false,
180 | >
181 | > "_shards": {
182 | >
183 | > "total": 5,
184 | >
185 | > "successful": 5,
186 | >
187 | > "failed": 0
188 | >
189 | > },
190 | >
191 | > "hits": {
192 | >
193 | > "total": 0,
194 | >
195 | > "max_score": null,
196 | >
197 | > "hits":
198 | >
199 | > }
200 | >
201 | > }
202 |
203 | 
204 |
205 | **即使no hits**,耗时却是惊人的3.4秒 (测试机是macbook pro, i7 CPU),并且执行过程中,CPU有一个很高的尖峰。
206 |
207 | 
208 |
209 | **线上的查询比我这个范例要复杂得多**,会同时查几个字段,实际测试下来,一个查询可能会执行十几秒钟。
210 |
211 | 再有比较多长字符串查询的时候,集群可能就DOS了。
212 |
213 | ### 探查深层次根源
214 |
215 | 为什么对只有一条数据的索引做这个查询开销这么高? 直觉上应该是瞬间返回结果才对!
216 |
217 | 回答这个问题前,可以再做个测试,如果继续加大查询字符串的长度,到了一定长度后,ES直接抛异常了,服务器ES里异常给出的cause如下:
218 |
219 | > Caused by: org.apache.lucene.util.automaton.TooComplexToDeterminizeException: Determinizing automaton with 22082 states and 34182 transitions would result in more than 10000 states. at org.apache.lucene.util.automaton.Operations.determinize(Operations.java:741) ~[lucene-core-6.4.1.jar:6.4.1
220 |
221 | 解释:该异常来自org.apache.lucene.util.automaton这个包,异常原因的字面含义是说“**自动机过于复杂而无法确定状态: 由于状态和转换太多,确定一个自动机需要生成的状态超过10000个上限**"
222 |
223 | **柯南丙**网上查找了大量资料后,终于搞清楚了问题的来龙去脉。
224 |
225 | 为了加速通配符和正则表达式的匹配速度,Lucene4.0开始会将输入的字符串模式构建成一个DFA (Deterministic Finite Automaton),带有通配符的pattern构造出来的DFA可能会很复杂,**开销很大**。
226 |
227 | 比如a*bc构造出来的DFA就像下面这个图一样:
228 |
229 | 
230 |
231 | ### Lucene构造DFA的实现
232 |
233 | 看了一下Lucene的里相关的代码,构建过程大致如下:
234 |
235 | 1. org.apache.lucene.search.WildcardQuery里的toAutomaton方法,遍历输入的通配符pattern,将每个字符变成一个自动机(automaton),然后将每个字符的自动机链接起来生成一个新的自动机。
236 |
237 | ```java
238 | public static Automaton toAutomaton(Term wildcardquery) {
239 | List276 | \* Worst case complexity: exponential in number of states. 277 | \* @param maxDeterminizedStates Maximum number of states created when 278 | \* determinizing. Higher numbers allow this operation to consume more 279 | \* memory but allow more complex automatons. Use 280 | \* DEFAULT_MAX_DETERMINIZED_STATES as a decent default if you don't know 281 | \* how many to allow. 282 | \* @throws TooComplexToDeterminizeException if determinizing a creates an 283 | \* automaton with more than maxDeterminizedStates 284 | */ 285 | ``` 286 | 287 | 代码注释里说这个过程的时间复杂度最差情况下是状态数量的指数级别! 288 | 289 | 为防止产生的状态过多,消耗过多的内存和CPU,类里面对最大状态数量做了限制 290 | 291 | ```java 292 | /** 293 | * Default maximum number of states that {@link Operations#determinize} should create. 294 | */ 295 | public static final int DEFAULT_MAX_DETERMINIZED_STATES = 10000; 296 | ``` 297 | 298 | 在有首尾通配符,并且字符串很长的情况下,这个determinize过程会产生大量的state,甚至会超过上限。 299 | 300 | 至于NFA和DFA的区别是什么? 如何相互转换? 301 | 302 | 网上有很多数学层面的资料和论文,限于帅丙算法方面有限的知识,无精力去深入探究。 303 | 304 | 但是一个粗浅的理解是: NFA在输入一个条件的情况下,可以从一个状态转移到多种状态,而DFA只会有一个确定的状态可以转移,因此DFA在字符串匹配时速度更快。 305 | 306 | **DFA虽然搜索的时候快,但是构造方面的时间复杂度可能比较高,特别是带有首部通配符+长字符串的时候。** 307 | 308 | 回想Elasticsearch官方文档里对于Wildcard query有特别说明,**要避免使用通配符开头的term**。 309 | 310 | > " Note that this query can be slow, as it needs to iterate over many terms. In order to prevent extremely slow wildcard queries, a wildcard term should not start with one of the wildcards * or ?." 311 | 312 | 结合对上面Wildcard query底层实现的探究,也就不难理解这句话的含义了! 313 | 314 | **小结: Wildcard query应杜绝使用通配符打头,实在不得已要这么做,就一定需要限制用户输入的字符串长度。** 315 | 316 | 最好换一种实现方式,通过在index time做文章,选用合适的分词器,比如nGram tokenizer预处理数据,然后使用更廉价的term query来实现同等的模糊搜索功能。 317 | 318 | 对于部分输入即提示的应用场景,可以考虑优先使用completion suggester, phrase/term suggeter一类性能更好,模糊程度略差的方式查询,待suggester没有匹配结果的时候,再fall back到更模糊但性能较差的wildcard, regex, fuzzy一类的查询。 319 | 320 | **补充**: 有同学问regex, fuzzy query是否有同样的问题,答案是有,原因在于他们底层和wildcard一样,都是通过将pattern构造成DFA来加速字符串匹配速度的。 321 | 322 | **回忆**:为啥之前挂了一次重启恢复了,马上又挂了?用户搜了两次。。。 323 | 324 | ### 解决方案 325 | 326 | 其实解决这种问题很简单,既然知道关键词长了会有问题,我就**做限制**嘛,大家可以去看看搜索引擎某度、某宝啥的,是不是都做了长度限制? 327 | 328 | 我复制了很长的一段汉字进去百度就是这个结果咯,某宝过长都返回**默认页面**了。 329 | 330 | 331 | 332 |  333 | 334 |  335 | 336 | 如果你的产品一定要给用户一点东西,简单,找出一些热词分析出来就好了,或者给点热搜商品**兜底**。 337 | 338 | 我怎么做的呢?判断字符串长度大于50我就直接返回空数组了,这样对用户体验好点,你返回个参数错误或者默认错误别人还**以为你有Bug**呢对吧。 339 | 340 | ### 总结 341 | 342 | 其实敖丙我啥事故等级都没背哈哈,这个算是事故,但是敖丙我这么可爱,领导也心疼我啊,肯定不会怪我的拉,主要是我设计都考虑了很多方案和场景了,没想到有这个坑。(yy:敖丙你个渣男,又是标题党,人家还以为你没工作了要养你呢!) 343 | 344 | 大家也可以通过这次事故体会到,技术选型的时候,**方案的重要性**了吧,就算你考虑不全,但是不至于真正的问题来了手足无措啊,并不是所有的事故都可以像这次这样重启就搞定了,**不要存有侥幸心理,心存敬畏**。 345 | 346 | ### 絮叨 347 | 348 | 敖丙啊,又有牌面了,得到**阿里云消息中间件团队**小伙伴的认可,并且发现居然是我学姐-**风云**(花名)!!! 349 | 350 | 她是个好学的小姐姐,大家多多像优秀的仔学习,学姐不是做技术的,但是都在不断学习,说实话我的眼角又湿了。 351 | 352 |  353 | 354 | ### 别跑,投票!!! 355 | 356 | 我准备把我的公众号**JavaFamily** 这个名字改了,这个名字还是差点意思,但是又不能叫敖丙了,被注册商标了,我就问了下群里的人才,目前有两个我比较喜欢的 357 | 358 | - **帅丙** 359 | - **三太子敖丙** 360 | - 其他给我留言 361 | 362 | 因为这个可能会陪伴我很久,甚至直到死去,希望大家都给点建议哈哈。 363 | 364 | 别问我为啥要跟敖丙这个名字相关,**再问自杀**! 365 | 366 | 我花名就叫这个,所以😂 367 | 368 |  369 | 370 | 371 | 372 | ## 日常求赞 373 | 374 | 好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是**人才**。 375 | 376 | 我后面会每周都更新几篇一线互联网大厂面试和常用技术栈相关的文章,非常感谢**人才**们能看到这里,如果这个文章写得还不错,觉得「敖丙」我**有点东西**的话 **求点赞👍** **求关注❤️** **求分享👥** 对暖男我来说真的 **非常有用**!!! 377 | 378 | 创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见! 379 | 380 | 敖丙 | 文 【原创】【转载请联系本人】 如果本篇博客有任何错误,请批评指教,不胜感激 ! 381 | 382 | ------ 383 | 384 | > 文章每周持续更新,可以关注我的公众号「 **JavaFamily** 」第一时间阅读和催更(公众号比博客早一到两篇哟),本文**GitHub** [https://github.com/JavaFamily](https://github.com/AobingJava/JavaFamily) 上已经收录,有一线大厂面试点思维导图,欢迎Star和完善,里面也有我个人联系方式有什么问题也可以直接找我,也有**技术交流群**,我们一起有点东西。 385 | 386 | 387 | 书三千,吾全取。 388 | 389 | 人千万,独暖你。 ---暖男敖丙 -------------------------------------------------------------------------------- /docs/creative/顶级程序员的百宝箱.md: -------------------------------------------------------------------------------- 1 | > 2 | > 3 | > 你知道的越多,你不知道的越多 4 | 5 | > 点赞再看,养成习惯 6 | 7 | > **GitHub**上已经开源 [https://github.com/JavaFamily](https://github.com/AobingJava/JavaFamily) 有一线大厂面试点脑图、个人联系方式和人才交流群,欢迎Star和指教 8 | 9 | ## 前言 10 | 11 | 这期是被人才群交流里,还有很多之前网友评论强行顶出来的一期,就是让我介绍自己常用的一些工具给他们安利一下,我一听很高兴呀,帅丙我这么乐于奉献的人是吧。 12 | 13 | 主要是能水一篇文章就很开心,不过写下来发现花的时间完全不比写技术少,**点赞**!!! 14 | 15 | 千万不要白嫖,**真香警告**⚠️。 16 | 17 | 但是我在构思这篇文章的时候发现我贴个标题,然后发下软件信息会不会太乏味了,于是创作鬼才我呀,准备用一个产品的研发流程,是的就是**用这样的一个思路**去写这个工具集的介绍文章。 18 | 19 | 因为读者很多还是学生,还有很多应届生,对一个需求的研发流程都不是很熟悉,还有可能对于以后自己需要使用到的工具都不是很熟悉,那我就一一罗列一下,帅丙我作为一个还算有点小经验的程序员都使用哪些工具呢? 20 | 21 | 那下面就跟随**暖男**的脚步,走进**顶级程序员的百宝箱**吧(我所有的标题都是噱头就为了夸大其词,我是低级程序员,大家看了也不能吊打面试官,笑笑就好了)。 22 | 23 | **注意**:下面的软件我都是简单的介绍下是干啥的,因为太多了,真正的功能需要大家深挖的,能力允许的朋友下载正版,破解方法去Github [https://github.com/JavaFamily](https://github.com/AobingJava/JavaFamily) 加我回复【**软件**】就好了。 24 | 25 | ## 正文 26 | 27 | 既然都说了**帅丙**是要用一个产品的研发流程角度去介绍软件,那我们先看看一个产品有哪些研发流程,帅丙就用自己接触的阿里系的研发流程举例了,这也基本上是互联网大厂的研发流程了,可能细节有出入,但是绝对大同小异。 28 | 29 |  30 | 31 | **Tip**:我从开发的视角去介绍的话我就会**跳过一些**软件,比如提出需求这个其实一般都是文档类的,**wiki**呀这样的形式。 32 | 33 | 我就不介绍那种流程工具了,公司很多自研的,大家工作了再去熟悉也很快的。 34 | 35 | ### 概要设计: 36 | 37 | **概要设计**,这个是大厂程序员需求下来之后基本上都会做的一步,不过看需求大小,可能很多小需求直接就**详细设计了**。 38 | 39 | 很多不了解的同学可能会问,需要设计什么呢?为什么要设计呢? 40 | 41 | 问得好,经常看我文章的都知道,**技术是把双刃剑**,你用了技术之后你是不是需要**列出他的优点缺点**,出问题之后的**解决方案**,还有**可能出现的问题**,**注意点**等等。 42 | 43 | 这么是为了让你能有把控力,比如你用了个**Es**(**Elasticsearch**)你什么都不管你就是要接入它,你把他开发好了上线了,但是有啥坑你知道么?上线崩了怎么办? 44 | 45 | 帅丙我做**Es**设计的时候设计被老大打回N次,不过成长真心大,对**Es**的了解也飞速进步。 46 | 47 | 其实远远不止这些问题,这就是我们做设计的主要原因,也是大家工作里面能成长的途径之一,你以为大佬们的经验是怎么来的? 48 | 49 | ##### 工具:Xmind/ProcessOn 50 | 51 | - Xmind官网地址: [https://www.xmind.cn](https://www.xmind.cn/) 52 | - ProcessOn**在线作图**地址:[https://www.processon.com](https://www.processon.com/i/5c349823e4b0db2e592c4847) 53 | 54 | > 我这里列举了两个工具,他们两个都可以做概要设计的脑图,我给大家看看我设计过的一些脑图,都是出自这两个软件。 55 | 56 |  57 | 58 | 大家在学习,看书等等的时候做个脑图,我告诉你后面你复习还是干啥都**思路贼清晰**,而且**效率**瞬间**高**很多。 59 | 60 | ### 详细设计 61 | 62 | 小伙伴又要问了啥是详细设计呀**帅丙**? 63 | 64 | 诶呀简单,见名知意嘛,概要设计是大概的设计,详细设计是详细的设计。 65 | 66 | 我们研发的时候整个流程往往很复杂,如果你理解不对直接就写代码,最后容易造成返工,延期,加班,被骂,心情差,回家吵架,离家出走。。。 67 | 68 | **看到不做详细设计的后果了吧**,其实大家花点时间做详细设计很有必要,你思路完全清晰了,写代码那就是分分钟的事情,不是嘛? 69 | 70 | 那再看看帅丙的一个小设计吧,之前文章中大量的流程图,时序图都来自它,**主要是这玩意还是在线的,都不用下载很方便啊。** 71 | 72 | 详细设计的工具我用的就是**在线**作图神器:**ProcessOn** 73 | 74 | - 在线画图地址:[https://www.processon.com](https://www.processon.com/i/5c349823e4b0db2e592c4847) 75 | 76 | > 总之一句话很香,流程图、思维导图、原型图、UML、网络拓扑图、组织结构图、BPMN等等一应俱全 77 | 78 |  79 | 80 | ### Ascilflow 81 | 82 | - 官网地址: [http://asciiflow.com](http://asciiflow.com/) 83 | 84 | > 进入网站后直接开画!网页上端是菜单,自行操作! 85 | 86 |  87 | 88 | 89 | 90 | ### 研发 91 | 92 | 这个关键了:**工欲善其事,必先利其器** 93 | 94 | 想必大家都知道这个谚语吧,我就说一下我写代码要用到的软件吧。 95 | 96 | #### Intellij IDEA 97 | 98 | - 官网地址 : [http://www.jetbrains.com/idea](http://www.jetbrains.com/idea/) 99 | 100 | > 这个我想都不用我介绍了吧,Java的同学都耳熟能详了,有同学问为啥不用eclipse呀,我不作回答,但是我只能告诉你IDEA肯定是效率还有很多方面都要香的。 101 | > 102 | > 不过看个人习惯的哈,新同学还是推荐IDEA!!! 103 | 104 |  105 | 106 | #### WebStorm 107 | 108 | - 官网地址 : [http://www.jetbrains.com/webstorm](http://www.jetbrains.com/webstorm/) 109 | 110 | > 有知道同学要问了,帅丙这不是前端的开发工具么,为啥你要用,帅丙我呀全才来的呀,前端偶尔也写点的嘛,主要是js,vue,jq,还有丢丢React,不过最近帮三歪改前端居然是jsx有没有大佬救救我啊。 111 | 112 |  113 | 114 | ### Visual Studio Code 115 | 116 | - 官网地址:[https://code.visualstudio.com](https://code.visualstudio.com/) 117 | 118 | > Visual Studio Code是一个**轻量且强大的跨平台开源**代码编辑器(IDE),支持Windows,OS X和Linux。内置JavaScript、TypeScript和Node.js支持,而且拥有丰富的插件生态系统,可通过安装插件来支持C++、C#、Python、PHP等其他语言。 119 | 120 |  121 | 122 | #### PyCharm 123 | 124 | - 官网地址 :[http://www.jetbrains.com/pycharm](http://www.jetbrains.com/pycharm/) 125 | 126 | > 这个是python之前那次还记得我写代码大赛那期嘛,最开始就是用这个写的,平时学的时候也用用。 127 | 128 |  129 | 130 | #### Navicat Premium 131 | 132 | - 官网地址 :[https://www.navicat.com.cn](https://www.navicat.com.cn/) 133 | 134 | > 这个呀是数据库的可视化工具很香很好用,不过我们线上的表都是网页操作的,这个只能用来看看本地的开发表了,不过也是很有必要的,你SQL怎么都得本地跑一下没问题,才向DBA申请的嘛。 135 | 136 |  137 | 138 | #### Postman 139 | 140 | - 官网地址 :[https://www.getpostman.com](https://www.getpostman.com/) 141 | 142 | > 这个是接口调试的神器,单测比较繁琐的你可以试试这个嘛,不过很多接口还是只能写写单测,反正很香。 143 | > 144 | > 不过这个名字一看就是男生用的,那我们女生用啥呢?往下看 145 | 146 |  147 | 148 | #### Postwoman 149 | 150 | - 官网地址 :[https://postwoman.io](https://postwoman.io/) 151 | 152 | > PostMan一听就是男生用的,咋妹子们肯定要用最近开源的Postwoman啊,它是一款开源的 Postman 替代品 153 | > 154 | > 155 | > 156 | > 开源没多久优点如下: 157 | > 158 | > - 轻盈,可直接在线访问; 159 | > - 简约,采用简约的 UI 设计精心打造; 160 | > - 支持 GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH 方法; 161 | > - 支持验证; 162 | > - 实时,发送请求即可获取响应。 163 | 164 |  165 | 166 | #### GIt 167 | 168 | - 官网地址 :[https://git-scm.com](https://git-scm.com/) 169 | 170 | > 代码文档管理工具,版本控制工具,大家之后的代码基本上都是使用git做版本管理 171 | 172 |  173 | 174 | #### Maven 175 | 176 | - 官网地址 :[http://maven.apache.org](http://maven.apache.org/) 177 | 178 | > 目前帅丙用到Maven的主要功能是:项目构建、项目构建、项目依赖管理、软件项目持续集成、版本管理、项目的站点描述信息管理 179 | 180 |  181 | 182 | #### Gradle 183 | 184 | - 官网地址 :[https://gradle.org](https://gradle.org/) 185 | 186 | > Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。 187 | > 188 | > 它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,目前也增加了基于Kotlin语言的kotlin-based DSL,抛弃了基于XML的各种繁琐配置。 189 | > 190 | > 这个跟Maven功能是一样的,但是两者语法不一样,而且我觉得版本控制的时候没Maven好使,有小坑,胜在语法简洁。 191 | 192 |  193 | 194 | #### Charles 195 | 196 | - 官网地址 :[https://www.charlesproxy.com](https://www.charlesproxy.com/) 197 | 198 | > 这玩意是个HTTP代理服务器,我用它的主要用法就是抓包! 199 | > 200 | > 都知道我是做电商的嘛,很多线上接口线上问题怎么排查呢,抓包看看数据呗。 201 | 202 |  203 | 204 | #### JMeter 205 | 206 | - 官网地址 :[https://jmeter.apache.org](https://jmeter.apache.org/) 207 | 208 | > Apache JMeter是Apache组织开发的基于Java的压力测试工具 209 | > 210 | > 是的就是用来压测的,你怎么模拟很多请求呀,就用它就对了。 211 | 212 |  213 | 214 | #### Dash 215 | 216 | - 官网地址 :[https://kapeli.com/dash](https://kapeli.com/dash) 217 | 218 | > Dash for mac是使用与Mac OS平台的软件编程文档管理工具,可以浏览API文档,以及管理代码片段工具。Dash自带了丰富的API文档,涉及各种主流的编程语言和框架。 219 | 220 |  221 | 222 | #### Devdocs 223 | 224 | - 官网地址:[https://devdocs.io](https://devdocs.io) 225 | 226 | > 上面那个的兄弟,但是这个不用下载,在线的 227 | 228 |  229 | 230 | #### DataGrip 231 | 232 | - 官网地址 :[http://www.jetbrains.com/datagrip](http://www.jetbrains.com/datagrip/) 233 | 234 | > DataGrip是JetBrains公司推出的管理数据库的产品,对于JetBrains公司,开发者肯定都不陌生,IDEA和ReSharper都是这个公司的产品,用户体验非常不错。 235 | > 236 | > 最开始我用它就单纯看同事在用很酷的界面,后面发现功能也香,高亮文本啥的,很多功能大家可以去挖。 237 | 238 |  239 | 240 | #### JVisualVM 241 | 242 | - 官网地址 :[http://visualvm.github.io](http://visualvm.github.io/) 243 | 244 | > VisualVM 是Netbeans的profile子项目,已在JDK6.0 update 7 中自带,能够监控线程,内存情况,查看方法的CPU时间和内存中的对 象,已被GC的对象,反向查看分配的堆栈(如100个String对象分别由哪几个对象分配出来的)。 245 | > 246 | > VisualVM可以根据需要安装不同的插件,每个插件的关注点都不同,有的主要监控GC,有的主要监控内存,有的监控线程等。 247 | 248 |  249 | 250 | #### Iterm2 251 | 252 | - 官网地址 :https://www.iterm2.com/ 253 | 254 | > 这个是我做日志排查的客户端工具,也是支持很多配置,直接ssh上跳板机查看线上机器的状态等等,线上问题排查还是很有必要的。 255 | 256 |  257 | 258 | #### 网*有道词典 259 | 260 | - 官网地址 :[http://www.youdao.com](http://www.youdao.com/) 261 | 262 | > 有朋友要疑问了帅丙这是什么情况,鬼畜乱入么? 263 | > 264 | > 不是的,我们研发的时候很多单词不认识,或者命名的时候这个词汇的英文不知道还是很有必要查一下的,规范的命名是你成为顶级大牛的第一步,你命名都是A,B,C你代码review的时候,你的Leader会叫hr让你提交前回家过年的,马上过年了大家不要轻易尝试。 265 | 266 |  267 | 268 | #### Sublime Text 269 | 270 | - 官网地址 :[http://www.sublimetext.com](http://www.sublimetext.com/) 271 | 272 | > 这是个文本记录的工具,也可以用于写代码,但是我们有IDE了那就用来当日常琐事记录的工具,临时文档处理的工具也是可以的,反正还是很好用的。 273 | 274 |  275 | 276 | 277 | 278 | ### 刚好最近呀人才群里的人才们都叫我安利一下我做笔记还有写博客的工具,说我排版好看。(我飘了) 279 | 280 | 安排! 281 | 282 | #### 印象笔记 283 | 284 | - 官网地址 :[https://www.yinxiang.com](https://www.yinxiang.com/) 285 | 286 | > 这个可以说是陪伴我大学到现在的一个工具了吧,我数了下,上千文件了,我的生活琐事的记录,还有学编程之后的很多东西,我都是收录在里面的。 287 | > 288 | > 这个东西我就不和别的笔记比较了,因为我最开始就用的这个一直没换过,好不好用我说了不算的,大家下一个看看就知道了。 289 | 290 |  291 | 292 | #### Typora 293 | 294 | - 官网地址 :[https://www.typora.io](https://www.typora.io/) 295 | 296 | > Typora是我一直写Markdown的工具,好用到不行,还可以切换模式你敢信?打字机模式,专注模式,源码模式总有一个你的菜. 297 | 298 |  299 | 300 | #### Ipic 301 | 302 | - 官网地址 :[https://ipic.ca](https://ipic.ca/) 303 | 304 | > 图床我是配合Typora一起使用的大家Markdown是不是复制图片进来都是本地的地址,发到网上就会失效的,但是跟Typora搞基的这个工具他可以在你复制进来的时候直接传到网上了,你再去任何平台发表都可以随心所欲了。 305 | 306 |  307 | 308 | #### Md2All 309 | 310 | - 官网地址 :[http://md.aclickall.com](http://md.aclickall.com/) 311 | 312 | > 大家好奇我的markdown怎么这么好看呀,其实我写了markdown之后还转成了html的,用的也就是上面这个工具。 313 | > 314 | > 我写完也是在这里面进行排版然后发出去的,排版要花好久,忍不住给帅丙**点赞**。 315 | 316 |  317 | 318 | ### 图像处理 319 | 320 | #### Adobe Photoshop CC 2019 321 | 322 | - 官网地址 :[https://www.adobe.com/cn/products/photoshop](https://www.adobe.com/cn/products/photoshop.html?promoid=PC1PQQ5T&mv=other) 323 | 324 | > Ps嘛大家都知道的,正常的图片处理啊用这个香,没事帮美女P下图,搞不好能找个女朋友(我又开始YY了) 325 | 326 |  327 | 328 | 329 | 330 | #### Adobe Premiere Pro CC 2019 331 | 332 | - 官网地址 :[https://www.adobe.com/products/premiere](https://www.adobe.com/products/premiere.html?promoid=PQ7SQBYQ&mv=other) 333 | 334 | > 这个可能是大家使用得最多的视频处理软件了吧,很好用!!! 335 | > 336 | > 功能全到无法令人呼吸,缺点就是学习成本有点大,入门很快,想成为大神需要大量时间积累。 337 | 338 |  339 | 340 | #### Adobe After Effects CC 2019 341 | 342 | - 官网地址 :[https://www.adobe.com/cn/products/aftereffects](https://www.adobe.com/cn/products/aftereffects/free-trial-download.html) 343 | 344 | > 不知道大家视频看得多么,很多视频的特效开场都是这个做的,下面也有一个我的demo。 345 | 346 |  347 | 348 | ##  349 | 350 | #### GIPHY CAPTURE 351 | 352 | - 官网地址 :[https://giphy.com/apps/giphycapture](https://giphy.com/apps/giphycapture) 353 | 354 | > 有时候大家文章不想用静态的图画去表达,想录制写代码的Gif动图,那这个软件是真的好使。 355 | 356 |  357 | 358 | #### 视频播放 KMPlayer 359 | 360 | - 官网地址 :[http://www.kmplayer.com](http://www.kmplayer.com/) 361 | 362 | > 其实帅丙我心中有个播放神器的,快播。 363 | > 364 | > 可惜了还没用多久,播播就夭折了,我会使用下面这个播放软件去播放我自己的视频。 365 | > 366 | > 因为很多格式电脑自带的可能不支持,我又喜欢剪辑视频,所以一直用它了。 367 | 368 |  369 | 370 | #### Iina 371 | 372 | - 官网地址:[https://www.iina.io](https://www.iina.io/) 373 | 374 | > 视频播放 同上 375 | 376 |  377 | 378 | #### DouTu 379 | 380 | - 官网地址 : [https://www.52doutu.cn/maker/1/?order=timedown](https://www.52doutu.cn/maker/1/?order=timedown) 381 | 382 | >大家是不是发现我之前的文章很多表情包,其实都是在线制作的。 383 | 384 |  385 | 386 | #### Carbon 387 | 388 | - 官网地址 :[https://carbon.now.sh/](https://carbon.now.sh/) 389 | 390 | > 帅丙之前的文章里面很多代码的图片都是这个网站生成的,很多样式可以选择,就很好看。 391 | 392 |  393 | 394 | #### CodeLF 395 | 396 | - 官网地址 :[https://unbug.github.io/codelf](https://unbug.github.io/codelf/#帅丙) 397 | 398 | > 这个网站有意思了,写代码不知道单词怎么命名就去这里查,他是GItHub的一个爬虫工具吧,看看大神的命名总是会有思路的吧。 399 | 400 |  401 | 402 | **注意**:上面的软件我都是简单的介绍下是干啥的,因为太多了,真正的功能需要大家深挖的,能力允许的朋友下载正版,破解方法去Github [https://github.com/JavaFamily](https://github.com/AobingJava/JavaFamily) 加我回复【**软件**】就好了。 403 | 404 | ## 总结 405 | 406 | 其实比较香的工具还有太多了,我这里就不一一介绍了,其实有个很简单的办法,就是**问**,**学习**,**借鉴**。 407 | 408 | 我就是这样的,我看Leader用的什么工具我就问他这是啥,好用不?怎么用? 409 | 410 | 包括我写博客吧,其实才写了20多天,第一天准备写的时候我就直接问**三歪(Java3y)**,你用的什么开发工具呀,怎么用的呀,包括他主要发布的哪些平台呀,发布的时间段呀,我都直接问。 411 | 412 | 他坐我对面,**迫于我的淫威**不得不和盘托出,主要是最近有个需求需要我帮他写代码哈哈。 413 | 414 | 别人都这么多的经验下来了,软件**能差嘛**?而且使用过程中不会的**还可以问一下对方**,不香嘛。 415 | 416 | ## 絮叨 417 | 418 | 先看**人才交流群**的某个人才提的问题: 419 | 420 |  421 | 422 | **Tip**: **GItHub** [https://github.com/JavaFamily](https://github.com/AobingJava/JavaFamily) 上有进群方式和个人联系方式,说实话在这个群,哪怕您不说话,光看聊天记录,都能学到东西(美团王炸,三歪(Java3y),并夕夕等的大佬都在)。 423 | 424 | 不知道大家是否还记得我之前写的幂等这样的情况? 425 | 426 | 就是下图这样的情况,我下单增减GMV先去看看这个流水有么,有就证明加过了,就直接返回,没有才继续下面的流程。 427 | 428 |  429 | 430 | 他其实提的问题很好,因为我们日常开发都是**主从同步,读写分**离的,就是说我们可能加GMV加了但是我们操作的是主库,他需要将数据同步到从库,但是这个过程中他发生了延迟。 431 | 432 | 那这个时候如果别的系统这个**订单号消息重试**了,你是不是又进来了,你去查询流水你发现没流水你以为没加,你执行加钱的操作,结果那条延迟的也好了,是不是就加了两次。 433 | 434 | 正常开发中确实会有,但是主从延迟这个应该让**DBA**(**数据库管理员 Database Administrator**)去考虑的,但是呢我说过不能写有逻辑漏洞的代码嘛,其实很简单,把他放Redis嘛,设置一个30分钟左右的时间,这期间的重复消费都可以避免,要是延迟超过30分钟了那其实问题已经很大了,DBA会知道的。 435 | 436 | **这篇是吐血整理,大家好好食用,记得点个赞!👍** 437 | 438 | ## 日常求赞 439 | 440 | 好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是**人才**。 441 | 442 | 我后面会每周都更新几篇《吊打面试官》系列和互联网常用技术栈相关的文章,非常感谢**人才**们能看到这里,如果这个文章写得还不错,觉得「敖丙」我**有点东西**的话 **求点赞👍** **求关注❤️** **求分享👥** 对暖男我来说真的 **非常有用**!!! 443 | 444 | 创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见! 445 | 446 | 敖丙 | 文 【原创】【转载请联系本人】 如果本篇博客有任何错误,请批评指教,不胜感激 ! 447 | 448 | ------ 449 | 450 | > 《吊打面试官》系列每周持续更新,可以关注我的公众号「 **JavaFamily** 」第一时间阅读和催更(公众号比博客早一到两篇哟),本文**GitHub**上已经收录[https://github.com/JavaFamily](https://github.com/AobingJava/JavaFamily),有一线大厂面试点思维导图,欢迎Star和完善,里面也有我个人联系方式有什么问题也可以直接找我,也有人才交流群,我们一起有点东西。 451 | -------------------------------------------------------------------------------- /docs/idea/电子书.md: -------------------------------------------------------------------------------- 1 | 计算机类的书籍那么贵,作为一个几个小时看完一本书且机不离身的程序员,天天买纸质书是不可能的了,所以对电子书的需求量还是挺多的。为了方便广大的小伙伴也能方便找到对应的电子书,我花费洪荒之力收集了几百本常用的电子书,并且为了解决百度云链接容易失效的问题,我把电子书全部下载打包上传,都有哪些电子书呢?请往下看。 2 | 3 | 4 | > **重要说明**:**如果目录无法跳转的话,直接拉下去就可以了**,这些书籍都是在同一个页面的,我只是方便大家找到对应的,弄了一个**页内目录**,不过有部分读者反馈他跳转不了(手机是绝对跳转不了的了)。 5 | 6 | 7 | 8 | - [数据结构与算法相关书籍](#数据结构与算法相关书籍) 9 | - [计算机基础](#计算机基础) 10 | - [操作系统](#操作系统) 11 | - [汇编语言](#汇编语言) 12 | - [计算机网络](#计算机网络) 13 | - [计算机组成原理](#计算机组成原理) 14 | - [Python](#python) 15 | - [1、Python基础](#1python基础) 16 | - [2、数据分析与爬虫](#2数据分析与爬虫) 17 | - [Linux](#linux) 18 | - [C语言](#c语言) 19 | - [C ](#c) 20 | - [前端](#前端) 21 | - [人工智能](#人工智能) 22 | - [设计模式](#设计模式) 23 | - [Java](#java) 24 | - [Java 基础](#java-基础) 25 | - [Java进阶](#java进阶) 26 | - [JavaWeb](#javaweb) 27 | - [数据库](#数据库) 28 | - [Go](#go) 29 | - [中间件](#中间件) 30 | - [面试相关](#面试相关) 31 | - [未分类书籍](#未分类书籍) 32 | - [Git](#git) 33 | - [没找到请看这里](#没找到请看这里) 34 | - [免责声明](#免责声明) 35 | 36 | 37 | 38 | # 数据结构与算法相关书籍 39 | 40 | - 挑战程序设计竞赛 [百度云下载链接](https://pan.baidu.com/s/1diObrFpHKm4r-XyTp4cGAQ) 密码:mxn7 41 | - Java数据结构和算法 [百度云下载链接](https://pan.baidu.com/s/1vD9CQVwnWMfqSaEmn8Dudw ) 密码:lpym 42 | - 算法图解 [百度云下载链接](https://pan.baidu.com/s/1NFiwO-_Kzt-VxXxxteRCTA) 密码:7osf 43 | - 算法导论 [百度云下载链接](https://pan.baidu.com/s/1WHmnchIdy0FvMWLImPoIhQ) 密码:p2tp 44 | - 算法第四版 [百度云下载链接](https://pan.baidu.com/s/1WEliUJ_hQhl-OzWPtXcFdQ) 密码:rixw 45 | - 数据结构与算法分析C语言描述版 [百度云下载链接](https://pan.baidu.com/s/1v4OsTTCd5SyC4WGarHZdcA) 密码:mn10 46 | - 数据结构与算法分析Java语言描述版 [百度云下载链接](https://pan.baidu.com/s/1hZGhkErn9Bc17ZnN_ilgAw) 密码:917n 47 | - 数据结构与算法 Python语言描述_裘宗燕 [百度云下载链接](https://pan.baidu.com/s/1VjlQugLPIiN91bmISkJ3xg) 密码:96gw 48 | - 剑指offer [百度云下载链接](https://pan.baidu.com/s/1lUs2fVqxNMK8OOUrVSBCmw) 密码:a4rt 49 | - 计算机程序设计艺术1-3卷 [百度云下载链接](https://pan.baidu.com/s/1rxEqkKAogFpy1aNQnXUyBw) 密码:i3nh 50 | - 大话数据结构 [百度云下载链接](https://pan.baidu.com/s/1fTxelwIZa8pBmdnMW8PFYg) 密码:np2o 51 | - 程序员代码面试指南:IT 名企算法与数据结构题目最优解 [百度云下载链接](https://pan.baidu.com/s/1DhjBLEiORLRTiffpJnJq_g) 密码:20oh 52 | - 编程珠玑 [百度云下载链接](https://pan.baidu.com/s/1ix17W5-CG4r5Wn8bF3erVQ) 密码:4oow 53 | - 编程之美 [百度云下载链接](https://pan.baidu.com/s/1y8SWiLipsKEzCulyxdbgGQ) 密码:4zme 54 | - 啊哈算法 [百度云下载链接](https://pan.baidu.com/s/1S6OTJlQtywaRvu4IA_ogCw) 密码:h4id 55 | - 程序员的算法趣题 [百度云下载链接](https://pan.baidu.com/s/1iIHm0kRlfwck3IQn-BUZZA) 密码:kk84 56 | 57 | # 计算机基础 58 | 59 | ### 操作系统 60 | 61 | - 30天填自制操作系统 [百度云下载链接](https://pan.baidu.com/s/1QSIUlat1HpllNFMWY9WBzw) 密码:pxxr 62 | - 操作系统之哲学原理 [百度云下载链接](https://pan.baidu.com/s/1GEfALJhtJ2IJtjtKcLneKg) 密码:hua7 63 | - 程序是怎样跑起来的 [百度云下载链接](https://pan.baidu.com/s/1i_xDxT8QgA_x4kRHXEmPqg) 密码:pbvh 64 | - 深入理解计算机操作系统 [百度云下载链接](https://pan.baidu.com/s/1xrDC6wGAH7Yv3uuXzVUWxg) 密码:2toh 65 | - 现代操作系统 [百度云下载链接](https://pan.baidu.com/s/1QA0VZ20pA8giW6ax7AHQBA) 密码:huk2 66 | 67 | 68 | 69 | ### 汇编语言 70 | 71 | - 汇编语言(注:这边是王爽写的,我觉得写的很好,适合入门) [百度云下载链接](https://pan.baidu.com/s/1kZLH0dW6Y37S-WCLNV309A) 密码:qea3 72 | 73 | ### 计算机网络 74 | 75 | - 计算机网络:自顶向下 [百度云下载链接](https://pan.baidu.com/s/18X_L2RINmtLK9g0Ki2GiFw) 密码:l77d 76 | - 图解HTTP [百度云下载链接](https://pan.baidu.com/s/1NEAK2PH_4JzPY454QvmmsQ) 密码:b42z 77 | - 图解TC/IP [百度云下载链接](https://pan.baidu.com/s/1FJru4ppyxBhx_J3pk8rpvA) 密码:5k3x 78 | - 网络是怎样连接的 [百度云下载链接](https://pan.baidu.com/s/1HhE9MoC4rp5NSvyWOtk_hw) 密码:g983 79 | - HTTP权威指南 [百度云下载链接](https://pan.baidu.com/s/1b2fIsmdt9ANVMcqU97t6kw) 密码:tqj8 80 | - UNIX网络编程 [百度云下载链接](https://pan.baidu.com/s/1vXbj7OLsouVFH4DCIMqF3w) 密码:4buy 81 | 82 | ### 计算机组成原理 83 | 84 | - 隐匿在计算机软硬件背后的语言 [百度云下载链接](https://pan.baidu.com/s/1gJCnChBTCZD07mm3IqCRwQ) 密码:6jiq 85 | - 大话计算机 [百度云下载链接](https://pan.baidu.com/s/1AakpZmD8hziokFnV0VSGFA) 密码:6j1o 86 | - 计算机是怎样跑起来的 [百度云下载链接](https://pan.baidu.com/s/1JIq3U8kNYohz0C3xnCk6EA) 密码:er12 87 | 88 | 89 | 90 | 91 | 92 | # Python 93 | 94 | ### 1、Python基础 95 | 96 | - 编程小白的第一本Python入门书 [百度云下载链接](https://pan.baidu.com/s/128kxkHLrEAidlMt0E80SUg) 密码:s76b 97 | - Python编程初学者指南 [百度云下载链接](https://pan.baidu.com/s/1ytNZt1VMlbyREyc1L7ShYA) 密码:g696 98 | - Python高级编程 [百度云下载链接](https://pan.baidu.com/s/1-ItrNDj2R9Z-S1ZuEMlf1Q) 密码:qnuf 99 | - Python高性能编程 [百度云下载链接](https://pan.baidu.com/s/10wPoXPM83so2WvdlVnPZTw) 密码:d8s5 100 | - Python灰帽子 [百度云下载链接](https://pan.baidu.com/s/17hvNff7O5OsdRAB3_mBBcg) 密码:nfkt 101 | - Python开发技术详解 [百度云下载链接](https://pan.baidu.com/s/1cTVhr9BEmy79GbKq41qQ5A) 密码:z0av 102 | - Python开发实战 [百度云下载链接](https://pan.baidu.com/s/1AFgXTjEQyBf6SP2CCniA1A) 密码:ee5x 103 | - Python网络编程基础 [百度云下载链接](https://pan.baidu.com/s/1qBpXTD3Ll6p2KAv0RAkKHQ) 密码:m15q 104 | - Python学习手册 [百度云下载链接](https://pan.baidu.com/s/18DsRhIawELjVGGDSTRvhYA) 密码:0yqf 105 | - 精通Scrapy网络爬虫 106 | 107 | ### 2、数据分析与爬虫 108 | 109 | - 数据科学入门 [百度云下载链接](https://pan.baidu.com/s/1LBUGeGdjUNhCUUOZRpgbrg) 密码:1hz8 110 | - 用Python写网络爬虫 [百度云下载链接](https://pan.baidu.com/s/1ENi8Y4vAMqSQviPYNRBMUA) 密码:nlpa 111 | - Python数据处理 [百度云下载链接](https://pan.baidu.com/s/1UOOC1APb6fueaxDyyshMuQ) 密码:8eom 112 | - Python数据分析实战 [百度云下载链接](https://pan.baidu.com/s/13yQ4hvUf4EzgGAuKQUM4ag) 密码:idn1 113 | - Python数据科学手册 [百度云下载链接](https://pan.baidu.com/s/1Y1KnyILg-0ZWJbIKNzNsmw) 密码:16u0 114 | - Python数据可视化编程实战 [百度云下载链接](https://pan.baidu.com/s/1BKIzCFI_5CzLXAQpRQCp8Q) 密码:i7hp 115 | - 精通Scrapy网络爬虫 [百度云下载链接](https://pan.baidu.com/s/1FuAE8Kq3YItoO4yNba5ckA) 密码:jb6u 116 | 117 | # Linux 118 | 119 | - 精通正则表达式 [百度云下载链接](https://pan.baidu.com/s/1tt-S2QEye0qZde_3SiG1Eg) 密码:vp94 120 | - 鸟哥的Linux私房菜基础篇和服务器篇 [百度云下载链接](https://pan.baidu.com/s/1ZvTMk23dKPbQG7siYXyrbg) 密码:ubg2 121 | - 深入Linux内核架构 [百度云下载链接](https://pan.baidu.com/s/15Vyl69xGDY_RkpQPk5qCCQ) 密码:fnh2 122 | - Linux宝典 [百度云下载链接](https://pan.baidu.com/s/1cQX4jgG0-7fYFuR5F9G2_g) 密码:nxhe 123 | - Linux常用命令大全 [百度云下载链接](https://pan.baidu.com/s/1WH7DFOzL25mOHsp5orrWmQ) 密码:e0n2 124 | - Linux防火墙 [百度云下载链接](https://pan.baidu.com/s/1NTMCysm_btHNpek38rBMfg) 密码:sc4u 125 | - Linux高级程序设计 [百度云下载链接](https://pan.baidu.com/s/11y7OBER2c9mcbsCtjTRsrA) 密码:d4wq 126 | - Linux环境编程 [百度云下载链接](https://pan.baidu.com/s/1sl-6GF3onLPRXeJDVedwqA) 密码:xudv 127 | - Linux命令详解词典 [百度云下载链接](https://pan.baidu.com/s/1CSlkxcBRBPsHHRYOrQpfSw) 密码:yxuz 128 | - 汇编语言基于linux环境第3版 [百度云下载链接](https://pan.baidu.com/s/13gwNQvvG5fRYxo83zMb2VA) 密码:yq75 129 | 130 | # C语言 131 | 132 | - 经典C程序100例 [百度云下载链接](https://pan.baidu.com/s/1fJnp014zqOCdO8O6gzcDUw) 密码:tls2 133 | - C Primer Plus [百度云下载链接](https://pan.baidu.com/s/1SuVacfN0q-MGeKs6Z-O2LQ) 密码:5s85 134 | - C程序设计语言(包括课后答案等) [百度云下载链接](https://pan.baidu.com/s/1ICTaU2avonev25DfykAr-w) 密码:cfj4 135 | - C和指针 [百度云下载链接](https://pan.baidu.com/s/11zphu-XC2YS57BkkKjAtoQ) 密码:d8a0 136 | - C语言编程精粹 [百度云下载链接](https://pan.baidu.com/s/1_GmhiP3jL0cQR36uAiZNNw) 密码:6mct 137 | - C语言参考手册 [百度云下载链接](https://pan.baidu.com/s/1hzINX8yDELZ4WF1ALwDsYg) 密码:4hnx 138 | - C语言函数大全 [百度云下载链接](https://pan.baidu.com/s/1_kM7pd1J6K65X6oC38AviA) 密码:xywt 139 | - C语言解析教程 [百度云下载链接](https://pan.baidu.com/s/1Sm-CRO8DzhT7gCgxNJkKfw) 密码:6luf 140 | - C语言深度剖析 [百度云下载链接](https://pan.baidu.com/s/1Dn4csGs7xEdZt9smdBcmbQ) 密码:yu63 141 | - C专家编程 [百度云下载链接](https://pan.baidu.com/s/1y_Uz1SWi1NikG0D0URqv0w) 密码:xlfm 142 | 143 | # C++ 144 | 145 | - C++ Primer [百度云下载链接](https://pan.baidu.com/s/1OvJd3JfxujySAs6Tqugl9g) 密码:js1a 146 | - C++编程思想 [百度云下载链接](https://pan.baidu.com/s/1p98_fU039F6Er3_CtnmIfQ) 密码:vi02 147 | - C++对象模型 [百度云下载链接](https://pan.baidu.com/s/1JVnJwxbTXe6HIMDFXlYnbQ) 密码:v90k 148 | - 深入探索C++对象模型 [百度云下载链接](https://pan.baidu.com/s/1NxvGvIBYpKNunjnu5ev_vw) 密码:3xuv 149 | - C++ Templates [百度云下载链接](https://pan.baidu.com/s/1bkQ-aPpFDc_osxqFC9I1Jw) 密码:4rvw 150 | - C++编程规范-101条规则准则与最佳实践 [百度云下载链接](https://pan.baidu.com/s/1PAfapM3g1YDNB2qpZlJnpg) 密码:t43e 151 | - C++沉思录中文第2版 [百度云下载链接](https://pan.baidu.com/s/1ckINRCEKKt3DJ9eg412EtA) 密码:6emr 152 | - C++大学教程 [百度云下载链接](https://pan.baidu.com/s/1OS5iWmRib0QvFOFaRMSpMw) 密码:n6ph 153 | - C++设计新思维-泛型编程与设计之应用 [百度云下载链接](https://pan.baidu.com/s/1zKojQCCfs0NPH_9ORpiBvA) 密码:0el5 154 | - Effective STL 中文版 [百度云下载链接](https://pan.baidu.com/s/1btF8iWfAXoEUo5A18SYaLw) 密码:u7s1 155 | - More Effective C++中文版 [百度云下载链接](https://pan.baidu.com/s/1I3uRE2s8n5OZRm_76a1Lag) 密码:xbxv 156 | - STL源码剖析 [百度云下载链接](https://pan.baidu.com/s/1DbnRAJgeAtmXo5tpuhc-rg) 密码:mxsh 157 | 158 | # 前端 159 | 160 | - 疯狂aJax讲义 [百度云下载链接](https://pan.baidu.com/s/1C1NdOCrYD6LULgbGtRp_Vw) 密码:pce0 161 | - Bootstrap实战 [百度云下载链接](https://pan.baidu.com/s/1ty1U6-XUDFqnjVS57IrZSA) 密码:rzhm 162 | - HTML5揭秘 [百度云下载链接](https://pan.baidu.com/s/138vuPiKZFIU0Zza80eui_g) 密码:vaam 163 | - HTML5与CSS3基础教程 [百度云下载链接](https://pan.baidu.com/s/1ddq73aQviPIM9ci6xhAt_g) 密码:2wxm 164 | - HTML与CSS入门经典 [百度云下载链接](https://pan.baidu.com/s/1fJaT9zqQOWxIB8Mkn_vQqQ) 密码:tsgm 165 | - JavaScript DOM编程艺术 [百度云下载链接](https://pan.baidu.com/s/1Dx3z3D9DYbWyebr3V86cLA) 密码:gsbt 166 | - JavaScript高级程序设计 [百度云下载链接](https://pan.baidu.com/s/1NYkMExeBSG1SBVfT7nUkWQ) 密码:wbw0 167 | - JavaScript高效图形编程 [百度云下载链接](https://pan.baidu.com/s/1jLPlJ1tpnF6LOkhhUgcF6w) 密码:tab1 168 | - jQuery高级编程 [百度云下载链接](https://pan.baidu.com/s/1XSvgFixfnm_9YxytuuSvLA) 密码:qwtr 169 | - jQuery技术内幕 [百度云下载链接](https://pan.baidu.com/s/11sUqBmGJWlHOB29WtZjf2A) 密码:pglf 170 | - jQuery权威指南 [百度云下载链接](https://pan.baidu.com/s/14Iu2h8BQ4oHXsyuKG9k-Qw) 密码:4vrw 171 | - Node.js开发指南 [百度云下载链接](https://pan.baidu.com/s/1cSoqtNHTrmoovTNy7VonqA) 密码:voze 172 | 173 | # 人工智能 174 | 175 | - 贝叶斯思维统计建模的Python学习法 [百度云下载链接](https://pan.baidu.com/s/1GX6Uqzh8-AzMv0UjO2Ed2A) 密码:ztbe 176 | - 机器学习实战 [百度云下载链接](https://pan.baidu.com/s/1ZDcgp1ht4XZPYH5Wy3I1KQ) 密码:cfqc 177 | - Python机器学习及实践 [百度云下载链接](https://pan.baidu.com/s/1IIUCLptUPsQvLRbUEqJaTA) 密码:qq3q 178 | - Tensorflow实战Google深度学习框架 [百度云下载链接](https://pan.baidu.com/s/1CJIJmNvZHx2rtkUDH-zrIg) 密码:12kj 179 | - TensorFlow实践与智能系统 [百度云下载链接](https://pan.baidu.com/s/1EYFAmV8z9hvTX06Hwf1MsA) 密码:e668 180 | - 深度学习_中文版 [百度云下载链接](https://pan.baidu.com/s/1FH9vlBBBb-yvB26eFmKjQw) 密码:01xp 181 | 182 | # 设计模式 183 | 184 | - 图解设计模式 [百度云下载链接](https://pan.baidu.com/s/16Lss7o-zu0_HNio6od4c0Q) 密码:g50a 185 | - 研磨设计模式 [百度云下载链接](https://pan.baidu.com/s/1a5EPImWzDfPGg1DQ4F7EkA) 密码:h5fb 186 | - Head First设计模式 [百度云下载链接](https://pan.baidu.com/s/1-rMyG6AuRHrzFF-dOiaBDw) 密码:pxpq 187 | 188 | # Java 189 | 190 | ### Java 基础 191 | 192 | - 阿里巴巴Java开发手册 [百度云下载链接](https://pan.baidu.com/s/1SoqPq0-x9aZPEaCiggVtUA) 密码:g6lv 193 | - 码出高效 [百度云下载链接](https://pan.baidu.com/s/1ejmKaxyd2ACKbV3lj9Vyvg) 密码:mbt9 194 | - Head First Java [百度云下载链接](https://pan.baidu.com/s/1AhFSveV6DE3nWMpBUhFcMw) 密码:d5ll 195 | - Java8实战 [百度云下载链接](https://pan.baidu.com/s/1ni-dF2XqmMFwI5pBPo3P2A) 密码:lvmb 196 | - Java编程思想 [百度云下载链接](https://pan.baidu.com/s/1cqF8lcDdMoV3g2OLxQCUKg) 密码:0add 197 | - Java并发编程的艺术 [百度云下载链接](https://pan.baidu.com/s/1N3aSnY8rZxQLTbnUwIk5yQ) 密码:vn74 198 | - Java并发编程实践 [百度云下载链接](https://pan.baidu.com/s/1Bk47A0tLXUv1wVQjJlxd6Q) 密码:i6w9 199 | - Java从小白到大牛 [百度云下载链接](https://pan.baidu.com/s/1qDLSzWrkSVu91KcrBN5fKQ) 密码:9auc 200 | - Java核心技术1-2卷 [百度云下载链接](https://pan.baidu.com/s/1t9YFSagCpVC7N4pK6aNuGQ) 密码:tr3s 201 | - 深入理解Java虚拟机 [百度云下载链接](https://pan.baidu.com/s/1qyRd-YANK1Czs51k1tWYWQ) 密码:b6op 202 | 203 | ### Java进阶 204 | 205 | - 代码大全 [百度云下载链接](https://pan.baidu.com/s/1ehGZsgt-Rl47pVnNGUKWWw) 密码:juhq 206 | - 代码整洁之道 [百度云下载链接](https://pan.baidu.com/s/1fQf91LpvIWeJ-HH2QWKVog) 密码:hzn2 207 | - 敏捷软件开发 [百度云下载链接](https://pan.baidu.com/s/1HveePOP4fOynad9yrHKS_A) 密码:mmi4 208 | - Effective Java(中文) [百度云下载链接](https://pan.baidu.com/s/1jvaEtd4H-ELdjY-I2uV76A) 密码:4dcx 209 | - Effective Java(英文) [百度云下载链接](https://pan.baidu.com/s/1FOVL661If9yaJSjTpMw22g) 密码:bhu4 210 | - Java性能优化权威指南 [百度云下载链接](https://pan.baidu.com/s/1XCOWv6W5_rsCUM6Q4YIU9Q) 密码:054x 211 | 212 | ### JavaWeb 213 | 214 | - 轻量级JavaEE企业应用实战 [百度云下载链接](https://pan.baidu.com/s/1EjBGj1z6sJ4kDokUZRG2IA) 密码:8j3c 215 | - 深入分析JavaWeb技术内幕 [百度云下载链接](https://pan.baidu.com/s/15Q_ZJZyOtm5gYhhp_D0OFA) 密码:31uu 216 | - 深入剖析Tomcat [百度云下载链接](https://pan.baidu.com/s/1YQXpaveUeRXxid1BdU-nUw) 密码:y1yt 217 | - Head First Servlet and JSP [百度云下载链接](https://pan.baidu.com/s/1036AnuSKhckNC_vqa5qjPw) 密码:v8b8 218 | - Maven实战 [百度云下载链接](https://pan.baidu.com/s/15DddRDQpR_KAOzg-HuuDvw) 密码:s0q9 219 | - Spring实战 [百度云下载链接](https://pan.baidu.com/s/1Y9J20oR38qVyQ4Z7Kh9KQw) 密码:40fb 220 | - Camel in Action [百度云下载链接](https://pan.baidu.com/s/1300e_-sgpqAzl_2H1EPlJA) 密码:plyn 221 | 222 | # 数据库 223 | 224 | - 高性能MySQL [百度云下载链接](https://pan.baidu.com/s/1_vXaan9KbIWAHEnyQnQFlg) 密码:gh5t 225 | - 深入浅出MySQL [百度云下载链接](https://pan.baidu.com/s/1gWJcwszv3CnjIRMzy--_rw) 密码:ju0h 226 | - MongoDB权威指南 [百度云下载链接](https://pan.baidu.com/s/1LO1ACpRDi7n0i9Q7nLooqg) 密码:llvx 227 | - MySQL必知必会 [百度云下载链接](https://pan.baidu.com/s/1IWeqx7IQGc0sY5bJ9WtyMA) 密码:f1v9 228 | - MySQL技术内幕InnoDB存储引擎 [百度云下载链接](https://pan.baidu.com/s/1fLL3GXn_Hp6DdEnHXcBFJQ) 密码:6g04) 229 | - SQL查询的艺术 [百度云下载链接](https://pan.baidu.com/s/1PfE3oLfmQN8Xtdj-08L--A) 密码:ndcv 230 | - SQLite 权威指南 [百度云下载链接](https://pan.baidu.com/s/1BqFp4W_I0Wwn87fKrCpB8A) 密码:ex3h 231 | 232 | # Go 233 | 234 | - 学习Go语言 [百度云下载链接](https://pan.baidu.com/s/1tNJJ-UNBk7nsZuxILFAy7w) 密码:5tri 235 | - Go语言实战 [百度云下载链接](https://pan.baidu.com/s/1BIGNOG3AfFAVrBnHeemPlQ) 密码:q0x3 236 | - Go web编程 [百度云下载链接](https://pan.baidu.com/s/1UQU7uWFSZb3ILob6b64ZeA) 密码:pyw3 237 | - C 程序设计语言第2版 [百度云下载链接](https://pan.baidu.com/s/14NmKpWeBQ-vg6XzyvXTaeg) 密码:3yza 238 | 239 | 240 | 241 | # 中间件 242 | 243 | * redis实战 [百度云下载链接](https://pan.baidu.com/s/13Y-Uk2HmV1Y5TLec4J20aQ) 密码:ro48 244 | 245 | 246 | 247 | # 面试相关 248 | 249 | - 阿里巴巴Java面试问题大全 [百度云下载链接](https://pan.baidu.com/s/1tbd8N88ae-O0xsm6RTJIag) 密码:8xzm 250 | - 程序员面试宝典 [百度云下载链接](https://pan.baidu.com/s/1LilCd-QIcVgZ1uQyFWMaWw) 密码:ko62 251 | - 大厂面试真题 [百度云下载链接](https://pan.baidu.com/s/1631WVa3Fhf2wOpdZX_ou2g) 密码:gu92 252 | - Java面试突击 [百度云下载链接](https://pan.baidu.com/s/1bAZS8KiUNF0lOt-R0UBOyg) 密码:h44t 253 | 254 | # 未分类书籍 255 | 256 | - 黑客与画家 [百度云下载链接](https://pan.baidu.com/s/1lEyXNK8W4a0vStIPHOihiA) 密码:uux2 257 | - 浪潮之巅 [百度云下载链接](https://pan.baidu.com/s/1NIeoGRy6s1lYB3WdlhA8lQ) 密码:xr66 258 | - 码农翻身 [百度云下载链接](https://pan.baidu.com/s/1zEmECfVe4rFRsQL8goN4nA) 密码:x0ik 259 | - 奔跑吧,程序员:从零开始打造产品、技术和团队 [百度云下载链接](https://pan.baidu.com/s/1O0QkDLuJMasimr9XZsNSmA) 密码:jxvj 260 | 261 | # Git 262 | 263 | - 快速入门Git [百度云下载链接](https://pan.baidu.com/s/1ka8s2-1h24LLX5ebeeU6WA) 密码:ofdd 264 | - 专业git中文 [百度云下载链接](https://pan.baidu.com/s/1pvgoGleexrvdMhnTgd0VYw) 密码:b3kx 265 | - Git参考手册 [百度云下载链接](https://pan.baidu.com/s/1DC8S-wnLrpanW2HRROizMQ) 密码:axou 266 | - 《Pro Git》中文版 [百度云下载链接](https://pan.baidu.com/s/1TLHL03vKY5gLs1tOjN5KeA) 密码:l05a 267 | 268 | 269 | 270 | # 没找到请看这里 271 | 272 | 别急,我会慢慢更新完善的,可能只是暂时没有而已,,,欢迎持续关注哦 273 | 274 | 275 | 276 | 277 | # 免责声明 278 | 279 | 书籍全部来源于网络其他人的整理,我这里只是收集整理了他们的链接,如有侵权,马上联系我,我立马删除对应链接。我的邮箱:aobing@mogu.com 280 | 281 | 282 | 283 | 284 | 285 | 286 | -------------------------------------------------------------------------------- /docs/all/缓存/redis/Redis常见面试题.md: -------------------------------------------------------------------------------- 1 | > 你知道的越多,你不知道的越多 2 | 3 | > 点赞再看,养成习惯 4 | 5 | > [**GitHub**](https://github.com/AobingJava/JavaFamily)上已经开源[https://github.com/Java...](https://github.com/AobingJava/JavaFamily),有面试点思维导图,欢迎[**Star**](https://github.com/AobingJava/JavaFamily)和[**完善**](https://github.com/AobingJava/JavaFamily) 6 | 7 | ## 前言 8 | 9 | **Redis**在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在**Redis**的使用和原理方面对小伙伴们进行360°的刁难。 10 | 11 | 作为一个在互联网公司面一次拿一次Offer的面霸,打败了无数竞争对手,每次都只能看到无数落寞的身影失望的离开,略感愧疚(**请允许我使用一下夸张的修辞手法**)。 12 | 13 | 于是在一个寂寞难耐的夜晚,我痛定思痛,决定开始写**《吊打面试官》**系列,希望能帮助各位读者以后面试势如破竹,对面试官进行360°的反击,吊打问你的面试官,让一同面试的同僚瞠目结舌,疯狂收割大厂Offer! 14 | 15 | ## 絮叨 16 | 17 | 上一期因为是在双十一一直在熬夜的大环境下完成的,所以我自己觉得质量明显没之前的好,我这不一睡好就加班加点准备补偿大家,来点干货。(熬夜太容易感冒了,这次**点个赞**别白嫖了!) 18 | 19 | 顺带提一嘴,我把我准备写啥画了一个思维导图,以后总不能每篇都放个贼大的图吧,就开源到了我的**[GitHub](https://github.com/AobingJava/JavaFamily)**,大家有兴趣可以去完善和**Star**。 20 | 21 | 这篇我就先放出来大家看看,感觉还是差点意思,等大家完善了。 22 | 23 |  24 | 25 | 26 | 27 | ## 回望过去 28 | 29 | 上一期吊打系列我们提到了**Redis**相关的一些知识,还没看的小伙伴可以回顾一下 30 | 31 | - **[《吊打面试官》系列-Redis基础](https://juejin.im/post/5db66ed9e51d452a2f15d833)** 32 | - **[《吊打面试官》系列-缓存雪崩、击穿、穿透](https://juejin.im/post/5dbef8306fb9a0203f6fa3e2)** 33 | - **[《吊打面试官》系列-Redis哨兵、持久化、主从、手撕LRU](https://juejin.im/post/5dc3a9fbf265da4d3c072eab)** 34 | - **[《吊打面试官》系列-Redis终章-凛冬将至、FPX-新王登基](https://juejin.im/post/5dc850b4e51d452c2308ee27)** 35 | 36 | 这期我就从缓存到一些常见的问题讲一下,有一些我是之前提到过的,不过可能大部分仔是第一次看,我就重复发一下。 37 | 38 | ### 缓存知识点 39 | 40 | ######  41 | 42 | 43 | 44 | ### 缓存有哪些类型? 45 | 46 | 缓存是高并发场景下提高热点数据访问性能的一个有效手段,在开发项目时会经常使用到。 47 | 48 | 缓存的类型分为:**本地缓存**、**分布式缓存**和**多级缓存**。 49 | 50 | #### 本地缓存: 51 | 52 | **本地缓存**就是在进程的内存中进行缓存,比如我们的 **JVM** 堆中,可以用 **LRUMap** 来实现,也可以使用 **Ehcache** 这样的工具来实现。 53 | 54 | 本地缓存是内存访问,没有远程交互开销,性能最好,但是受限于单机容量,一般缓存较小且无法扩展。 55 | 56 | #### 分布式缓存: 57 | 58 | **分布式缓存**可以很好得解决这个问题。 59 | 60 | 分布式缓存一般都具有良好的水平扩展能力,对较大数据量的场景也能应付自如。缺点就是需要进行远程请求,性能不如本地缓存。 61 | 62 | #### 多级缓存: 63 | 64 | 为了平衡这种情况,实际业务中一般采用**多级缓存**,本地缓存只保存访问频率最高的部分热点数据,其他的热点数据放在分布式缓存中。 65 | 66 | 在目前的一线大厂中,这也是最常用的缓存方案,单考单一的缓存方案往往难以撑住很多高并发的场景。 67 | 68 | ### 淘汰策略 69 | 70 | 不管是本地缓存还是分布式缓存,为了保证较高性能,都是使用内存来保存数据,由于成本和内存限制,当存储的数据超过缓存容量时,需要对缓存的数据进行剔除。 71 | 72 | 一般的剔除策略有 **FIFO** 淘汰最早数据、**LRU** 剔除最近最少使用、和 **LFU** 剔除最近使用频率最低的数据几种策略。 73 | 74 | - **noeviction**:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外) 75 | 76 | - **allkeys-lru**: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。 77 | 78 | - **volatile-lru**: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。 79 | 80 | - **allkeys-random**: 回收随机的键使得新添加的数据有空间存放。 81 | 82 | - **volatile-random**: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。 83 | 84 | - **volatile-ttl**: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。 85 | 86 | 如果没有键满足回收的前提条件的话,策略**volatile-lru**, **volatile-random**以及**volatile-ttl**就和noeviction 差不多了。 87 | 88 | 其实在大家熟悉的**LinkedHashMap**中也实现了Lru算法的,实现如下: 89 | 90 |  91 | 92 | 当容量超过100时,开始执行**LRU**策略:将最近最少未使用的 **TimeoutInfoHolder** 对象 **evict** 掉。 93 | 94 | 真实面试中会让你写LUR算法,你可别搞原始的那个,那真TM多,写不完的,你要么怼上面这个,要么怼下面这个,找一个数据结构实现下Java版本的LRU还是比较容易的,知道啥原理就好了。 95 | 96 |  97 | 98 | 99 | 100 | ### Memcache 101 | 102 | 注意后面会把 **Memcache** 简称为 MC。 103 | 104 | 先来看看 MC 的特点: 105 | 106 | - MC 处理请求时使用多线程异步 IO 的方式,可以合理利用 CPU 多核的优势,性能非常优秀; 107 | - MC 功能简单,使用内存存储数据; 108 | - MC 的内存结构以及钙化问题我就不细说了,大家可以查看[官网](http://www.memcached.org/about)了解下; 109 | - MC 对缓存的数据可以设置失效期,过期后的数据会被清除; 110 | - 失效的策略采用延迟失效,就是当再次使用数据时检查是否失效; 111 | - 当容量存满时,会对缓存中的数据进行剔除,剔除时除了会对过期 key 进行清理,还会按 LRU 策略对数据进行剔除。 112 | 113 | 114 | 115 | 另外,使用 MC 有一些限制,这些限制在现在的互联网场景下很致命,成为大家选择**Redis**、**MongoDB**的重要原因: 116 | 117 | - key 不能超过 250 个字节; 118 | - value 不能超过 1M 字节; 119 | - key 的最大失效时间是 30 天; 120 | - 只支持 K-V 结构,不提供持久化和主从同步功能。 121 | 122 | 123 | 124 | ### Redis 125 | 126 | 先简单说一下 **Redis** 的特点,方便和 MC 比较。 127 | 128 | - 与 MC 不同的是,Redis 采用单线程模式处理请求。这样做的原因有 2 个:一个是因为采用了非阻塞的异步事件处理机制;另一个是缓存数据都是内存操作 IO 时间不会太长,单线程可以避免线程上下文切换产生的代价。 129 | - **Redis** 支持持久化,所以 Redis 不仅仅可以用作缓存,也可以用作 NoSQL 数据库。 130 | - 相比 MC,**Redis** 还有一个非常大的优势,就是除了 K-V 之外,还支持多种数据格式,例如 list、set、sorted set、hash 等。 131 | - **Redis** 提供主从同步机制,以及 **Cluster** 集群部署能力,能够提供高可用服务。 132 | 133 | # 134 | 135 | ### 详解 Redis 136 | 137 | Redis 的知识点结构如下图所示。 138 | 139 | 140 | 141 |  142 | 143 | 144 | 145 | 146 | 147 | ### 功能 148 | 149 | 来看 **Redis** 提供的功能有哪些吧! 150 | 151 | #### 我们先看基础类型: 152 | 153 | #### **String:** 154 | 155 | **String** 类型是 **Redis** 中最常使用的类型,内部的实现是通过 **SDS**(Simple Dynamic String )来存储的。SDS 类似于 **Java** 中的 **ArrayList**,可以通过预分配冗余空间的方式来减少内存的频繁分配。 156 | 157 | 这是最简单的类型,就是普通的 set 和 get,做简单的 KV 缓存。 158 | 159 | 但是真实的开发环境中,很多仔可能会把很多比较复杂的结构也统一转成**String**去存储使用,比如有的仔他就喜欢把对象或者**List**转换为**JSONString**进行存储,拿出来再反序列话啥的。 160 | 161 | 我在这里就不讨论这样做的对错了,但是我还是希望大家能在最合适的场景使用最合适的数据结构,对象找不到最合适的但是类型可以选最合适的嘛,之后别人接手你的代码一看这么**规范**,诶这小伙子**有点东西**呀,看到你啥都是用的**String**,**垃圾!** 162 | 163 |  164 | 165 | 好了这些都是题外话了,道理还是希望大家记在心里,习惯成自然嘛,小习惯成就你。 166 | 167 | **String**的实际应用场景比较广泛的有: 168 | 169 | - **缓存功能:String**字符串是最常用的数据类型,不仅仅是**Redis**,各个语言都是最基本类型,因此,利用**Redis**作为缓存,配合其它数据库作为存储层,利用**Redis**支持高并发的特点,可以大大加快系统的读写速度、以及降低后端数据库的压力。 170 | 171 | - **计数器:**许多系统都会使用**Redis**作为系统的实时计数器,可以快速实现计数和查询的功能。而且最终的数据结果可以按照特定的时间落地到数据库或者其它存储介质当中进行永久保存。 172 | 173 | - **共享用户Session:**用户重新刷新一次界面,可能需要访问一下数据进行重新登录,或者访问页面缓存**Cookie**,但是可以利用**Redis**将用户的**Session**集中管理,在这种模式只需要保证**Redis**的高可用,每次用户**Session**的更新和获取都可以快速完成。大大提高效率。 174 | 175 | #### **Hash:** 176 | 177 | 这个是类似 **Map** 的一种结构,这个一般就是可以将结构化的数据,比如一个对象(前提是**这个对象没嵌套其他的对象**)给缓存在 **Redis** 里,然后每次读写缓存的时候,可以就操作 **Hash** 里的**某个字段**。 178 | 179 | 但是这个的场景其实还是多少单一了一些,因为现在很多对象都是比较复杂的,比如你的商品对象可能里面就包含了很多属性,其中也有对象。我自己使用的场景用得不是那么多。 180 | 181 | #### **List:** 182 | 183 | **List** 是有序列表,这个还是可以玩儿出很多花样的。 184 | 185 | 比如可以通过 **List** 存储一些列表型的数据结构,类似粉丝列表、文章的评论列表之类的东西。 186 | 187 | 比如可以通过 **lrange** 命令,读取某个闭区间内的元素,可以基于 **List** 实现分页查询,这个是很棒的一个功能,基于 **Redis** 实现简单的高性能分页,可以做类似微博那种下拉不断分页的东西,性能高,就一页一页走。 188 | 189 | 比如可以搞个简单的消息队列,从 **List** 头怼进去,从 **List** 屁股那里弄出来。 190 | 191 | **List**本身就是我们在开发过程中比较常用的数据结构了,热点数据更不用说了。 192 | 193 | - **消息队列:Redis**的链表结构,可以轻松实现阻塞队列,可以使用左进右出的命令组成来完成队列的设计。比如:数据的生产者可以通过**Lpush**命令从左边插入数据,多个数据消费者,可以使用**BRpop**命令阻塞的“抢”列表尾部的数据。 194 | 195 | - 文章列表或者数据分页展示的应用。 196 | 197 | 比如,我们常用的博客网站的文章列表,当用户量越来越多时,而且每一个用户都有自己的文章列表,而且当文章多时,都需要分页展示,这时可以考虑使用**Redis**的列表,列表不但有序同时还支持按照范围内获取元素,可以完美解决分页查询功能。大大提高查询效率。 198 | 199 | #### **Set:** 200 | 201 | **Set** 是无序集合,会自动去重的那种。 202 | 203 | 直接基于 **Set** 将系统里需要去重的数据扔进去,自动就给去重了,如果你需要对一些数据进行快速的全局去重,你当然也可以基于 **JVM** 内存里的 **HashSet** 进行去重,但是如果你的某个系统部署在多台机器上呢?得基于**Redis**进行全局的 **Set** 去重。 204 | 205 | 可以基于 **Set** 玩儿交集、并集、差集的操作,比如交集吧,我们可以把两个人的好友列表整一个交集,看看俩人的共同好友是谁?对吧。 206 | 207 | 反正这些场景比较多,因为对比很快,操作也简单,两个查询一个**Set**搞定。 208 | 209 | #### **Sorted Set:** 210 | 211 | **Sorted set** 是排序的 **Set**,去重但可以排序,写进去的时候给一个分数,自动根据分数排序。 212 | 213 | 有序集合的使用场景与集合类似,但是set集合不是自动有序的,而**Sorted set**可以利用分数进行成员间的排序,而且是插入时就排序好。所以当你需要一个有序且不重复的集合列表时,就可以选择**Sorted set**数据结构作为选择方案。 214 | 215 | - 排行榜:有序集合经典使用场景。例如视频网站需要对用户上传的视频做排行榜,榜单维护可能是多方面:按照时间、按照播放量、按照获得的赞数等。 216 | 217 | - 用**Sorted Sets**来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。 218 | 219 | 微博热搜榜,就是有个后面的热度值,前面就是名称 220 | 221 | 222 | 223 | ### 高级用法: 224 | 225 | #### **Bitmap** : 226 | 227 | 位图是支持按 bit 位来存储信息,可以用来实现 **布隆过滤器(BloomFilter)**; 228 | 229 | #### **HyperLogLog:** 230 | 231 | 供不精确的去重计数功能,比较适合用来做大规模数据的去重统计,例如统计 UV; 232 | 233 | #### **Geospatial:** 234 | 235 | 可以用来保存地理位置,并作位置距离计算或者根据半径计算位置等。有没有想过用Redis来实现附近的人?或者计算最优地图路径? 236 | 237 | 这三个其实也可以算作一种数据结构,不知道还有多少朋友记得,我在梦开始的地方,Redis基础中提到过,你如果只知道五种基础类型那只能拿60分,如果你能讲出高级用法,那就觉得你**有点东西**。 238 | 239 | #### **pub/sub:** 240 | 241 | 功能是订阅发布功能,可以用作简单的消息队列。 242 | 243 | #### **Pipeline:** 244 | 245 | 可以批量执行一组指令,一次性返回全部结果,可以减少频繁的请求应答。 246 | 247 | #### **Lua:** 248 | 249 | **Redis** 支持提交 **Lua** 脚本来执行一系列的功能。 250 | 251 | 我在前电商老东家的时候,秒杀场景经常使用这个东西,讲道理有点香,利用他的原子性。 252 | 253 | 话说你们想看秒杀的设计么?我记得我面试好像每次都问啊,想看的直接**点赞**后评论秒杀吧。 254 | 255 | #### **事务:** 256 | 257 | 最后一个功能是事务,但 **Redis** 提供的不是严格的事务,**Redis** 只保证串行执行命令,并且能保证全部执行,但是执行命令失败时并不会回滚,而是会继续执行下去。 258 | 259 | ### 持久化 260 | 261 | **Redis** 提供了 RDB 和 AOF 两种持久化方式,RDB 是把内存中的数据集以快照形式写入磁盘,实际操作是通过 fork 子进程执行,采用二进制压缩存储;AOF 是以文本日志的形式记录 **Redis** 处理的每一个写入或删除操作。 262 | 263 | **RDB** 把整个 Redis 的数据保存在单一文件中,比较适合用来做灾备,但缺点是快照保存完成之前如果宕机,这段时间的数据将会丢失,另外保存快照时可能导致服务短时间不可用。 264 | 265 | **AOF** 对日志文件的写入操作使用的追加模式,有灵活的同步策略,支持每秒同步、每次修改同步和不同步,缺点就是相同规模的数据集,AOF 要大于 RDB,AOF 在运行效率上往往会慢于 RDB。 266 | 267 | 细节的点大家去高可用这章看,特别是两者的优缺点,以及怎么抉择。 268 | 269 | **[《吊打面试官》系列-Redis哨兵、持久化、主从、手撕LRU](https://juejin.im/post/5dc3a9fbf265da4d3c072eab)** 270 | 271 | ### 高可用 272 | 273 | 来看 Redis 的高可用。Redis 支持主从同步,提供 Cluster 集群部署模式,通过 Sentine l哨兵来监控 Redis 主服务器的状态。当主挂掉时,在从节点中根据一定策略选出新主,并调整其他从 slaveof 到新主。 274 | 275 | 选主的策略简单来说有三个: 276 | 277 | - slave 的 priority 设置的越低,优先级越高; 278 | - 同等情况下,slave 复制的数据越多优先级越高; 279 | - 相同的条件下 runid 越小越容易被选中。 280 | 281 | 在 Redis 集群中,sentinel 也会进行多实例部署,sentinel 之间通过 Raft 协议来保证自身的高可用。 282 | 283 | Redis Cluster 使用分片机制,在内部分为 16384 个 slot 插槽,分布在所有 master 节点上,每个 master 节点负责一部分 slot。数据操作时按 key 做 CRC16 来计算在哪个 slot,由哪个 master 进行处理。数据的冗余是通过 slave 节点来保障。 284 | 285 | ### 哨兵 286 | 287 | 哨兵必须用三个实例去保证自己的健壮性的,哨兵+主从并**不能保证数据不丢失**,但是可以保证集群的**高可用**。 288 | 289 | 为啥必须要三个实例呢?我们先看看两个哨兵会咋样。 290 | 291 |  292 | 293 | 294 | 295 | master宕机了 s1和s2两个哨兵只要有一个认为你宕机了就切换了,并且会选举出一个哨兵去执行故障,但是这个时候也需要大多数哨兵都是运行的。 296 | 297 | 那这样有啥问题呢?M1宕机了,S1没挂那其实是OK的,但是整个机器都挂了呢?哨兵就只剩下S2个裸屌了,没有哨兵去允许故障转移了,虽然另外一个机器上还有R1,但是故障转移就是不执行。 298 | 299 | 经典的哨兵集群是这样的: 300 | 301 |  302 | 303 | M1所在的机器挂了,哨兵还有两个,两个人一看他不是挂了嘛,那我们就选举一个出来执行故障转移不就好了。 304 | 305 | 暖男我,小的总结下哨兵组件的主要功能: 306 | 307 | - 集群监控:负责监控 Redis master 和 slave 进程是否正常工作。 308 | - 消息通知:如果某个 **Redis** 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。 309 | - 故障转移:如果 master node 挂掉了,会自动转移到 slave node 上。 310 | - 配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址。 311 | 312 | ### 主从 313 | 314 | 提到这个,就跟我前面提到的数据持久化的**RDB**和**AOF**有着比密切的关系了。 315 | 316 | 我先说下为啥要用主从这样的架构模式,前面提到了单机**QPS**是有上限的,而且**Redis**的特性就是必须支撑读高并发的,那你一台机器又读又写,**这谁顶得住啊**,不当人啊!但是你让这个master机器去写,数据同步给别的slave机器,他们都拿去读,分发掉大量的请求那是不是好很多,而且扩容的时候还可以轻松实现水平扩容。 317 | 318 |  319 | 320 | 你启动一台slave 的时候,他会发送一个**psync**命令给master ,如果是这个slave第一次连接到master,他会触发一个全量复制。master就会启动一个线程,生成**RDB**快照,还会把新的写请求都缓存在内存中,**RDB**文件生成后,master会将这个**RDB**发送给slave的,slave拿到之后做的第一件事情就是写进本地的磁盘,然后加载进内存,然后master会把内存里面缓存的那些新命名都发给slave。 321 | 322 | **我发出来之后来自CSDN的网友:Jian_Shen_Zer 问了个问题:** 323 | 324 | 主从同步的时候,新的slaver进来的时候用**RDB**,那之后的数据呢?有新的数据进入master怎么同步到slaver啊 325 | 326 | 敖丙答:笨,**AOF**嘛,增量的就像**MySQL**的**Binlog**一样,把日志增量同步给从服务就好了 327 | 328 | #### key 失效机制 329 | 330 | **Redis** 的 key 可以设置过期时间,过期后 Redis 采用主动和被动结合的失效机制,一个是和 MC 一样在访问时触发被动删除,另一种是定期的主动删除。 331 | 332 | 定期+惰性+内存淘汰 333 | 334 | ### 缓存常见问题 335 | 336 | #### 缓存更新方式 337 | 338 | 这是决定在使用缓存时就该考虑的问题。 339 | 340 | 缓存的数据在数据源发生变更时需要对缓存进行更新,数据源可能是 DB,也可能是远程服务。更新的方式可以是主动更新。数据源是 DB 时,可以在更新完 DB 后就直接更新缓存。 341 | 342 | 当数据源不是 DB 而是其他远程服务,可能无法及时主动感知数据变更,这种情况下一般会选择对缓存数据设置失效期,也就是数据不一致的最大容忍时间。 343 | 344 | 这种场景下,可以选择失效更新,key 不存在或失效时先请求数据源获取最新数据,然后再次缓存,并更新失效期。 345 | 346 | 但这样做有个问题,如果依赖的远程服务在更新时出现异常,则会导致数据不可用。改进的办法是异步更新,就是当失效时先不清除数据,继续使用旧的数据,然后由异步线程去执行更新任务。这样就避免了失效瞬间的空窗期。另外还有一种纯异步更新方式,定时对数据进行分批更新。实际使用时可以根据业务场景选择更新方式。 347 | 348 | #### 数据不一致 349 | 350 | 第二个问题是数据不一致的问题,可以说只要使用缓存,就要考虑如何面对这个问题。缓存不一致产生的原因一般是主动更新失败,例如更新 DB 后,更新 **Redis** 因为网络原因请求超时;或者是异步更新失败导致。 351 | 352 | 解决的办法是,如果服务对耗时不是特别敏感可以增加重试;如果服务对耗时敏感可以通过异步补偿任务来处理失败的更新,或者短期的数据不一致不会影响业务,那么只要下次更新时可以成功,能保证最终一致性就可以。 353 | 354 | #### 缓存穿透 355 | 356 | **缓存穿透**。产生这个问题的原因可能是外部的恶意攻击,例如,对用户信息进行了缓存,但恶意攻击者使用不存在的用户id频繁请求接口,导致查询缓存不命中,然后穿透 DB 查询依然不命中。这时会有大量请求穿透缓存访问到 DB。 357 | 358 | 解决的办法如下。 359 | 360 | 1. 对不存在的用户,在缓存中保存一个空对象进行标记,防止相同 ID 再次访问 DB。不过有时这个方法并不能很好解决问题,可能导致缓存中存储大量无用数据。 361 | 2. 使用 **BloomFilter** 过滤器,BloomFilter 的特点是存在性检测,如果 BloomFilter 中不存在,那么数据一定不存在;如果 BloomFilter 中存在,实际数据也有可能会不存在。非常适合解决这类的问题。 362 | 363 | #### 缓存击穿 364 | 365 | **缓存击穿**,就是某个热点数据失效时,大量针对这个数据的请求会穿透到数据源。 366 | 367 | 解决这个问题有如下办法。 368 | 369 | 1. 可以使用互斥锁更新,保证同一个进程中针对同一个数据不会并发请求到 DB,减小 DB 压力。 370 | 2. 使用随机退避方式,失效时随机 sleep 一个很短的时间,再次查询,如果失败再执行更新。 371 | 3. 针对多个热点 key 同时失效的问题,可以在缓存时使用固定时间加上一个小的随机数,避免大量热点 key 同一时刻失效。 372 | 373 | #### 缓存雪崩 374 | 375 | **缓存雪崩**,产生的原因是缓存挂掉,这时所有的请求都会穿透到 DB。 376 | 377 | 解决方法: 378 | 379 | 1. 使用快速失败的熔断策略,减少 DB 瞬间压力; 380 | 2. 使用主从模式和集群模式来尽量保证缓存服务的高可用。 381 | 382 | 实际场景中,这两种方法会结合使用。 383 | 384 | 老朋友都知道为啥我**没有大篇幅介绍**这个几个点了吧,我在之前的文章实在是写得太详细了,忍不住**点赞**那种,我这里就不做重复拷贝了。 385 | 386 | - **[《吊打面试官》系列-Redis基础](https://juejin.im/post/5db66ed9e51d452a2f15d833)** 387 | - **[《吊打面试官》系列-缓存雪崩、击穿、穿透](https://juejin.im/post/5dbef8306fb9a0203f6fa3e2)** 388 | - **[《吊打面试官》系列-Redis哨兵、持久化、主从、手撕LRU](https://juejin.im/post/5dc3a9fbf265da4d3c072eab)** 389 | - **[《吊打面试官》系列-Redis终章_凛冬将至、FPX_新王登基](https://juejin.im/post/5dc850b4e51d452c2308ee27)** 390 | 391 | ### 考点与加分项 392 | 393 | 拿笔记一下! 394 | 395 |  396 | 397 | #### 考点 398 | 399 | 面试的时候问你缓存,主要是考察缓存特性的理解,对 **MC**、**Redis** 的特点和使用方式的掌握。 400 | 401 | - 要知道缓存的使用场景,不同类型缓存的使用方式,例如: 402 | 403 | 1. - 对 DB 热点数据进行缓存减少 DB 压力;对依赖的服务进行缓存,提高并发性能; 404 | 405 | 2. - 单纯 K-V 缓存的场景可以使用 **MC**,而需要缓存 list、set 等特殊数据格式,可以使用 **Redis**; 406 | 407 | 3. - 需要缓存一个用户最近播放视频的列表可以使用 **Redis** 的 list 来保存、需要计算排行榜数据时,可以使用 **Redis** 的 zset 结构来保存。 408 | 409 | - 要了解 MC 和 **Redis** 的常用命令,例如原子增减、对不同数据结构进行操作的命令等。 410 | 411 | - 了解 MC 和 **Redis** 在内存中的存储结构,这对评估使用容量会很有帮助。 412 | 413 | - 了解 MC 和 **Redis** 的数据失效方式和剔除策略,比如主动触发的定期剔除和被动触发延期剔除 414 | 415 | - 要理解 **Redis** 的持久化、主从同步与 **Cluster** 部署的原理,比如 **RDB** 和 **AOF** 的实现方式与区别。 416 | 417 | - 要知道缓存穿透、击穿、雪崩分别的异同点以及解决方案。 418 | 419 | - 不管你有没有电商经验我觉得你都应该知道秒杀的具体实现,以及细节点。 420 | 421 | - ........ 422 | 423 | 欢迎去[GitHub](https://github.com/AobingJava/JavaFamily)补充 424 | 425 | #### 加分项 426 | 427 | 如果想要在面试中获得更好的表现,还应了解下面这些加分项。 428 | 429 | - 是要结合实际应用场景来介绍缓存的使用。例如调用后端服务接口获取信息时,可以使用本地+远程的多级缓存;对于动态排行榜类的场景可以考虑通过 **Redis** 的 **Sorted set** 来实现等等。 430 | 431 | - 最好你有过分布式缓存设计和使用经验,例如项目中在什么场景使用过 **Redis**,使用了什么数据结构,解决哪类的问题;使用 MC 时根据预估值大小调整 **McSlab** 分配参数等等。 432 | 433 | - 最好可以了解缓存使用中可能产生的问题。比如 **Redis** 是单线程处理请求,应尽量避免耗时较高的单个请求任务,防止相互影响;**Redis** 服务应避免和其他 CPU 密集型的进程部署在同一机器;或者禁用 Swap 内存交换,防止 **Redis** 的缓存数据交换到硬盘上,影响性能。再比如前面提到的 MC 钙化问题等等。 434 | 435 | - 要了解 **Redis** 的典型应用场景,例如,使用 **Redis** 来实现分布式锁;使用 **Bitmap** 来实现 **BloomFilter**,使用 **HyperLogLog** 来进行 UV 统计等等。 436 | 437 | - 知道 Redis4.0、5.0 中的新特性,例如支持多播的可持久化消息队列 Stream;通过 Module 系统来进行定制功能扩展等等。 438 | - ........ 439 | 440 | 还是那句话欢迎去[GitHub](https://github.com/AobingJava/JavaFamily)补充。 441 | 442 | ## 总结 443 | 444 | 这次是对我**Redis**系列的总结,这应该是**Redis**相关的最后一篇文章了,其实四篇看下来的小伙伴很多都从**一知半解**到了**一脸懵逼**,哈哈开个玩笑。 445 | 446 | 我觉得我的方式应该还好,大部分小伙伴还是比较能理解的,这篇之后我就不会写**Redis**相关的文章了(秒杀看大家想看的热度吧),有啥问题可以微信找我,**下个系列写啥**? 447 | 448 | 大家不用急,下个系列前我会发个有意思的文章,是我在公司代码创意大赛拿奖的文章,我觉得还是**有点东西**,我忍不住分享一下,顺便就在那期发起**投票**吧哈哈。 449 | 450 | 我看到很多小伙伴都有评论说想看别的,大概搜集了一下,还没留言的这期赶紧哟: 451 | 452 | #### 掘金 453 | 454 | **愚辛** :想看计算机基础,网络和操作系统那些(FPX牛脾) 455 | 456 | **cherish君**:讲讲dubbo经常遇到的面试题目,太多人喜欢问dubbo😃 457 | 458 | **Java架构养成记**:真的很香啊,下一期讲Dubbbo(重点SPI)然后讲MQ好吗 459 | 460 | #### CSDN 461 | 462 | **小殿下**:看完了所有的redis篇 希望可以出ssm 463 | 464 | #### 博客园 465 | 466 | **程然**:Dubbo Dubbo 467 | 468 | #### 开源中国 469 | 470 | **linshi2019**:这期明显是赶工之作啊 471 | 472 | 敖丙:这条我回一下,鞭策我,我很喜欢,不过说实话还是希望大家**理解**下,我双十一熬夜三天了,现在给你们写的时候也是值班回家2点左右了,我一天吃饭工作时间肯定是固定的,想写点东西就只有挤出睡觉时间了,这种产出肯定没周末全情投入写的来的质量高。 473 | 474 | 其实第一期看过来的小伙伴应该也知道,我在**排版**,还有很多**文案**,**配图**其实我一直都有在改进的,光是名词高亮我都要弄很久,因为怕大家看单一的黑白色调枯燥。 475 | 476 | 我是真的用心在搞,还是希望大家支持下理解下。 477 | 478 | **知乎、简书、思否、慕课手记**没人看不知道为啥,懂行的老铁可以跟我说一下。 479 | 480 | 我只想说你们想看的肯定都在我开头和[GITHub](https://github.com/AobingJava/JavaFamily)那个图里吧,问题不大,后面都会写的。 481 | 482 | ## 鸣谢 483 | 484 | 最后感谢下,新浪微博的技术专家张雷。 485 | 486 | 他于2013年加入**新浪微博**,作为核心技术人员参与了微博服务化、混合云等多个重点项目,是微博开源的**RPC**框架**Motan**的技术负责人,同时也负责微博的**Service Mesh**方案的研发与推广,专注于高可用架构及服务中间件开发方向。 487 | 488 | 他负责的**Motan**框架每天承载着万亿级别的请求调用,是微博平台服务化的基石,每次的突发热点事件、每次的春晚流量高峰,都离不开**Motan**框架的支撑与保障。此外,他也多次应邀在**ArchSummit、WOT、GIAC**技术峰会做技术分享。 489 | 490 | 感谢他对文章部分文案提供的支持和思路。 491 | 492 | ## END 493 | 494 | 好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是**人才**。 495 | 496 | 我后面会每周都更新几篇《**吊打面试官**》系列和**互联网常用技术栈**相关的文章。如果你有什么想知道的,也可以留言给我,我一有时间就会写出来,我们共同进步。 497 | 498 | 非常感谢**人才**们能看到这里,如果这个文章写得还不错,觉得「敖丙」我**有点东西**的话 **求点赞👍** **求关注❤️** **求分享👥** **求留言💬** 对暖男我来说 **非常有用**!!! 499 | 500 | 各位的支持和认可,就是我创作的最大动力,我们下篇文章见! 501 | 502 | 敖丙 | 文 【原创】【转载请联系本人】 503 | 504 | ------ 505 | 506 | > 《吊打面试官》系列每周持续更新,可以关注我的公众号[JavaFamily](https://github.com/AobingJava/JavaFamily#%E5%85%AC%E4%BC%97%E5%8F%B7)第一时间阅读和催更(**公众号比博客早一到两天哟**),[**GitHub**](https://github.com/AobingJava/JavaFamily)上已经开源[https://github.com/Java...](https://github.com/AobingJava/JavaFamily),有面试点思维导图,欢迎[**Star**](https://github.com/AobingJava/JavaFamily)和[**完善**](https://github.com/AobingJava/JavaFamily)里面也有我个人微信有什么问题也可以直接滴滴我,我们一起进步。 507 | 508 |  --------------------------------------------------------------------------------