作者:rikeshi
给大家推荐一个靠谱的免费论文查重网站PaperPP:http://www.paperpp.com
作者:微信小助手
<p style="text-align: center;"><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;">(给</span><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;line-height: 22.4px;color: rgb(0, 128, 255);">ImportNew</span><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;">加星标,提高Java技能)</span></p> <blockquote> <p style="letter-spacing: 0.5440000295639038px;white-space: normal;background-color: rgb(255, 255, 255);max-width: 100%;min-height: 1em;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">转自:GitHub 作者:Stephanie Tang</span></p> <p style="letter-spacing: 0.5440000295639038px;white-space: normal;background-color: rgb(255, 255, 255);max-width: 100%;min-height: 1em;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 14px;">stephanietang.github.io/2020/04/19/how-https-works/</span></p> </blockquote> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">当你打开浏览器,访问某个网站,如果网址旁有个小锁,代表访问的网址是安全的,反之不安全。当我们没有看到那个小锁的小图标的时候,需要提高警惕,不要随意输入个人重要的资料。所有的银行和支付相关的网站都是100%使用HTTPS的。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <p style="text-align: center;"><img class="rich_pages" data-backh="306" data-backw="329" data-ratio="0.9300911854103343" data-s="300,640" src="/upload/b043db779a2f80641f7cee383c224be4.png" data-type="png" data-w="329" style="width: 100%;height: auto;"></p> <h2 style="line-height: 1.5em;"><br></h2> <h2 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">我们为什么需要HTTPS?</span></strong></span></h2> <p><span style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);">主要有三个原因:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);"><br></span> </section> <ol class="list-paddingleft-2"> <li style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);">保护隐私(Privacy):所有信息都是加密传播,第三方无法窃听数据。如果使用HTTP明文传输数据的话,很可能被第三方劫持数据,那么所输入的密码或者其他个人资料都被暴露在他人面前,后果可想而知。</span> </section><p><br></p></li> <li style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);">数据完整性(Integraty):一旦第三方篡改了数据,接收方会知道数据经过了篡改,这样便保证了数据在传输过程中不被篡改 —— 数据的完整性。</span> </section><p><br></p></li> <li style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);">身份认证(Identification):第三方不可能冒充身份参与通信,因为服务器配备了由证书颁发机构(Certificate Authority,简称CA)颁发的安全证书,可以证实服务器的身份信息,防止第三方冒充身份。(也有少数情况下,通信需要客户端提供证书,例如银行系统,需要用户在登录的时候,插入银行提供给用户的USB,就是需要客户端提供证书,用来验证客户的身份信息。)</span> </section></li> </ol> <h3 style="line-height: 1.5em;"><br></h3> <h3 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">HTTPS是什么?SSL/TLS是什么?</span></strong></span></h3> <p><span style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);"><br></span></p> <ul class="list-paddingleft-2"> <li style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);">HTTP协议(HyperText Transfer Protocol,超文本传输协议)是大家最熟悉的一种协议,它是一个用于传输超媒体文档的协议,它位于OSI网络协议模型的应用层。但是它是明文传输协议,是非常不安全的,容易被人篡改和窃取数据。</span> </section><p><br></p></li> <li style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);">SSL(Secure Socket Layer) —— 网景(Netscape)公司设计的主要用于web的安全传输协议。它位于TCP传输层协议和应用层协议之间。(它没有被划分在OSI网络协议模型中,且认为它是应用层的子层。)</span> </section><p><br></p></li> <li style="color: rgb(0, 0, 0);"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);">众所周知,网景公司20世纪90年代在和微软的竞争中最终败下阵来,之后网景公司将SSL协议的管理权转交给IETF(Internet Engineering Task Force, www.ietf.org)。于是IETF将SSL作了标准化,重新命名为TLS(Transport Layer Security)。在1999年,TLS 1.0诞生了(其实也就是SSL 3.1)。</span> </section><p><br></p></li> <li style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;color: rgb(0, 0, 0);">HTTPS(HyperText Transfer Protocol Secure)是建立在SSL/TLS协议之上,信息通信通过SSL/TLS进行加密,最后一个S就是Secure的缩写,代表安全的意思,HTTPS = HTTP + SSL/TLS。</span> </section></li> </ul> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.6164383561643836" data-s="300,640" src="/upload/bb09d88ecb5cf9f5bcb055615e4ea072.png" data-type="png" data-w="438" style=""></p> <h3 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);letter-spacing: normal;"><strong><span style="font-size: 15px;">SSL/TLS发展史</span></strong></span></h3> <p><span style="color: rgb(171, 25, 66);letter-spacing: normal;"><strong><span style="font-size: 15px;"><br></span></strong></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.734475374732334" data-s="300,640" src="/upload/cdff07c0539c1b66c034be41eef91cac.png" data-type="png" data-w="467" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.7370689655172413" data-s="300,640" src="/upload/7c3c109ef70cd3edb92462d49d85c938.png" data-type="png" data-w="464" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.7387580299785867" data-s="300,640" src="/upload/292e2cd27d9639d0479344dee9378aa4.png" data-type="png" data-w="467" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.7296137339055794" data-s="300,640" src="/upload/cf4b6ca3375ac7cf8b6a00c86788c865.png" data-type="png" data-w="466" style=""></p> <p style="text-align: center;"><br></p> <ul style="color: rgb(85, 85, 85);font-family: Lato, "PingFang SC", "Microsoft YaHei", sans-serif;font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);" class="list-paddingleft-2"> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">实际上现代的浏览器已经基本不使用SSL,使用的都是TLS,SSL 3.0于2015年已经寿终正寝 —— 各大浏览器也不支持了。但是由于SSL这个术语存在的时间太长,很多地方还是广泛的使用它,但是要清楚其实它说的是TLS。</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">有调查显示现在绝大部分浏览器(> 99.5%)都使用TLS 1.2或者TLS 1.3。只有不足1%的浏览器仍然使用TLS 1.0或者TLS 1.1。</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">TLS 1.2仍然是主流协议(本文写于2020年初),相信将来逐渐TLS 1.3将会作为主流协议。</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">很多浏览器将会开始不支持TLS 1.0和1.1:</span> </section></li> <p><br></p> <ul class="list-paddingleft-2" style="list-style-type: square;"> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">Google将在Chrome 72中不推荐使用TLS 1.0和1.1,而Chrome 81之后将会完全不支持。</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">Mozilla的Firefox,微软的Edge和IE以及苹果的Safari都会分别于2020年逐渐移除对TLS 1.0和1.1的支持。</span> </section><p><br></p></li> </ul> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">那么一些还在使用TLS 1.0和1.1的网站就得被迫升级到TLS 1.2或者TLS 1.3。</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">要关闭浏览器对TLS 1.0和1.1的支持,可以在Internet选项中修改:</span> </section> <section style="line-height: 1.5em;"> <br> </section></li> </ul> <p style="text-align: center;"><img class="rich_pages" data-ratio="1.4282744282744282" data-s="300,640" src="/upload/fe539dc8b9ad93a04e4d7cfad9688ca4.png" data-type="png" data-w="481" style=""></p> <h3 style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></h3> <h3 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">SSL/TLS的工作原理</span></strong></span></h3> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">需要理解SSL/TLS的工作原理,我们需要掌握加密算法。加密算法有两种:对称加密和非对称加密:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <ul class="list-paddingleft-2"> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">对称加密:通信双方使用相同的密钥进行加密。特点是加密速度快,但是缺点是需要保护好密钥,如果密钥泄露的话,那么加密就会被别人破解。常见的对称加密有AES,DES算法。</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">非对称加密:它需要生成两个密钥:公钥(Public Key)和私钥(Private Key)。公钥顾名思义是公开的,任何人都可以获得,而私钥是私人保管的。相信大多程序员已经对这种算法很熟悉了:我们提交代码到github的时候,就可以使用SSH key:在本地生成私钥和公钥,私钥放在本地.ssh目录中,公钥放在github网站上,这样每次提交代码,不用麻烦的输入用户名和密码了,github会根据网站上存储的公钥来识别我们的身份。公钥负责加密,私钥负责解密;或者,私钥负责加密,公钥负责解密。这种加密算法安全性更高,但是计算量相比对称加密大很多,加密和解密都很慢。常见的非对称算法有RSA。</span> </section></li> </ul> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">SSL/TLS是利用了对称加密和非对称加密的特点。先来看下整个SSL/TLS的握手过程,之后我们再分步骤详细解读,每一步都干了些什么。</span> </section> <section style="line-height: 1.5em;"> <br> </section> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.8079658605974396" data-s="300,640" src="/upload/914d593ff0a9d447f1bda5fd3459abbb.png" data-type="png" data-w="703" style=""></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">1.当TCP建立连接之后,TLS握手的第一步由客户端发起,发送ClientHello的消息到服务器。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br>ClientHello消息包含:</span> </section> <section style="line-height: 1.5em;"> <br> </section> <ul class="list-paddingleft-2"> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">客户端支持的SSL/TLS版本</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">客户端支持的加密套件(Cipher Suites)</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">会话Idsession id(如果有的值的话,服务器端会复用对应的握手信息,避免短时间内重复握手)</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">随机数client-random</span> </section></li> </ul> <section style="line-height: 1.5em;"> <br> </section> <p style="line-height: 1.5em;"><span style="letter-spacing: normal;color: rgb(171, 25, 66);font-size: 15px;">延伸阅读:</span></p> <p style="line-height: 1.5em;"><span style="letter-spacing: normal;color: rgb(171, 25, 66);font-size: 15px;"><br style="color: rgb(0, 0, 0);font-size: 15px;white-space: normal;">加密套件名如:“TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA256”,这么长的名字看着有点晕吧,不用怕,其实它的命名非常规范,格式很固定。基本的形式是“密钥交换算法-服务身份验证算法-对称加密算法-握手校验算法”。</span></p> <p style="line-height: 1.5em;"><span style="letter-spacing: normal;color: rgb(171, 25, 66);font-size: 15px;"><br style="color: rgb(0, 0, 0);font-size: 15px;white-space: normal;">握手过程中,证书签名使用的RSA算法,如果证书验证正确,再使用ECDHE算法进行密钥交换,握手后的通信使用的是AES256的对称算法分组模式是GCM。验证证书签名合法性使用SHA256作哈希算法检验。相关的算法的用处将在后文中详解。</span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">2.然后服务器端在收到这个ClientHello,从中选择服务器支持的版本和套件,发送ServerHello消息:</span> </section> <section style="line-height: 1.5em;"> <br> </section> <ul class="list-paddingleft-2"> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">服务器所能支持的最高SSL/TLS版本</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">服务器选择的加密套件</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">随机数server-random</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">会话Idsession id(用于下次复用当前握手的信息,避免短时间内重复握手。)</span> </section></li> </ul> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">随后服务器发送服务器的安全证书(含公钥)。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果需要客户端也提供证书的话,还会发出客户端证书请求(Client Certificate Request),只有少数金融机构才需要客户端也提供客户端证书。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">此后客户端发送Server Hello Done消息表示Hello阶段完成。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">3.客户端收到ServerHello后,会对收到的证书进行验证。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">我们来看一下为什么可以通过CA(Certificate Authority,证书颁发机构)签发的证书来确认网站的身份?</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">当我们安装操作系统或者浏览器的时候,会安装一组可信任的CA(根证书CA包括GlobalSign、GeoTrust、Verisign等)列表。根CA如GlobalSign就在我们的可信任的CA列表里,你的浏览器或者操作系统含有GlobalSign的公钥。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">先来看一下Google的证书,当你访问Google的时候,Google会发给你它的证书。证书中包含颁发机构的签名以及服务器的公钥。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <p style="text-align: center;"><img class="rich_pages" data-ratio="1.397872340425532" data-s="300,640" src="/upload/18525cbd4095a49ec0666fc885342935.png" data-type="png" data-w="470" style=""></p> <section style="line-height: 1.5em;"> <br> </section> <p style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">浏览器首先用哈希函数对明文信息的摘要做哈希得到一个哈希值(用到的就是证书中的签名哈希算法SHA256),然后用根CA的公钥对根证书的签名作解密得到另一个哈希值(用到的算法就是RSA非对称算法),如果两个哈希值相等则说明证书没有被篡改过。当然还需校验证书中服务器名称是否合法以及验证证书是否过期。</span></p> <p style="line-height: 1.5em;"><span style="text-align: center;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-backh="433" data-backw="578" data-ratio="0.7490118577075099" data-s="300,640" src="/upload/cecb054a903e8f324c35e5ac9d6f46e1.png" data-type="png" data-w="1012" style="width: 100%;height: auto;"></p> <p style="line-height: 1.5em;"><br></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">这样就免受中间人攻击了,因为假如有中间人修改了证书的内容(如将证书中的公钥替换成自己的公钥),那么将获得不同的哈希值,从而两个哈希值不匹配导致验证失败。如果要绕过这个机制,中间人必须要也替换签名,使签名也相匹配。而做到这一点就需要破解到了根证书的密钥(而这是不可能的,中间人必然会失败)。浏览器会出现以下画面,告诉你正在遭受中间人攻击,因为证书被篡改了:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.6286836935166994" data-s="300,640" src="/upload/2dd1d558722abf7b9d2a2938465d0116.png" data-type="png" data-w="509" style=""></p> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">那聪明的你肯定也想到了,如果你开发了一个系统还在测试阶段,还没有正式申请一张证书,那么你可以为服务器自签名一张证书,然后将证书导入客户端的CA信任列表中。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">信任链机制</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <p style="text-align: center;"><img class="rich_pages" data-ratio="1.3927813163481952" data-s="300,640" src="/upload/c8e05b556c3bced1635e9e92ed1c126a.png" data-type="png" data-w="471" style=""></p> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">可以看到证书路径是GlobalSign Root CA-R2 -> GTS CA 1O1->*.google.com。因为我们的浏览器信任GlobalSign Root CA,根据信任链机制,你相信了根CA颁发的证书,也要相信它签名的子CA颁发的证书,也要相信子CA签名的子子CA的证书…而我们通过一级级的校验,如果从根证书到最下层的证书都没有被篡改过,我们就相信最下层的这个服务器证书是合法的。所以在这个机制中,你就需要无条件的相信根证书的颁发机构。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果通过验证,客户端生成一个随机数pre-master,用于密钥交换过程。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">4.密钥交换过程:客户端用第三步中服务器的证书中拿到服务器的公钥,用这个公钥加密(算法是加密套件中的密钥交换算法,譬如ECDHE算法)生成密文发送给服务器。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">5.客户端用server-random + client-random + pre-master一起计算出对称密钥master secret。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">6.服务器收到第四步的信息之后,用服务器的私钥对密文进行解密得到密钥pre-master。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">因为只有服务器有私钥,可以针对客户端发出的加密过的信息进行解密得到pre-master,这样就保证了只有服务器和客户端知道pre-master。服务器端也可以用server-random + client-random + pre-master一起计算出对称密钥master secret。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">现在客户端和服务器均有密钥master secret了,后面就可以用它来进行加密和解密了。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;color: rgb(171, 25, 66);">为什么不能只用一个pre-master作为之后加密的对称密钥?</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;color: rgb(171, 25, 66);"><br style="font-size: 15px;white-space: normal;">虽然只有服务器有私钥,能够解密pre-master呀,但仅用它作为master secret是不够安全的,这是因为要以防客户端的pre-master并不是随机数的情况。加上另外两个随机数client-random以及server-random(而这两个随机数和时间有相关性),这样就能保证最后生成的master secret一定是随机数。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;letter-spacing: normal;color: rgb(171, 25, 66);"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">7.客户端用master secret加密了一条握手完成的消息发送给服务器。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">8.服务器端也回发了一条用master secret加密的握手完成的消息。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">9.当两方都收到对方发送的握手消息之后,也成功解密后,就可以用master secret愉快的开始数据加密和解密了。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">综上,整个握手过程主要是通过一系列步骤通过非对称加密的算法交换得到了master secret,这个步骤通常需要几百毫秒,但是就是这一顿猛操作之后使得只有服务器和客户端知道master secret。之后的通信又利用了高效的对称算法对所有信息进行加密和解密,虽然加密和解密也需要耗时耗流量,不过信息是完全不可能被别人篡改和破解的,这一点损耗还是值得的。</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section donone="shifuMouseDownCard('shifu_c_030')" label="Copyright Reserved by PLAYHUDONG." style="text-align: start;white-space: normal;margin-top: 1em;margin-bottom: 1em;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);border-width: 0px;border-style: initial;border-color: initial;"> <section style="margin-left: 1em;line-height: 1.4;"> <span style="padding: 3px 8px;border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;color: rgb(255, 255, 255);background-color: rgb(255, 105, 31);font-family: inherit;text-align: inherit;text-decoration: inherit;font-size: 16px;">推荐阅读</span> <span style="margin-left: 4px;padding: 3px 8px;border-top-left-radius: 1.2em;border-top-right-radius: 1.2em;border-bottom-right-radius: 1.2em;border-bottom-left-radius: 1.2em;color: rgb(255, 255, 255);line-height: 1.2;background-color: rgb(204, 204, 204);font-family: inherit;text-align: inherit;text-decoration: inherit;border-color: rgb(249, 110, 87);font-size: 12px;">点击标题可跳转</span> </section> <section style="margin-top: -11px;padding: 22px 16px 16px;border-width: 1px;border-style: solid;border-color: rgb(255, 105, 31);color: rgb(51, 51, 51);font-size: 1em;font-family: inherit;text-align: inherit;text-decoration: inherit;"> <p><span style="font-size: 12px;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-decoration: underline;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651486812&idx=1&sn=3d5778b3bf23a59e9141467ff9678f59&chksm=bd2516238a529f35a8a6818bec7f10b0353c7beeaf26d68e9da561209fba566f99314ed59c7a&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2">看完这篇 HTTPS ,和面试官扯皮就没问题了</a><br></span></p> <p><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-decoration: underline;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651485685&idx=1&sn=7f3653d01010f129ff8e6cea6cdaf077&chksm=bd25198a8a52909cedb5c6d7e1a94b2a3d9826fadf938445bed3b0acbfd0424338650e251291&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2">HTTPS 原理分析——带着疑问层层深入</a><br></span></p> <p><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-decoration: underline;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651485978&idx=2&sn=0b9392dd0c6157bd6331d0c1e1c6d5f2&chksm=bd251b658a5292738aaccd485ae9e99aedc16bbd673e43de0d02a4979797301254120b372075&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2">HttpClient 连接池设置引发的一次雪崩</a></span><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);"><br></span></p> </section> </section> <p style="caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);text-align: start;white-space: normal;"><br></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(255, 169, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">看完本文有收获?请转发分享给更多人</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;color: rgb(255, 169, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">关注「ImportNew」,提升Java技能</strong></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.9166666666666666" data-s="300,640" data-type="png" data-w="600" width="auto" src="/upload/899866149276fa5fddb73c61ae04be64.png" style="box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 600px !important;"></p> <p style="text-align: right;"><span style="font-size: 14px;text-align: right;">好文章,我</span><span style="font-size: 14px;text-align: right;color: rgb(255, 41, 65);">在看</span><span style="font-size: 14px;text-align: right;">❤️</span></p>
作者:微信小助手
<section style="display: none;" data-tools="新媒体管家" data-label="powered by xmt.cn"> <br> </section> <section data-mpa-powered-by="yiban.io" style="margin-right: 8px;margin-left: 8px;white-space: normal;letter-spacing: 0.544px;color: rgb(0, 0, 0);font-size: medium;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);text-align: center;"> <span style="color: rgb(136, 136, 136);letter-spacing: 0.544px;text-align: justify;font-size: 12px;"></span> </section> <p><span style="font-size: 15px;background-color: rgb(255, 255, 255);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;">前段时间发现github上邱锡鹏老师将他的</span><strong style="font-size: 15px;background-color: rgb(255, 255, 255);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">《神经网络与深度学习》</strong><span style="font-size: 15px;background-color: rgb(255, 255, 255);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;">书籍的pdf和ppt开源了出来,个人读完后,感觉内容的思路很清晰,非常适合初学者。</span><span style="font-size: 15px;background-color: rgb(255, 255, 255);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;">在这里分享给大家。</span><span style="font-size: 15px;background-color: rgb(255, 255, 255);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;">截止到发稿时,已经积累了 11</span><span style="font-size: 15px;background-color: rgb(255, 255, 255);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;">.6</span><span style="font-size: 15px;background-color: rgb(255, 255, 255);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;">k 个Star,2.6</span><span style="font-size: 15px;background-color: rgb(255, 255, 255);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;">k 个Fork。</span><br></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></span></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">项目地址:</span></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">https://github.com/nndl/nndl.github.io</span></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.582857px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.5857461024498887" src="/upload/c538c723f764eba91305a60ae6e60da6.png" data-type="png" data-w="898" style="font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 455px !important;visibility: visible !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">书籍介绍</span></strong></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></span></strong></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.582857px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">本书从基础到研究前沿介绍了深度学习的核心概念与理论。不仅能了解到全连接、卷积和循环等基本深度神经网络网络,同时还能学习到前沿的 Transformer 等模型,当然所需的数学基础在附录也都是有提供的。</span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.582857px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.582857px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;letter-spacing: 0.544px;color: rgb(0, 82, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">而且<span style="max-width: 100%;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;letter-spacing: 0.5px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;">,各种附加资料一站式配齐:从教材、讲解PPT、示例代码到课后练习,可以做到全方位无死角学习。</span></span></strong></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.582857px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;letter-spacing: 0.544px;color: rgb(0, 82, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;letter-spacing: 0.5px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></span></span></strong></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;">书籍目录</span></strong><br></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></p> <section style="max-width: 100%;white-space: normal;background-color: rgb(255, 255, 255);font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <figure style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.9561707035755479" src="/upload/3c11b14ecf1aed47794b972f72990689.png" data-type="png" data-w="867" style="font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 475px !important;visibility: visible !important;" title=""> </figure> </section> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">部分PPT和PDF截图</strong></span></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></strong></span></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.630718954248366" src="/upload/e73b1e474418e63bd352ea912c8390f8.png" data-type="png" data-w="1224" style="box-sizing: border-box !important;overflow-wrap: break-word !important;width: 493px;visibility: visible !important;height: auto;" title=""></p> <section style="max-width: 100%;white-space: normal;font-size: 16px;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <figure style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;color: rgb(127, 127, 127);font-size: 14px;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">▲ PPT和PDF截图</span> </figure> </section>
作者:微信小助手
<section style="box-sizing: border-box;font-style: normal;text-align: justify;"> <section style="font-weight: 400;font-size: 16px;margin: 30px 0% 20px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;vertical-align: top;box-sizing: border-box;"> <section style="box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 100%;vertical-align: top;border-width: 3px;border-radius: 20px;border-style: solid;border-color: rgb(226, 241, 246);overflow: hidden;padding: 5px 10px;background-color: rgb(226, 241, 246);box-sizing: border-box;"> <section style="transform: translate3d(1px, 0px, 0px);box-sizing: border-box;" powered-by="xiumi.us"> <section style="text-align: center;font-size: 14px;color: rgb(149, 187, 202);box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">文章出自 csdn<br></p> </section> </section> </section> </section> <section style="box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><br style="box-sizing: border-box;"></p> </section> </section> </section> <section style="font-weight: 400;font-size: 16px;text-align: left;margin: 0px 0% -15px;transform: translate3d(20px, 0px, 0px);box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 55px;height: 40px;vertical-align: top;overflow: hidden;box-sizing: border-box;"> <section style="text-align: center;margin: 0px 0%;box-sizing: border-box;" powered-by="xiumi.us"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;"> <img data-ratio="0.696" data-w="500" src="/upload/a040d38d88cdcfaed38ea2886a5b9df0.gif" style="vertical-align: middle;max-width: 100%;box-sizing: border-box;" data-type="gif"> </section> </section> </section> </section> <section style="font-weight: 400;font-size: 16px;box-sizing: border-box;" powered-by="xiumi.us"> <p style="text-align: center;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><span style="text-shadow: rgb(195, 134, 234) 2px 0px 7px;box-sizing: border-box;"><strong style="box-sizing: border-box;">点击蓝字波哥的IT人生,关注我们<br style="box-sizing: border-box;"></strong></span></p> </section> <section style="font-weight: 400;font-size: 16px;text-align: right;margin: 0px 0% 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;vertical-align: middle;width: 40%;box-sizing: border-box;"> <section style="text-align: center;margin: 0px 0%;box-sizing: border-box;" powered-by="xiumi.us"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;width: 100%;box-sizing: border-box;"> <img data-ratio="0.2106667" data-w="750" src="/upload/9a990984a6b8f7f7b3c167d0a48d8599.gif" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" width="100%" data-type="gif"> </section> </section> </section> <section style="display: inline-block;vertical-align: middle;width: 25%;padding: 0px;box-sizing: border-box;"> <section style="margin: 0.5em 0px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="background-color: rgb(29, 29, 29);height: 1px;box-sizing: border-box;"> <br> </section> </section> </section> </section> <section powered-by="xiumi.us"> <p>11、石头、剪刀、布游戏</p> <p><br></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <pre class="code-snippet__js" data-lang="bash"><code><span class="code-snippet_outer"><span class="code-snippet__meta">#!/bin/bash</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 编写脚本,实现人机<石头,剪刀,布>游戏</span></span></code><code><span class="code-snippet_outer">game=(石头 剪刀 布)</span></code><code><span class="code-snippet_outer">num=$[RANDOM%3]</span></code><code><span class="code-snippet_outer">computer=<span class="code-snippet__variable">${game[$num]}</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 通过随机数获取计算机的出拳</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 出拳的可能性保存在一个数组中,game[0],game[1],game[2]分别是 3 中不同的可能</span></span></code><code><span class="code-snippet_outer"> </span></code><code><span class="code-snippet_outer"><span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"请根据下列提示选择您的出拳手势"</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"1.石头"</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"2.剪刀"</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"3.布"</span></span></code><code><span class="code-snippet_outer"> </span></code><code><span class="code-snippet_outer"><span class="code-snippet__built_in">read</span> -p <span class="code-snippet__string">"请选择 1‐3:"</span> person</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">case</span> <span class="code-snippet__variable">$person</span> <span class="code-snippet__keyword">in</span></span></code><code><span class="code-snippet_outer">1)</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> [ <span class="code-snippet__variable">$num</span> -eq 0 ]</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">then</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"平局"</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">elif</span> [ <span class="code-snippet__variable">$num</span> -eq 1 ]</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">then</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"你赢"</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">else</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"计算机赢"</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">fi</span>;;</span></code><code><span class="code-snippet_outer">2) </span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> [ <span class="code-snippet__variable">$num</span> -eq 0 ]</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">then</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"计算机赢"</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">elif</span> [ <span class="code-snippet__variable">$num</span> -eq 1 ]</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">then</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"平局"</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">else</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"你赢"</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">fi</span>;;</span></code><code><span class="code-snippet_outer">3)</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> [ <span class="code-snippet__variable">$num</span> -eq 0 ]</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">then</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"你赢"</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">elif</span> [ <span class="code-snippet__variable">$num</span> -eq 1 ]</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">then</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"计算机赢"</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">else</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"平局"</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">fi</span>;;</span></code><code><span class="code-snippet_outer">*)</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"必须输入 1‐3 的数字"</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">esac</span></span></code></pre> </section> <p>12、编写脚本测试 192.168.4.0/24 整个网段中哪些主机处于开机状态,哪些主机处于关机状态(for 版本)</p> <p><br></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <pre class="code-snippet__js" data-lang="bash"><code><span class="code-snippet_outer"><span class="code-snippet__meta">#!/bin/bash</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 编写脚本测试 192.168.4.0/24 整个网段中哪些主机处于开机状态,哪些主机处于关机</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 状态(for 版本)</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">for</span> i <span class="code-snippet__keyword">in</span> {1..254}</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">do</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__comment"># 每隔0.3秒ping一次,一共ping2次,并以1毫秒为单位设置ping的超时时间</span></span></code><code><span class="code-snippet_outer"> ping ‐c 2 ‐i 0.3 ‐W 1 192.168.4.<span class="code-snippet__variable">$i</span> &>/dev/null</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> [ $? -eq 0 ];<span class="code-snippet__keyword">then</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"192.168.4.<span class="code-snippet__variable">$i</span> is up"</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">else</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"192.168.4.<span class="code-snippet__variable">$i</span> is down"</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">fi</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">done</span></span></code></pre> </section> <p>13、编写脚本测试 192.168.4.0/24 整个网段中哪些主机处于开机状态,哪些主机处于关机状态(while 版本) </p> <p><br></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <pre class="code-snippet__js" data-lang="bash"><code><span class="code-snippet_outer"><span class="code-snippet__meta">#!/bin/bash</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 编写脚本测试 192.168.4.0/24 整个网段中哪些主机处于开机状态,哪些主机处于关机</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 状态(while 版本) </span></span></code><code><span class="code-snippet_outer">i=1</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">while</span> [ <span class="code-snippet__variable">$i</span> -le 254 ]</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">do</span></span></code><code><span class="code-snippet_outer"> ping ‐c 2 ‐i 0.3 ‐W 1 192.168.4.<span class="code-snippet__variable">$i</span> &>/dev/null</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">if</span> [ $? -eq 0 ];<span class="code-snippet__keyword">then</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"192.168.4.<span class="code-snippet__variable">$i</span> is up"</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">else</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"192.168.4.<span class="code-snippet__variable">$i</span> is down"</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">fi</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">let</span> i++</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">done</span></span></code></pre> </section> <p>14、编写脚本测试 192.168.4.0/24 整个网段中哪些主机处于开机状态,哪些主机处于关机状态(多进程版)</p> <p><br></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <pre class="code-snippet__js" data-lang="bash"><code><span class="code-snippet_outer"><span class="code-snippet__meta">#!/bin/bash</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 编写脚本测试 192.168.4.0/24 整个网段中哪些主机处于开机状态,哪些主机处于关机</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 状态(多进程版)</span></span></code><code><span class="code-snippet_outer"> </span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment">#定义一个函数,ping 某一台主机,并检测主机的存活状态</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__function"><span class="code-snippet__title">myping</span></span>(){</span></code><code><span class="code-snippet_outer">ping ‐c 2 ‐i 0.3 ‐W 1 <span class="code-snippet__variable">$1</span> &>/dev/null</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">if</span> [ $? -eq 0 ];<span class="code-snippet__keyword">then</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"<span class="code-snippet__variable">$1</span> is up"</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">else</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"<span class="code-snippet__variable">$1</span> is down"</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">fi</span></span></code><code><span class="code-snippet_outer">}</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">for</span> i <span class="code-snippet__keyword">in</span> {1..254}</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">do</span></span></code><code><span class="code-snippet_outer"> myping 192.168.4.<span class="code-snippet__variable">$i</span> &</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">done</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 使用&符号,将执行的函数放入后台执行</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 这样做的好处是不需要等待ping第一台主机的回应,就可以继续并发ping第二台主机,依次类推。</span></span></code></pre> </section> <p>15、编写脚本,显示进度条</p> <p><br></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <pre class="code-snippet__js" data-lang="bash"><code><span class="code-snippet_outer"><span class="code-snippet__meta">#!/bin/bash</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 编写脚本,显示进度条</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__function"><span class="code-snippet__title">jindu</span></span>(){</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">while</span> :</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">do</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> -n <span class="code-snippet__string">'#'</span></span></code><code><span class="code-snippet_outer"> sleep 0.2</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">done</span></span></code><code><span class="code-snippet_outer">}</span></code><code><span class="code-snippet_outer">jindu &</span></code><code><span class="code-snippet_outer">cp -a <span class="code-snippet__variable">$1</span> <span class="code-snippet__variable">$2</span></span></code><code><span class="code-snippet_outer">killall <span class="code-snippet__variable">$0</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"拷贝完成"</span></span></code></pre> </section> <p>16、进度条,动态时针版本;定义一个显示进度的函数,屏幕快速显示| / ‐ \</p> <p><br></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <pre class="code-snippet__js" data-lang="bash"><code><span class="code-snippet_outer"><span class="code-snippet__meta">#!/bin/bash</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 进度条,动态时针版本</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 定义一个显示进度的函数,屏幕快速显示| / ‐ \</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__function"><span class="code-snippet__title">rotate_line</span></span>(){</span></code><code><span class="code-snippet_outer">INTERVAL=0.5 <span class="code-snippet__comment">#设置间隔时间</span></span></code><code><span class="code-snippet_outer">COUNT=<span class="code-snippet__string">"0"</span> <span class="code-snippet__comment">#设置4个形状的编号,默认编号为 0(不代表任何图像)</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">while</span> :</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">do</span></span></code><code><span class="code-snippet_outer"> COUNT=`expr <span class="code-snippet__variable">$COUNT</span> + 1` <span class="code-snippet__comment">#执行循环,COUNT 每次循环加 1,(分别代表4种不同的形状)</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">case</span> <span class="code-snippet__variable">$COUNT</span> <span class="code-snippet__keyword">in</span> <span class="code-snippet__comment">#判断 COUNT 的值,值不一样显示的形状就不一样</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__string">"1"</span>) <span class="code-snippet__comment">#值为 1 显示‐</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> -e <span class="code-snippet__string">'‐'</span><span class="code-snippet__string">"\b\c"</span></span></code><code><span class="code-snippet_outer"> sleep <span class="code-snippet__variable">$INTERVAL</span></span></code><code><span class="code-snippet_outer"> ;;</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__string">"2"</span>) <span class="code-snippet__comment">#值为 2 显示\\,第一个\是转义</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> -e <span class="code-snippet__string">'\\'</span><span class="code-snippet__string">"\b\c"</span></span></code><code><span class="code-snippet_outer"> sleep <span class="code-snippet__variable">$INTERVAL</span></span></code><code><span class="code-snippet_outer"> ;;</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__string">"3"</span>) <span class="code-snippet__comment">#值为 3 显示|</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> -e <span class="code-snippet__string">"|\b\c"</span></span></code><code><span class="code-snippet_outer"> sleep <span class="code-snippet__variable">$INTERVAL</span></span></code><code><span class="code-snippet_outer"> ;;</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__string">"4"</span>) <span class="code-snippet__comment">#值为 4 显示/</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> -e <span class="code-snippet__string">"/\b\c"</span></span></code><code><span class="code-snippet_outer"> sleep <span class="code-snippet__variable">$INTERVAL</span></span></code><code><span class="code-snippet_outer"> ;;</span></code><code><span class="code-snippet_outer"> *) <span class="code-snippet__comment">#值为其他时,将 COUNT 重置为 0</span></span></code><code><span class="code-snippet_outer"> COUNT=<span class="code-snippet__string">"0"</span>;;</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">esac</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">done</span></span></code><code><span class="code-snippet_outer">}</span></code><code><span class="code-snippet_outer">rotate_line</span></code></pre> </section> <p>17、9*9 乘法表</p> <p><br></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <pre class="code-snippet__js" data-lang="bash"><code><span class="code-snippet_outer"><span class="code-snippet__meta">#!/bin/bash</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 9*9 乘法表(编写 shell 脚本,打印 9*9 乘法表) </span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">for</span> i <span class="code-snippet__keyword">in</span> `seq 9`</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">do</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">for</span> j <span class="code-snippet__keyword">in</span> `seq <span class="code-snippet__variable">$i</span>`</span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">do</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> -n <span class="code-snippet__string">"<span class="code-snippet__variable">$j</span>*<span class="code-snippet__variable">$i</span>=$[i*j] "</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__keyword">done</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">done</span></span></code><code><span class="code-snippet_outer">18、使用死循环实时显示 eth0 网卡发送的数据包流量</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"><span class="code-snippet__meta">#!/bin/bash</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 使用死循环实时显示 eth0 网卡发送的数据包流量 </span></span></code><code><span class="code-snippet_outer"> </span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">while</span> :</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">do</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">'本地网卡 eth0 流量信息如下: '</span></span></code><code><span class="code-snippet_outer"> ifconfig eth0 | grep <span class="code-snippet__string">"RX pack"</span> | awk <span class="code-snippet__string">'{print $5}'</span></span></code><code><span class="code-snippet_outer"> ifconfig eth0 | grep <span class="code-snippet__string">"TX pack"</span> | awk <span class="code-snippet__string">'{print $5}'</span></span></code><code><span class="code-snippet_outer"> sleep 1</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">done</span></span></code></pre> </section> <p>19、使用 user.txt 文件中的人员名单,在计算机中自动创建对应的账户并配置初始密码本脚本执行,需要提前准备一个 user.txt 文件,该文件中包含有若干用户名信息</p> <p><br></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <pre class="code-snippet__js" data-lang="bash"><code><span class="code-snippet_outer"><span class="code-snippet__meta">#!/bin/bash</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 使用 user.txt 文件中的人员名单,在计算机中自动创建对应的账户并配置初始密码</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 本脚本执行,需要提前准备一个 user.txt 文件,该文件中包含有若干用户名信息</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">for</span> i <span class="code-snippet__keyword">in</span> `cat user.txt`</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">do</span></span></code><code><span class="code-snippet_outer"> useradd <span class="code-snippet__variable">$i</span></span></code><code><span class="code-snippet_outer"> <span class="code-snippet__built_in">echo</span> <span class="code-snippet__string">"123456"</span> | passwd ‐‐stdin <span class="code-snippet__variable">$i</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">done</span></span></code></pre> </section> <section> 20、编写批量修改扩展名脚本 </section> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> <pre class="code-snippet__js" data-lang="bash"><code><span class="code-snippet_outer"><span class="code-snippet__meta">#!/bin/bash</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 编写批量修改扩展名脚本,如批量将 txt 文件修改为 doc 文件 </span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 执行脚本时,需要给脚本添加位置参数</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 脚本名 txt doc(可以将 txt 的扩展名修改为 doc)</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__comment"># 脚本名 doc jpg(可以将 doc 的扩展名修改为 jpg)</span></span></code><code><span class="code-snippet_outer"> </span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">for</span> i <span class="code-snippet__keyword">in</span> `ls *.<span class="code-snippet__variable">$1</span>`</span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">do</span></span></code><code><span class="code-snippet_outer"> mv <span class="code-snippet__variable">$i</span> <span class="code-snippet__variable">${i%.*}</span>.<span class="code-snippet__variable">$2</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__keyword">done</span></span></code></pre> </section> <p></p> <strong style="font-size: 17px;text-align: justify;color: rgb(51, 51, 51);max-width: 100%;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p><br></p></strong> <strong style="font-size: 17px;text-align: justify;color: rgb(51, 51, 51);max-width: 100%;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;">关注波哥,分享最有用的东西!</strong> <p style="font-weight: 400;"><span style="font-size: 17px;"><strong style="max-width: 100%;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">江湖规矩:如文章对您有帮助,请帮波哥转发分享、点赞哦!</strong></span><br></p> </section> <section style="font-weight: 400;font-size: 16px;text-align: center;margin: 10px 0% 0px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;width: 250px;height: 95px;vertical-align: top;overflow: hidden;background-position: 50% 50%;background-repeat: no-repeat;background-size: contain;background-attachment: scroll;line-height: 1.6;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/SRBEicJEW1Q08QPtycF0aCIOhuiceSjWXCWDsK48icPCibjkZicF9GsnSiczSVQpKeOpMHzkBibaoibNTkhrOy8JcSAPZw/640?wx_fmt=png");box-sizing: border-box;"> <section style="margin: 15px 0% 0px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="font-size: 14px;line-height: 1.5;box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">扫码关注<br></p> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">绝对干货的公众号</p> </section> </section> </section> <br> </section> <section style="font-weight: 400;font-size: 16px;text-align: center;margin: 10px 0%;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;vertical-align: middle;width: 8%;box-sizing: border-box;"> <section style="margin: 0px 0%;box-sizing: border-box;" powered-by="xiumi.us"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;"> <img data-ratio="0.7434944" data-w="269" src="/upload/e6cbcf3697ad6e50610fecf01ccf25e3.gif" style="vertical-align: middle;max-width: 100%;box-sizing: border-box;" data-type="gif"> </section> </section> </section> <section style="display: inline-block;vertical-align: middle;width: 35%;box-sizing: border-box;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;"> <img data-ratio="1" data-w="344" src="/upload/fec8378b8286f808184c5e6d215ff424.jpg" style="vertical-align: middle;max-width: 100%;box-sizing: border-box;" data-type="jpeg"> </section> </section> </section> <section style="display: inline-block;vertical-align: middle;width: 8%;box-sizing: border-box;"> <section style="margin: 0px 0%;box-sizing: border-box;" powered-by="xiumi.us"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;"> <img data-ratio="0.7434944" data-w="269" src="/upload/f82ac25cbcf86584002fe49c162dafe4.gif" style="vertical-align: middle;max-width: 100%;box-sizing: border-box;" data-type="gif"> </section> </section> </section> </section> <section style="font-weight: 400;font-size: 16px;color: rgb(227, 46, 46);font-family: PingFangTC-ultralight;box-sizing: border-box;" powered-by="xiumi.us"> <p style="white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><br></p> </section> <section powered-by="xiumi.us" style="font-weight: 400;font-size: 16px;max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(227, 46, 46);font-family: PingFangTC-ultralight;overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;">推荐阅读</p> </section> <section powered-by="xiumi.us" style="font-weight: 400;font-size: 16px;max-width: 100%;box-sizing: border-box;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <a title="https://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484733&idx=1&sn=8a5fcad29d0fea680f8ba93fea44c0da&chksm=fe7b0a01c90c8317e174ca316b1c15dd11bdfe41f1c70b3331576683ca87a0d2e8de267b99ad&token=1047100134&lang=zh_CN&scene=21#wechat_redirect" formlinkparm=""https://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484733&idx=1&sn=8a5fcad29d0fea680f8ba93fea44c0da&chksm=fe7b0a01c90c8317e174ca316b1c15dd11bdfe41f1c70b3331576683ca87a0d2e8de267b99ad&token=1047100134&lang=zh_CN&scene=21#wechat_redirect"" href="https://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484733&idx=1&sn=8a5fcad29d0fea680f8ba93fea44c0da&chksm=fe7b0a01c90c8317e174ca316b1c15dd11bdfe41f1c70b3331576683ca87a0d2e8de267b99ad&token=1047100134&lang=zh_CN&scene=21#wechat_redirect" target="_blank" rel="noopener noreferrer" data-linktype="2" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;font-size: 12px;overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"></p> </section></a> </section> <section powered-by="xiumi.us" style="font-weight: 400;font-size: 12px;max-width: 100%;box-sizing: border-box;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><br></p> </section> <section powered-by="xiumi.us" style="font-weight: 400;font-size: 12px;white-space: normal;box-sizing: border-box;"> <p style="box-sizing: border-box;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484673&idx=1&sn=f1c6fd7c00049734ed97121b5c401c6a&chksm=fe7b0a3dc90c832b226d1df991f413a4dfaebce8c4be4549ebd777a688e08f61f651b1bcd337&scene=21#wechat_redirect" textvalue="实战项目--kkitDeploy(客户端版)(强推)" data-itemshowtype="0" tab="innerlink" data-linktype="2">实战项目--kkitDeploy(客户端版)<span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);">(强推<span style="letter-spacing: 0.544px;">,已开源</span>)</span></a></p> <p style="box-sizing: border-box;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485054&idx=1&sn=76b2afbaa98227a0efb06e1c5e53be17&chksm=fe7b0942c90c8054172c8ca3020ddeb28d32cee3d3807efc6e7c9b063d128ee31dcdc831f457&scene=21#wechat_redirect" textvalue="实战项目--kkitDeploy(PaaS版)(强推)" data-itemshowtype="0" tab="innerlink" data-linktype="2"><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);">实战项目--kkitDeploy(PaaS版)<span style="letter-spacing: 0.544px;">(强推)</span></span></a></p> <p style="box-sizing: border-box;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484871&idx=1&sn=eea93b8ec270325f961e41038eade6d4&chksm=fe7b0afbc90c83ed0251453b69c1ac0e48db7444dd27caf8d8830b03235190cb7802058c64b6&scene=21#wechat_redirect" textvalue="实战项目--kkit3.0功能介绍(强推)" data-itemshowtype="0" tab="innerlink" data-linktype="2"><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);">实战项目--kkit3.0<span style="letter-spacing: 0.544px;">功能介绍(强推)</span></span></a></p> <p style="box-sizing: border-box;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247483880&idx=1&sn=5a38522f8639330a62fd8bd1fe032972&chksm=fe7b0ed4c90c87c26e4444cf21254dc613258082b28b4a6707a041edadb982ab0d13b994749a&scene=21#wechat_redirect" textvalue="实战项目--kkit1.0功能介绍(强推,已开源)" data-itemshowtype="0" tab="innerlink" data-linktype="2"><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;background-color: rgb(255, 255, 255);letter-spacing: 0.544px;">实战项目--kkit1.0<span style="letter-spacing: 0.544px;">功能介绍(强推,已开源)</span></span></a></p> </section> <section powered-by="xiumi.us" style="font-weight: 400;font-size: 16px;white-space: normal;max-width: 100%;box-sizing: border-box;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;font-size: 12px;overflow-wrap: break-word !important;"> <section powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;font-size: 16px;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;font-size: 12px;overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484768&idx=1&sn=4016a88bc54e9fe67b7b6d76fa3cedb4&chksm=fe7b0a5cc90c834ae4e95f951324ffe2a9991b502da194c507c6d02b7b277403f00fcc123940&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">面试题之---网络安全(2019年10月更新)</a></p> </section> </section> <section powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;font-size: 16px;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;font-size: 12px;overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484733&idx=1&sn=8a5fcad29d0fea680f8ba93fea44c0da&chksm=fe7b0a01c90c8317e174ca316b1c15dd11bdfe41f1c70b3331576683ca87a0d2e8de267b99ad&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">面试题之---k8s(2019年10月更新)</a></p> </section> </section> <section powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;font-size: 16px;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;font-size: 12px;overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484360&idx=1&sn=b0f6bdca5a3f4f4ac3c53c9f1ef9cbc9&chksm=fe7b0cf4c90c85e2ee1afb0571603426ab172c5c2e1d85d4763b086a562f5673973d4230e17a&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">面试题之---运维工程师经典面试汇总(一)</a></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;overflow-wrap: break-word !important;"><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484747&idx=1&sn=b49dfe531c0c1331200a7e4947f65976&chksm=fe7b0a77c90c8361f2ac4f3784681c7580c3699bf0f49d930b56999a2bd8e3e62fa3e6c9b521&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" hasload="1" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">经历贴之---外包接活却坐牢456天完整记录(强推)</a></p> </section> </section> </section> </section> <section powered-by="xiumi.us" style="font-weight: 400;font-size: 16px;white-space: normal;max-width: 100%;box-sizing: border-box;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;font-size: 12px;overflow-wrap: break-word !important;"> <p><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484455&idx=1&sn=da41f73724909d3051343133cd53db74&chksm=fe7b0b1bc90c820d954f649d76be230f651d62431858eb06bae8f5deaa36e66339f515116373&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2">脚本之---短信轰炸机</a></p> <p><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484740&idx=1&sn=0683fbf63643218045c1b8cd522137ec&chksm=fe7b0a78c90c836e85c254cce4b8c6897579fd4f6a1386b59084b6fe4cfdd3a72bbcbfbce96f&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">脚本之---QQ微信轰炸机</a></p> <p><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484909&idx=1&sn=27ab3125be7e9fd31e93fa1cb30bd3ae&chksm=fe7b0ad1c90c83c7158a5679dec8d987a1f05f933efd4073d15ef83a98e897666ed88c235e2f&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2">脚本之---linux流量监控利器</a><br></p> <p><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484957&idx=1&sn=ad4f9320dfd49a0c7a54042a20bb66c0&chksm=fe7b0921c90c8037a273419352a5677461e9895ca945bd6e33fae2fc401443c6c7a34ef355d9&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2">脚本之---linux系统巡检脚本合集</a></p> <p><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485039&idx=1&sn=ddd14e33325dfd99ac61ee83a4fc198c&chksm=fe7b0953c90c8045e6de3e39cc83b53e067d1a19a051dd17129e8ec2386b36adc9c4d6d1589d&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2">脚本之---linux批量用户管理脚本</a></p> <p><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485046&idx=1&sn=ee3e7a258eafcce88aa65e3daa3fd7be&chksm=fe7b094ac90c805c6ed4e8eb16a698fee1e1b467e948b0e86288aa39cbfebd48ee5e383594c1&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2">脚本之---根据PID查看相关信息</a></p> <p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485065&idx=1&sn=8913154de8cb68c4679d5a40957eaf18&chksm=fe7b09b5c90c80a323324d176c0be3a3370f1ee3fc9d05625937b7d8c0df206c2e23b6c4773a&scene=21#wechat_redirect" textvalue="脚本之---一键完成系统安全加固" data-itemshowtype="0" tab="innerlink" data-linktype="2">脚本之---一键完成系统安全加固</a></p> <p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485059&idx=1&sn=f4671cd621367c9faf5d697b181e351a&chksm=fe7b09bfc90c80a9d89b23553d1366d17686dd5e3542a17df738d9ead2274fb104943237bc5b&scene=21#wechat_redirect" textvalue="脚本之---检查系统用户" data-itemshowtype="0" tab="innerlink" data-linktype="2">脚本之---检查系统用户</a></p> <p><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485014&idx=1&sn=a633abf6ec6137240528957a16de2f33&chksm=fe7b096ac90c807c09b7881315263c7d6cf87f0fa038d4159b00c2518e5bce619fe2bf68faea&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2">脚本之---一键同步脚本文件夹</a></p> <p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485111&idx=1&sn=6332d3366f992980cd16862e9974b3c0&chksm=fe7b098bc90c809d65219f1ffe51a03c68c76615bbef5beed46ec59bbea805e1e5d1eb8d8409&scene=21#wechat_redirect" textvalue="脚本之---一键升/降级k8s集群脚本" data-itemshowtype="0" tab="innerlink" data-linktype="2">脚本之---一键升/降级k8s集群脚本</a></p> <p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485122&idx=1&sn=d88e6ae5a5327b783c9c7e26fe4615ac&chksm=fe7b09fec90c80e8c61c6e76b6ac514457e9872871a7bb0b6f285297b676307b99bde99278bb&scene=21#wechat_redirect" textvalue="脚本之---一键升新增k8s集群node节点脚本" data-itemshowtype="0" tab="innerlink" data-linktype="2">脚本之---一键升新增k8s集群node节点脚本</a></p> <p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485128&idx=1&sn=3adf091282012695ac2b7d6aadfe00c3&chksm=fe7b09f4c90c80e287710850a2d4912cdea3484537b511c1451a30cd5767d1e7b1af90bbd660&scene=21#wechat_redirect" textvalue="脚本之---k8s一键部署脚本(多版本通用版)" data-itemshowtype="0" tab="innerlink" data-linktype="2">脚本之---k8s一键部署脚本(多版本通用版)(强推)</a></p> <p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485159&idx=1&sn=a0516b2fb0197e8bd603cbb225d96cf1&chksm=fe7b09dbc90c80cd9fcebdf2285b48d50fd6bdda812565769b413da6b806411e5d634c4ba119&scene=21#wechat_redirect" textvalue="脚本之---一键部署ceph(luminous)集群脚本" data-itemshowtype="0" tab="innerlink" data-linktype="2">脚本之---一键部署ceph(luminous)集群脚本</a></p> <p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485197&idx=1&sn=5225f0b73fd496332db24f5cded6c87f&chksm=fe7b0831c90c8127d737569822b00319193fb733a452f65c1e5eb936bc08aa914dcdf584850d&scene=21#wechat_redirect" textvalue="脚本之---一键部署openvpn脚本" data-itemshowtype="0" tab="innerlink" data-linktype="2"><span style="letter-spacing: 0.544px;">脚本之---一键部署openvpn脚本</span></a><br></p> <p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485203&idx=1&sn=7a4d5359527a6b8be6e7840e2db7fe25&chksm=fe7b082fc90c813968dd6c244bb86b72deb8d68f81b02b7578dfe98db5deb5517ff7d755c747&scene=21#wechat_redirect" textvalue="脚本之---一键(单双向)互信初始化服务器脚本" data-itemshowtype="0" tab="innerlink" data-linktype="2"><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);">脚本之---一键(单双向)互信初始化服务器脚本</span></a></p> <p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485388&idx=1&sn=d12267364d1066de084b3a02e55da1f0&chksm=fe7b08f0c90c81e6044cea65f30026207dd4bf95098cdb01caf77f371038da8bdcc876b39ce5&scene=21#wechat_redirect" textvalue="脚本之---一键初始化调优服务器脚本" data-itemshowtype="0" tab="innerlink" data-linktype="2">脚本之---一键初始化调优服务器脚本</a></p> <p><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484965&idx=1&sn=50455d6e48c8e58f98a1b2b9ea3c0ae1&chksm=fe7b0919c90c800f7a49d154072edc20a5cee3aca7dbd4e1e292b35664417d0acabfab7e58ff&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2">脚本之---zabbixAgent一键部署脚本(windos/linux)</a></p> <p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247485248&idx=1&sn=1134c6914570f1b5ad657cb0864d14d1&chksm=fe7b087cc90c816a7b172c552061370bc6db54679af785dbc899580a66d1e4b227c783b66409&scene=21#wechat_redirect" textvalue="ansible---一键搭建redis5.0.5集群" data-itemshowtype="0" tab="innerlink" data-linktype="2">ansible---一键搭建redis5.0.5集群</a></p> <p><a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247483959&idx=1&sn=f1c132a3f3ef3c2cf53166d92bbb1c81&chksm=fe7b0d0bc90c841d865c6ada6ad1b1747636b2ca719906ce5faf36a4775b595fb83cdcbd7988&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2">工具之---地表最强CMDB自动抓取工具</a><br></p> <p><br></p> </section> </section> <section powered-by="xiumi.us" style="font-weight: 400;font-size: 16px;margin-top: 10px;margin-bottom: 10px;white-space: normal;text-align: right;box-sizing: border-box;"> <a href="http://mp.weixin.qq.com/s?__biz=MzU5NDg5MzM5NQ==&mid=2247484740&idx=1&sn=0683fbf63643218045c1b8cd522137ec&chksm=fe7b0a78c90c836e85c254cce4b8c6897579fd4f6a1386b59084b6fe4cfdd3a72bbcbfbce96f&scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2" style="background-color: rgb(255, 255, 255);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;text-align: justify;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></a> <br> </section> <section style="font-weight: 400;font-size: 16px;margin-top: 10px;margin-bottom: 10px;text-align: right;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;vertical-align: middle;box-sizing: border-box;"> <section style="display: inline-block;vertical-align: bottom;padding-left: 5px;padding-right: 5px;line-height: 1.2em;margin-bottom: 2px;color: rgb(121, 121, 121);box-sizing: border-box;"> <p style="margin: 0px;padding: 0px;box-sizing: border-box;">点小花花,让他们知道你<span style="color: rgb(139, 207, 224);box-sizing: border-box;"><strong style="box-sizing: border-box;">“在看”</strong></span>我</p> </section> <section style="max-width: 100%;display: inline-block;vertical-align: bottom;line-height: 0;width: 8%;box-sizing: border-box;"> <img data-ratio="1.321875" data-w="320" src="/upload/5103810f55f9d6b6b422944c97ec479e.gif" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" width="100%" data-type="gif"> </section> </section> </section> </section>
作者:微信小助手
<section> <h2> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="padding-top: 10px;padding-right: 10px;padding-left: 10px;background-color: rgb(239, 239, 239);box-sizing: border-box;"> <span style="display: inline-block;width: 5%;line-height: 0.8;font-weight: bolder;font-size: 48px;box-sizing: border-box;" title="" opera-tn-ra-cell="_$.pages:0.layers:0.comps:0.txt1"> <section style="box-sizing: border-box;"> “ </section></span> <section style="display: inline-block;vertical-align: top;float: right;width: 90%;line-height: 1.5;font-size: 15px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;">前几天,临近五一节,想到有 5 天假期,我就开始飘了。于是写个简单的 Bash 脚本都不上心了,写完后检都不检查,直接拖到到实体服务器跑。</span></p> </section> <section style="clear: both;box-sizing: border-box;line-height: 0;"> <section style="line-height: 0;width: 0px;"> <svg viewbox="0 0 1 1" style="vertical-align:top;"></svg> </section> </section> </section> </section> </section><p style="line-height: 1.75em;"><br></p></h2> <section style="text-align: center;margin-left: 8px;margin-right: 8px;"> <img class="rich_pages" data-ratio="0.5787278415015641" data-s="300,640" src="/upload/12d6cb6b67dad1f4f4a905f405ccbce4.png" data-type="png" data-w="959" style=""> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;"><em>图片来自 Pexels</em></span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">结果一跑起来,发生不对劲,怎么一个简单脚本跑了 10 秒还没结束,于是立马 Ctrl+C 一顿操作停掉了运行中的脚本。</span></p> <section style="text-align: center;margin-bottom: 5px;"> <img class="rich_pages" data-ratio="0.626" data-s="300,640" src="/upload/f3449d9520efe8950760e6817a6f2b45.jpg" data-type="jpeg" data-w="500" style=""> </section> </section> <section style="margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"> <span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">接着,习惯性的输入了 ls,结果 what?找不到 ls 命令?</span> </section> <section style="text-align: center;margin-bottom: 5px;"> <img class="rich_pages" data-ratio="0.3181818181818182" data-s="300,640" src="/upload/b8b0ccb453e9299d5dcb788a6df24904.png" data-type="png" data-w="506" style=""> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">瞬间背后一凉,慌慌张张打开了脚本。发现问题了,我写了个巨蠢的 Bug,间接执行了 rm -fr /* ,这不意味着我删库了?</span> </section> <section style="text-align: center;margin-bottom: 5px;"> <img class="rich_pages" data-ratio="0.8204545454545454" data-s="300,640" src="/upload/2cd7ffbc11c1cb7bf13ae01a9ec0bb24.jpg" data-type="jpeg" data-w="440" style=""> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这台是公司的授权服务器呀,被我这么一整,公司历史的授权记录和其他重要信息不就丢了?</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">心里慌的一批的我,跟我的朋友们说了这件事,朋友建议我先第一时间上报给 Leader,不要把删库的事情瞒着。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">于是,我就向 Leader 说了我删库事情,本以为会被痛批一顿。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">结果 Leader 笑着说:“没事,你先看看重要的文件还在不在。不过你这么一整,我突然想起编译服务器半年没备份,我先备份一下我的编译服务器,防止哪天也被你们删库了。”</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我:“????”</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">吃瓜的小伙伴,是不是觉得我要删库跑路了?哈哈哈,我没跑路,反而是恢复了回来,所以接下来说说我是如何从删库到恢复的。</span></p> <section style="line-height: normal;"> <br> </section> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;border-top-color: rgb(89, 89, 89);border-right-color: rgb(89, 89, 89);border-left-color: rgb(89, 89, 89);font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">初探案发现场</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">先来看看我写的垃圾代码,是如何引发这次的删库:</span> </section> <section style="text-align: center;margin-bottom: 5px;"> <img class="rich_pages" data-ratio="0.2917547568710359" data-s="300,640" src="/upload/27a29a6a0431812a9af904349f12333e.jpg" data-type="jpeg" data-w="473" style=""> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">既然发生了 rm -fr /* 的现象,那必然 new_lic_dir 这个变量是空的。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">所以导致执行 rm -fr $new_lic_dir/* 这条语句的时候,变成了 rm -fr /* 删库语句。很好,凶器找到了。</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">那为什么 new_lic_dir 会是空的呢?细心的小伙伴肯定察觉出来了,是因为给 new_lic_dir 变量赋值的时使用了反引号。</span> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-ratio="0.27906976744186046" data-s="300,640" src="/upload/f1a2629083e5e6b096ece933208bb624.jpg" data-type="jpeg" data-w="559" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">没错,就是反引号的原因。</span><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">反引号在 Linux Shell 命令行中有特殊的含义:反引号间的内容,会被 Shell 先执行。其输出被放入主命令后,主命令再被执行。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">也就是说, new_lic_dir 的值是 ${lic_path}/new_license 这条命令执行的结果,问题这哪是命令啊,所以肯定返回空值给 new_lic_dir 变量。</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我写的那么温柔的代码,竟然变成了穷凶极恶的删库代码。</span> </section> <section style="text-align: center;margin-bottom: 5px;"> <img class="rich_pages" data-ratio="0.954" data-s="300,640" src="/upload/cb95b0612b41f0909bdaa967c02d139e.jpg" data-type="jpeg" data-w="500" style=""> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这下原因是找到了,反引号应该改成双引号才对。(内心 OS:你真菜呀,那么简单的赋值命令都写错!)</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">哈哈哈,确实菜,都说了嘛,快五一了,是飘着写这份代码的。</span><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">所以习惯性开启程序员内容的第一大武功:Crtl+C 和 Crtl+V。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">把第一条赋值 lic_path=`pwd` 语句,复制粘贴了,然后只改了变量名,没注意反引号要修改成双引号,所以造成了删库的悲剧。</span></p> <section style="line-height: normal;"> <br> </section> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;border-top-color: rgb(89, 89, 89);border-right-color: rgb(89, 89, 89);border-left-color: rgb(89, 89, 89);font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">保留案发现场</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">既然发生了删库的事情,千万不要重启服务器,也不要关闭 SSH 连接的会话,而是要保留案发现场,接着查查还剩什么。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">PS:这不是吹大炮嘛?ls 都没了,还怎么查?</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">还好这次是比较幸运,因为在执行脚本的时候,第一时间发现不对劲,立马掐断了还在运行的脚本,所以并非 Linux 所有文件都被删除了。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">只要我掐的快,rm -fr /* 就干不死我。</span><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">虽然 ls 被删了,但所幸发现 cd 命令还能用。</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">只要 cd 用的好,它也能用出的 ls 效果。很简单,只需 cd + Tab 键就会自动出现指定目录下的所有文件。</span> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-ratio="0.48148148148148145" data-s="300,640" src="/upload/c2f3015b571c82d79f3a963017d9bee2.png" data-type="png" data-w="2484" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">有了 cd+Tab 键,我们就可以查看每个目录下的文件,于是就可以一步一步来确认哪些系统文件被删了。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">通过一番的确认和对比后,发现主要被删除的有四个目录分别是:</span></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">/bin 、/boot 、/dev 这三个目录整个都被删除了。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">/lib 目录里的动态库部分被删除。</span></p></li> </ul> <p style="text-align: justify;line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">来复习下上面这四个目录主要是存放了什么:</span> </section> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">/bin 存放常用系统命令,ls、cp、rm、chmod 等常用命令都在此目录。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">/boot 系统启动目录,保存与系统启动相关的文件,如内核文件和启动引导程序。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">/dev 设备文件保存位置。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">/lib 存放程序所需的动态库和静态库文件。</span></p></li> </ul> <p style="text-align: justify;line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">/boot 都被删除了,还好小林没有重启服务器,要是重启了服务器,就完犊子了,系统肯定起不来了。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">cd 命令是在 /sin 目录下,/sin 还健全,所以 cd 是可以正常使用。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">所幸重要的数据库信息和文件都还没删除,所以小林首要的目标是要恢复 /bin、/boot、/dev、/lib 这四个目录。</span> </section> <p style="line-height: normal;"><br></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;border-top-color: rgb(89, 89, 89);border-right-color: rgb(89, 89, 89);border-left-color: rgb(89, 89, 89);font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">还原文件</p> </section> </section> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">由于 /bin 目录 和 /lib 部分动态文件被删除,常用的传递文件的方式是无法使用的,如 ftp、scp、mount 等。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我摸索了很久,竟然发现 wget 可以使用,wget 命令是在 /usr/bin 目录,所幸 /usr/bin 还健全。</span> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">于是,用了取巧的方法,先另一台正常的服务器,把 /bin 目录放到了 Web 服务器的 Web 目录,接着通过 wget 进行下载。</span></p> <section style="text-align: center;margin-bottom: 5px;margin-left: 8px;margin-right: 8px;"> <img class="rich_pages" data-ratio="0.14122137404580154" data-s="300,640" src="/upload/c666701d5a43f1956a43c90581124950.png" data-type="png" data-w="1572" style=""> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">有戏,看到了成功的曙光。</span> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">但是新的问题就来了,我下载过来的命令文件,是没有执行权限的。</span></p> <section style="text-align: center;margin-bottom: 5px;"> <img class="rich_pages" data-ratio="0.15161290322580645" data-s="300,640" src="/upload/27fd14a2726d2a3b769281f2cb06021e.png" data-type="png" data-w="310" style=""> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">而 chmod 命令是在 /bin 目录的,它同样也被删除了,无法使用它来给予文件权限。</span> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">还在,在网上搜到了一个伟大命令 perl,可以通过它来给予文件权限:</span></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">perl</span> -e <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">"chmod 777, 'ls'"</span><br></code></pre> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">真是个神奇的命令。</span> <span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">好了,这下赋值权限问题也解决了,成功在望了。</span> <br> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">wget 是无法直接把 /bin 目录下载下来的,只能下载一个文件。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">但是我不可能一个一个去下载来进行恢复,这得要何年何月才能完成......</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">于是我就想到了一个方法:</span> </section> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">先通过 wget 的方式下载 tar 命令,并通过 perl 给予 tar 命令权限。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">接着把另一台服务器把 /bin 目录打包成压缩文件,然后通过 wget 下载 bin 目录的压缩包文件。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">最后通过 tar 命令把 bin 压缩包解压出来。</span></p></li> </ul> <p style="text-align: justify;line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">/bin 就这样恢复回来啦,剩余的其他目录 也是通过同样的操作恢复了回来。</span> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我的笑容渐渐恢复了回来,哈哈哈哈哈哈哈哈哈哈哈哈!</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-ratio="0.8252631578947368" data-s="300,640" src="/upload/50114b261b09fa3f5385793b06a2126d.jpg" data-type="jpeg" data-w="475" style=""></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">遇到 rm -fr /* 删库事件发生,一定要沉住气,稳住心态!</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">本次删库事件,之所以能幸运的恢复回来,有非常关键两点:</span> </section> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">发现脚本执行不正常,果断立马的掐断它,没有造成重要的数据库信息被删除,如果掐断的时候再晚一点,可能就真没了。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">发现常用命令无法使用的时候,没有重启服务器,不然服务器就起不来了,也没有关闭 SSH 会话,不然无法在重新连接 SSH 会话了,也就无法进行操作了。</span></p></li> </ul> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如果以上两点都没做好,服务器恢复的难度就加大了很多,更严重的是五一节就没的过了。</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-ratio="0.5504587155963303" data-s="300,640" src="/upload/13b603a1f36bc6a0b97766a036c11a20.jpg" data-type="jpeg" data-w="545" style=""></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;border-top-color: rgb(89, 89, 89);border-right-color: rgb(89, 89, 89);border-left-color: rgb(89, 89, 89);font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">预防误执行 rm -fr /*</p> </section> </section> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">既然 rm -fr /* 是残忍的凶器,那么预防它是很有必要的,接下来跟大家讨论讨论预防它的几种方案。</span> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <strong><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">方案一:rm -rf 删除目录时要判断目录</span></strong> </section> <p style="line-height: normal;"><br></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);word-wrap: inherit !important;word-break: inherit !important;">#!/bin/bash<br></span><br>work_path=`<span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">pwd</span>`<br><br><span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);word-wrap: inherit !important;word-break: inherit !important;">#如果目录不为空,才执行删除操作</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">if</span> [ <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);word-wrap: inherit !important;word-break: inherit !important;">${work_path}</span> != <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">""</span> ];<span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">then</span><br> rm -fr <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);word-wrap: inherit !important;word-break: inherit !important;">${work_path}</span>/*<br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">fi</span><br></code></pre> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">在执行删除目录操作前,先判断要删除的目录是否为空,不为空才执行删除操作。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <strong><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">方案二:Shell 脚本指定 set -u</span></strong> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">执行脚本的时候,如果遇到不存在的变量,Bash 默认忽略它。</span></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);word-wrap: inherit !important;word-break: inherit !important;">#!/bin/bash<br></span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">echo</span> <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);word-wrap: inherit !important;word-break: inherit !important;">$a</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">echo</span> hello<br></code></pre> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">上面代码中,$a 是一个不存在的变量,执行结果如下。</span></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">$ bash test.sh<br><br>hello<br></code></pre> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">可以发现,echo $a 输出了一个空行,Bash 忽略了不存在的 $a,然后继续执行 echo hello。</span> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">最好是遇到变量不存在,脚本应该报错,而不是一声不响地往下执行。</span> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">set -u 就用来改变这种行为,在脚本加上它,遇到不存在的变量就会报错,并停止执行。</span></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);word-wrap: inherit !important;word-break: inherit !important;">#!/bin/bash</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">set</span> -u<br><br>rm -fr <span style="font-size: inherit;line-height: inherit;color: rgb(98, 151, 85);word-wrap: inherit !important;word-break: inherit !important;">$a</span>/*<br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">echo</span> hello<br></code></pre> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">运行结果如下:</span></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">$ bash test.sh<br><span style="font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);word-wrap: inherit !important;word-break: inherit !important;">test.sh: line 4: a: unbound variable</span><br></code></pre> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">可以看到,因为 a 是未定义变量,脚本报错了,并且不再执行后面的语句。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <strong><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">方案三:safe-rm 替换 rm</span></strong> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">safe-rm 是一个开源软件工具,这名字听起来就很安全嘛,所以它是用来替代不太安全的 rm。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">它可以在 /etc/safe-rm.conf 中配置路径黑名单,定义哪些不能被 safe-rm 删除。</span> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我们可以将 safe-rm 更名为 rm,假设定义了 /etc/ 无能被删除,那么删除 /etc 时就会报错:</span></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">$ rm -rf <span style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">/etc/</span><br>safe-rm: skipping <span style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">/etc/</span><br></code></pre> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <strong><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">方案四:建立回收站机制</span></strong> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Windows 是有回收站的,即使误删了,也可以在回收站恢复。</span> <span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">所以,我们也可以在 Linux 实现回收站的机制。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">实现思路:</span> </section> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">删除文件时,它并不真正执行删除操作,而是将文件移动到一个特定目录,可以设置定时清除回收站,或者在回收站里面的文件大小达到一定容量时(或者用时间做判断)执行删除操作以腾出空间。</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">可以写个 Shell 脚本替换 rm 命令,或者在需要删除文件的时候使用 mv 命令将文件移动到回收站。 </span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">① 创建回收站目录</span></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">mkdir <span style="font-size: inherit;color: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;">/home/</span>.trash<br></code></pre> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">② 编写 remove.sh 脚本,内容如下:</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-ratio="0.6710775047258979" data-s="300,640" src="/upload/a7da7b5ab0eac8c970de8632df479710.png" data-type="png" data-w="2116" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">③ 修改 ~/.bashrc, 用我们自建的 remove.sh 替代 rm 命令:</span></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">alias</span> rm=<span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);word-wrap: inherit !important;word-break: inherit !important;">"sh /home/remove.sh"</span><br></code></pre> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">④ 设置 crontab,定期清空垃圾箱,如每天 0 点清空垃圾箱:</span></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">0 0 <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">* *</span> <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">* rm -rf /home/.trash/*</span><br></code></pre> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">⑤ 最后,执行以下命令,使之生效:</span></p> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">source</span> ~/.bashrc <br></code></pre> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <strong><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">方案五:根文件挂载成只读</span></strong> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">在 /etc/fstab 文件,把 / 文件系统挂载成只读的方式。</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-ratio="0.4253164556962025" data-s="300,640" src="/upload/5cf60f3ca3eb154d0e2449520f0ae9c8.png" data-type="png" data-w="3160" style=""></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">其中 remount,ro,就表示只读的方式挂载。</span> </section> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">只读的方式挂载后,进行删除操作是无法成功的:</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-ratio="0.7722772277227723" data-s="300,640" src="/upload/869a74d85d77445c80957ff7c0d58888.png" data-type="png" data-w="606" style=""></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;border-top-color: rgb(89, 89, 89);border-right-color: rgb(89, 89, 89);border-left-color: rgb(89, 89, 89);font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">事后反思</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">涉及到 rm -fr 命令的代码,要留个心眼,要反复检查,要做好预防误执行 rm -fr /*,并在测试机验证完后,再拖到实体机上跑,千万不可大意。</span> </section> <p style="line-height: normal;"><br></p> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">就算的发生了 rm -fr /*,要第一时间停掉它,并且要做到三不要:</span> </section> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">不要慌,不要心跳爆炸(稳住稳住)</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">不要隐瞒删库事件(不丢人)</span></p></li> <li><p><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">不要重启服务器或断开 ssh 会话(保留现场)</span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">只要立马掐断 rm -fr /* ,它是干不死我们的。</span><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">利用当下环境剩有的命令,冷静分析,是有机会恢复的。</span></p> <section style="text-align: center;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"> <img class="rich_pages" data-ratio="1.662962962962963" data-s="300,640" src="/upload/bad0d8ea53695cfe5d27fced59b680be.jpg" data-type="jpeg" data-w="1080" style=""> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我现在是一个删过库没跑路的男人了,Goodbye, 我们下次见。</span> </section> <p style="line-height: normal;"><br></p> <p style="white-space: normal;line-height: 1.75em;"><span style="letter-spacing: 1px;color: rgb(89, 89, 89);"><em><span style="font-size: 14px;">作者:<em><span style="line-height: 27.2px;">小林</span></em></span></em></span></p> <p style="white-space: normal;line-height: 1.75em;"><span style="letter-spacing: 1px;color: rgb(89, 89, 89);"><em><span style="font-size: 14px;">编辑:陶家龙</span></em><br></span></p> <p style="white-space: normal;line-height: 27.2px;text-align: start;"><span style="color: rgb(89, 89, 89);"><em><span style="line-height: 1.75em;font-size: 14px;letter-spacing: 1px;">出处:转载自微信公众号</span><span style="font-size: 14px;letter-spacing: 0.544px;line-height: 20px;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">小林 coding(ID:CodingLin)</span></em></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.39375" src="/upload/eccf90ae5f48405df149baa3056d4bf3.gif" data-type="gif" data-w="640" style=""></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 0.5em;margin-bottom: 0.5em;box-sizing: border-box;" powered-by="xiumi.us"> <section style="font-size: 15px;border-style: solid;border-width: 0px 0px 1px;color: rgb(89, 89, 89);border-bottom-color: rgba(215, 215, 215, 0.960784);box-sizing: border-box;"> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;"><strong>精彩文章推荐:</strong></span></p> </section> </section> </section> <section style="line-height: 2em;"> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655830844&idx=3&sn=5d94cdd6653594e1d3f7edcb0458d56c&chksm=bd748eeb8a0307fd8fd654e05f2a88c5c9755f34d611625318c941d5b9b91510e78b71933c4a&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;" data-linktype="2"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">因用了Insert into select语句,同事被开除了!</span></a> <br> </section> <section style="line-height: 2em;"> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655830827&idx=1&sn=02b7bc0607d85c6a3303d13465f4c12b&chksm=bd748efc8a0307eaa1e4c63652f580fc7f0b4c7df7328148b7019383f0b6326dc0b25b241840&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;" data-linktype="2"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">MySQL它不香吗,为什么还要NoSQL?</span></a> <br> </section> <section style="line-height: 2em;"> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655830777&idx=1&sn=c32e919d0a694b65aa96555f280e782d&chksm=bd748f2e8a030638416600e3c7926731accb3fa8828b8088ed85729be48685f11fcf1727de09&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;" data-linktype="2"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">月均活跃用户达1.3亿,B站高可用架构实践</span></a> <br> </section>
作者:微信小助手
<section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 10px;margin-bottom: 10px;box-sizing: border-box;" powered-by="xiumi.us"> <section style="padding-top: 10px;padding-right: 10px;padding-left: 10px;background-color: rgb(239, 239, 239);box-sizing: border-box;"> <span style="display: inline-block;width: 5%;line-height: 0.8;font-weight: bolder;font-size: 48px;box-sizing: border-box;" title="" opera-tn-ra-cell="_$.pages:0.layers:0.comps:0.txt1"> <section style="box-sizing: border-box;"> “ </section></span> <section style="display: inline-block;vertical-align: top;float: right;width: 90%;line-height: 1.5;font-size: 15px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;">支持多线程的 Redis 6.0 版本于 2020-05-02 终于发布了,为什么 Redis 忽然要支持多线程?如何开启多线程?开启后性能提升效果如何?线程数量该如何设置?开启多线程后会不会有线程安全问题?多线程的实现原理是怎样的?带着这些疑问,我们来开启 Redis 新特性-多线程连环 13 问。</span></p> </section> <section style="clear: both;box-sizing: border-box;line-height: 0;"> <section style="line-height: 0;width: 0px;"> <svg viewbox="0 0 1 1" style="vertical-align:top;"></svg> </section> </section> </section> </section> </section> <section style="line-height: 1.75em;"> <br> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;"> <img class="rich_pages" data-ratio="0.6649214659685864" data-s="300,640" src="/upload/f1e011ad0adf99080cdf8db75431d760.png" data-type="png" data-w="955" style=""> </section> <section> <section> <section> <section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;"><em>图片来自 Pexels</em></span></p> <section style="line-height: normal;"> <br> </section> </section> </section> </section> </section> <section> <section powered-by="xiumi.us"> <section> <section> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;border-top-color: rgb(89, 89, 89);border-right-color: rgb(89, 89, 89);border-left-color: rgb(89, 89, 89);font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">Redis 6.0 来了</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> </section> </section> </section> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">在全国一片祥和 IT 民工欢度五一节假日的时候,Redis 6.0 不声不响地于 5 月 2 日正式发布了,吓得我赶紧从床上爬起来,学无止境!学无止境!</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">对于 6.0 版本,Redis 之父 Antirez 在 RC1 版本发布时(2019-12-19)在他的博客上连续用了几个“EST”词语来评价: </span> </section> <section style="box-sizing: border-box;font-size: 16px;"> <section style="text-align: center;margin-top: 0.5em;margin-bottom: 0.5em;box-sizing: border-box;" powered-by="xiumi.us"> <section style="border-color: rgb(204, 204, 204);box-shadow: rgb(102, 102, 102) 0.2em 0.2em 0.5em;padding: 10px;border-width: 3px;border-style: solid;box-sizing: border-box;"> <section style="text-align: left;color: rgb(89, 89, 89);font-size: 14px;box-sizing: border-box;" powered-by="xiumi.us"> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;"><em>the most “enterprise” Redis version to date // 最”企业级”的</em></span></p> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;"><em>the largest release of Redis ever as far as I can tell // 最大的</em></span></p> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;"><em>the one where the biggest amount of people participated // 参与人数最多的</em></span></p> </section> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这个版本提供了诸多令人心动的新特性及功能改进,比如新网络协议 RESP3,新的集群代理,ACL 等,其中关注度最高的应该是“多线程”了。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">笔者也第一时间体验了一下,带着众多疑问,我们来一起开始“Redis 6.0 新特性-多线程连环 13 问”。</span></p> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"><img class="rich_pages" data-ratio="0.4059500959692898" data-s="300,640" src="/upload/9d5f9482bfdd755ba1799790c3738bc0.png" data-type="png" data-w="1042" style="width: 527px;height: 214px;"></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="border-bottom: 1px solid black;margin-top: 0.5em;margin-bottom: 0.5em;line-height: 1.2;box-sizing: border-box;" powered-by="xiumi.us"> <section style="display: inline-block;border-bottom: 6px solid rgb(89, 89, 89);margin-bottom: -1px;border-top-color: rgb(89, 89, 89);border-right-color: rgb(89, 89, 89);border-left-color: rgb(89, 89, 89);font-size: 20px;color: rgb(89, 89, 89);box-sizing: border-box;"> <p style="box-sizing: border-box;">Redis 6.0 多线程连环13问</p> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">①Redis 6.0 之前的版本真的是单线程吗?</span></strong></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Redis 在处理客户端的请求时,包括获取(Socket 读)、解析、执行、内容返回(Socket 写)等都由一个顺序串行的主线程处理,这就是所谓的“单线程”。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">但如果严格来讲从 Redis 4.0 之后并不是单线程,除了主线程外,它也有后台线程在处理一些较为缓慢的操作,例如清理脏数据、无用连接的释放、大 Key 的删除等等。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">②Redis 6.0 之前为什么一直不使用多线程?</span></strong></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">官方曾做过类似问题的回复:使用 Redis 时,几乎不存在 CPU 成为瓶颈的情况, Redis 主要受限于内存和网络。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">例如在一个普通的 Linux 系统上,Redis 通过使用 Pipelining 每秒可以处理 100 万个请求,所以如果应用程序主要使用 O(N) 或 O(log(N)) 的命令,它几乎不会占用太多 CPU。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">使用了单线程后,可维护性高。多线程模型虽然在某些方面表现优异,但是它却引入了程序执行顺序的不确定性,带来了并发读写的一系列问题,增加了系统复杂度、同时可能存在线程切换、甚至加锁解锁、死锁造成的性能损耗。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Redis 通过 AE 事件模型以及 IO 多路复用等技术,处理性能非常高,因此没有必要使用多线程。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">单线程机制使得 Redis 内部实现的复杂度大大降低,Hash 的惰性 Rehash、Lpush 等等 “线程不安全” 的命令都可以无锁进行。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">③Redis 6.0 为什么要引入多线程呢?</span></strong></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Redis 将所有数据放在内存中,内存的响应时长大约为 100 纳秒,对于小数据包,Redis 服务器可以处理 80,000 到 100,000 QPS,这也是 Redis 处理的极限了,对于 80% 的公司来说,单线程的 Redis 已经足够使用了。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">但随着越来越复杂的业务场景,有些公司动不动就上亿的交易量,因此需要更大的 QPS。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">常见的解决方案是在分布式架构中对数据进行分区并采用多个服务器,但该方案有非常大的缺点,例如要管理的 Redis 服务器太多,维护代价大。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">某些适用于单个 Redis 服务器的命令不适用于数据分区;数据分区无法解决热点读/写问题;数据偏斜,重新分配和放大/缩小变得更加复杂等等。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">从 Redis 自身角度来说,因为读写网络的 Read/Write 系统调用占用了 Redis 执行期间大部分 CPU 时间,瓶颈主要在于网络的 IO 消耗。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">优化主要有两个方向:</span></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">提高网络 IO 性能,典型的实现比如使用 DPDK 来替代内核网络栈的方式。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">使用多线程充分利用多核,典型的实现比如 Memcached。</span></p></li> </ul> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">协议栈优化的这种方式跟 Redis 关系不大,支持多线程是一种最有效最便捷的操作方式。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">所以总结起来,Redis 支持多线程主要就是两个原因:</span></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">可以充分利用服务器 CPU 资源,目前主线程只能利用一个核。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">多线程任务可以分摊 Redis 同步 IO 读写负荷。</span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">④Redis 6.0 默认是否开启了多线程?</span></strong></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Redis 6.0 的多线程默认是禁用的,只使用主线程。如需开启需要修改 redis.conf 配置文件:io-threads-do-reads yes。</span> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <img class="rich_pages" data-croporisrc="/upload/d208814a0c9db25d62db6e4699f32c2b.png" data-cropx1="1.7098765432098766" data-cropx2="291.53395061728395" data-cropy1="79.50925925925927" data-cropy2="118.83641975308642" data-ratio="0.13793103448275862" data-s="300,640" src="https://mmbiz.qpic.cn/mmbiz_jpg/DkA0VYrOHvtWkvO02tIickx6ibOgCywvlibpOoSj6Fd9SaGQNcjsvDUHl2gVep84hxRDXmiaWIq8MLd07zWUPZTj3g/640?wx_fmt=jpeg" data-type="jpeg" data-w="290" style="width: 402px;height: 55px;"> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">⑤Redis 6.0 多线程开启时,线程数如何设置?</span></strong></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">开启多线程后,还需要设置线程数,否则是不生效的。同样修改 redis.conf 配置文件:</span> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <img class="rich_pages" data-ratio="0.142433234421365" data-s="300,640" src="/upload/1445afecaeb7748c155943101d61b738.png" data-type="png" data-w="337" style=""> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">关于线程数的设置,官方有一个建议:4 核的机器建议设置为 2 或 3 个线程,8 核的建议设置为 6 个线程,线程数一定要小于机器核数。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">还需要注意的是,线程数并不是越大越好,官方认为超过了 8 个基本就没什么意义了。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">⑥Redis 6.0 采用多线程后,性能的提升效果如何?</span></strong></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Redis 作者 antirez 在 RedisConf 2019 分享时曾提到:Redis 6 引入的多线程 IO 特性对性能提升至少是一倍以上。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">国内也有大牛曾使用 unstable 版本在阿里云 esc 进行过测试,GET/SET 命令在 4 线程 IO 时性能相比单线程是几乎是翻倍了。</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">测试环境:</span> </section> <section style="box-sizing: border-box;font-size: 16px;"> <section style="text-align: center;margin-top: 0.5em;margin-bottom: 0.5em;box-sizing: border-box;" powered-by="xiumi.us"> <section style="border-color: rgb(204, 204, 204);box-shadow: rgb(102, 102, 102) 0.2em 0.2em 0.5em;padding: 10px;border-width: 3px;border-style: solid;box-sizing: border-box;"> <section style="text-align: left;color: rgb(89, 89, 89);font-size: 14px;box-sizing: border-box;" powered-by="xiumi.us"> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;"><em>Redis Server:阿里云 Ubuntu 18.04,8 CPU 2.5 GHZ, 8G 内存,主机型号 ecs.ic5.2xlarge</em></span></p> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;"><em><br></em></span></p> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;"><em>Redis Benchmark Client:阿里云 Ubuntu 18.04,8 2.5 GHZ CPU, 8G 内存,主机型号 ecs.ic5.2xlarge</em></span></p> </section> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">测试结果:</span> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <img class="rich_pages" data-cropselx1="0" data-cropselx2="530" data-cropsely1="0" data-cropsely2="183" data-ratio="0.34641068447412354" data-s="300,640" src="/upload/8f16594760c6336370939515510cc88b.png" data-type="png" data-w="1198" style="width: 530px;height: 184px;"> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">详见:</span> </section> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">https:<span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);word-wrap: inherit !important;word-break: inherit !important;">//zhuanlan.zhihu.com/p/76788470</span><br></code></pre> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">说明 1:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这些性能验证的测试并没有针对严谨的延时控制和不同并发的场景进行压测。数据仅供验证参考而不能作为线上指标。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">说明 2:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如果开启多线程,至少要 4 核的机器,且 Redis 实例已经占用相当大的 CPU 耗时的时候才建议采用,否则使用多线程没有意义。所以估计 80% 的公司开发人员看看就好。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">⑦Redis 6.0 多线程的实现机制?</span></strong></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <img class="rich_pages" data-cropselx1="0" data-cropselx2="554" data-cropsely1="0" data-cropsely2="394" data-ratio="0.724972497249725" data-s="300,640" src="/upload/e16c00a17a0abda311f7d8713a3ca134.png" data-type="png" data-w="909" style="width: 554px;height: 402px;"> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">流程简述如下:</span></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">主线程负责接收建立连接请求,获取 Socket 放入全局等待读处理队列。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">主线程处理完读事件之后,通过 RR(Round Robin)将这些连接分配给这些 IO 线程。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">主线程阻塞等待 IO 线程读取 Socket 完毕。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">主线程通过单线程的方式执行请求命令,请求数据读取并解析完成,但并不执行。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">主线程阻塞等待 IO 线程将数据回写 Socket 完毕。</span></p></li> <li> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">解除绑定,清空等待队列。</span> </section></li> </ul> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <img class="rich_pages js_insertlocalimg" data-ratio="1.2375601926163724" data-s="300,640" src="/upload/b8e3794dfca5d03dc1caa9e9a861f216.png" data-type="png" data-w="623" style=""> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 14px;"><em><span style="color: rgb(89, 89, 89);letter-spacing: 1px;">图片来源:https://ruby-china.org/topics/38957</span></em></span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">该设计有如下特点:</span></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">IO 线程要么同时在读 Socket,要么同时在写,不会同时读或写。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">IO 线程只负责读写 Socket 解析命令,不负责命令处理。</span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">⑧开启多线程后,是否会存在线程并发安全问题?</span></strong></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">从上面的实现机制可以看出,Redis 的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程顺序执行。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">所以我们不需要去考虑控制 Key、Lua、事务,LPUSH/LPOP 等等的并发及线程安全问题。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">⑨Linux 环境上如何安装 Redis 6.0.1(6.0 的正式版是 6.0.1)?</span></strong></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这个和安装其他版本的 Redis 没有任何区别,整个流程跑下来也没有任何的坑,所以这里就不做描述了。</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">唯一要注意的就是配置多线程数一定要小于 CPU 的核心数,查看核心数量命令:</span> </section> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">[root@centos7<span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">.5</span> ~]<span style="font-size: inherit;line-height: inherit;color: rgb(91, 218, 237);word-wrap: inherit !important;word-break: inherit !important;"># lscpu</span><br>Architecture: x86_64<br>CPU op-mode(s): <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">32</span>-bit, <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">64</span>-bit<br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">Byte</span> <span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">Order</span>: Little Endian<br>CPU(s): <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">4</span><br><span style="font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);word-wrap: inherit !important;word-break: inherit !important;">On</span>-line CPU(s) list: <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">0</span><span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);word-wrap: inherit !important;word-break: inherit !important;">-3</span><br></code></pre> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">⑩Redis 6.0 的多线程和 Memcached 多线程模型进行对比</span></strong></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">前些年 Memcached 是各大互联网公司常用的缓存方案,因此 Redis 和 Memcached 的区别基本成了面试官缓存方面必问的面试题,最近几年 Memcached 用的少了,基本都是 Redis。</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">不过随着 Redis 6.0 加入了多线程特性,类似的问题可能还会出现,接下来我们只针对多线程模型来简单比较一下。</span> </section> <p style="text-align: center;line-height: 1.75em;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages js_insertlocalimg" data-ratio="0.7531645569620253" data-s="300,640" src="/upload/642f0773ecea36c2d22e3fed3ccd79de.png" data-type="png" data-w="948" style=""></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">如上图所示:Memcached 服务器采用 master-woker 模式进行工作,服务端采用 Socket 与客户端通讯。</span><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">主线程、工作线程 采用 Pipe 管道进行通讯。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">主线程采用 Libevent 监听 Listen、Accept 的读事件,事件响应后将连接信息的数据结构封装起来,根据算法选择合适的工作线程,将连接任务携带连接信息分发出去,相应的线程利用连接描述符建立与客户端的 Socket 连接并进行后续的存取数据操作。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">Redis 6.0 与 Memcached 多线程模型对比:</span></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">相同点:</span></strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">都采用了 Master 线程 -Worker 线程的模型。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">不同点:Memcached 执行主逻辑也是在 Worker 线程里,模型更加简单,实现了真正的线程隔离,符合我们对线程隔离的常规理解。</span></p><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">而 Redis 把处理逻辑交还给 Master 线程,虽然一定程度上增加了模型复杂度,但也解决了线程并发安全等问题。</span></p></li> </ul> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">⑪Redis 作者是如何点评 “多线程”这个新特性的?</span></strong></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">关于多线程这个特性,在 6.0 RC1 时,Antirez 曾做过说明:</span> </section> <section style="box-sizing: border-box;font-size: 16px;"> <section style="text-align: center;margin-top: 0.5em;margin-bottom: 0.5em;box-sizing: border-box;" powered-by="xiumi.us"> <section style="border-color: rgb(204, 204, 204);box-shadow: rgb(102, 102, 102) 0.2em 0.2em 0.5em;padding: 10px;border-width: 3px;border-style: solid;box-sizing: border-box;"> <section style="text-align: left;color: rgb(89, 89, 89);font-size: 14px;box-sizing: border-box;" powered-by="xiumi.us"> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;"><em>Redis 支持多线程有 2 种可行的方式:</em></span></p> <p style="box-sizing: border-box;"><br></p> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;"><em>第一种就是像“Memcached”那样,一个 Redis 实例开启多个线程,从而提升GET/SET等简单命令中每秒可以执行的操作。这涉及到 I/O、命令解析等多线程处理,因此,我们将其称之为“I/O threading”。</em></span></p> <p style="box-sizing: border-box;"><br></p> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;"><em>另一种就是允许在不同的线程中执行较耗时较慢的命令,以确保其它客户端不被阻塞,我们将这种线程模型称为“Slow commands threading”。</em></span></p> </section> </section> </section> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">经过深思熟虑,Redis 不会采用“I/O threading”,Redis 在运行时主要受制于网络和内存,所以提升 Redis 性能主要是通过在多个 Redis 实例,特别是 Redis 集群。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;letter-spacing: 1px;color: rgb(71, 193, 168);">接下来我们主要会考虑改进两个方面:</span></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Redis 集群的多个实例通过编排能够合理地使用本地实例的磁盘,避免同时重写 AOF。</span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">提供一个 Redis 集群代理,便于用户在没有较好的集群协议客户端时抽象出一个集群。</span></p></li> </ul> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">补充说明一下,Redis 和 Memcached 一样是一个内存系统,但不同于 Memcached。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">多线程是复杂的,必须考虑使用简单的数据模型,执行 LPUSH 的线程需要服务其他执行 LPOP 的线程。</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">我真正期望的实际是“slow operations threading”,在 Redis 6 或 Redis 7 中,将提供“key-level locking”,使得线程可以完全获得对键的控制以处理缓慢的操作。</span> <span style="color: rgb(89, 89, 89);font-size: 15px;letter-spacing: 1px;">详见:</span> </section> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"><code style="margin-right: 2px;margin-left: 2px;line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;word-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">http:<span style="font-size: inherit;line-height: inherit;color: rgb(128, 128, 128);word-wrap: inherit !important;word-break: inherit !important;">//antirez.com/news/126</span><br></code></pre> </section> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">⑫Redis 线程中经常提到 IO 多路复用,如何理解?</span></strong></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这是 IO 模型的一种,即经典的 Reactor 设计模式,有时也称为异步阻塞 IO。</span> </section> <p style="text-align: center;line-height: 1.75em;margin-left: 8px;margin-right: 8px;margin-bottom: 5px;"><img class="rich_pages" data-croporisrc="/upload/6273aa6a1a4333fb5599e89222ac09b4.jpg" data-cropx1="0" data-cropx2="649.0000000000001" data-cropy1="1.1499766573295984" data-cropy2="341.54306722689074" data-ratio="0.5254237288135594" data-s="300,640" src="https://mmbiz.qpic.cn/mmbiz_jpg/DkA0VYrOHvtWkvO02tIickx6ibOgCywvlibW8ELDCn2rxX7pJPbhkhJt1U01WTpI6uw5NWyA4iaB1iaXVxL8VunHZMQ/640?wx_fmt=jpeg" data-type="jpeg" data-w="649" style="width: 561px;height: 296px;"></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">多路指的是多个 Socket 连接,复用指的是复用一个线程。多路复用主要有三种技术:Select,Poll,Epoll。</span></p> <section style="line-height: normal;"> <br> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">Epoll 是最新的也是目前最好的多路复用技术。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快(内存内的操作不会成为这里的性能瓶颈),主要以上两点造就了 Redis 具有很高的吞吐量。</span></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><strong><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">⑬你知道 Redis 的彩蛋 LOLWUT 吗?</span></strong></p> <p style="line-height: normal;"><br></p> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">这个其实从 Redis 5.0 就开始有了,但是原谅我刚刚知道。作者是这么描述这个功能的《LOLWUT: a piece of art inside a database command》,“数据库命令中的一件艺术品”。</span></p> <section style="line-height: normal;"> <br> </section> <section style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <span style="font-size: 15px;color: rgb(89, 89, 89);letter-spacing: 1px;">你可以把它称之为情怀,也可以称之为彩蛋,具体是什么,我就不透露了。和我一样不清楚是什么的小伙伴可以参见:http://antirez.com/news/123,每次运行都会随机生成的噢。</span> </section> <section style="text-align: center;margin-left: 8px;margin-right: 8px;line-height: 1.75em;margin-bottom: 5px;"> <img data-ratio="0.595" src="/upload/bc97d5b02077b3b641da4f692d2da2d.png" data-type="png" data-w="800" style="text-align: left;text-indent: 2em;width: 458px;height: 274px;"> </section> <p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 14px;color: rgb(71, 193, 168);"><em><span style="letter-spacing: 1px;">参考、致谢:</span></em></span></p> <ul class="list-paddingleft-2" style="list-style-type: disc;"> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 14px;"><em><span style="color: rgb(89, 89, 89);letter-spacing: 1px;">Redis 作者 Antirez 的博客:http://antirez.com</span></em></span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 14px;"><em><span style="color: rgb(89, 89, 89);letter-spacing: 1px;">https://www.zhihu.com/question/26943938/answer/68773398</span></em></span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 14px;"><em><span style="color: rgb(89, 89, 89);letter-spacing: 1px;">https://zhuanlan.zhihu.com/p/76788470</span></em></span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 14px;"><em><span style="color: rgb(89, 89, 89);letter-spacing: 1px;">http://www.web-lovers.com/redis-source-6-rc-mult-thread.html</span></em></span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 14px;"><em><span style="color: rgb(89, 89, 89);letter-spacing: 1px;">https://ruby-china.org/topics/38957</span></em></span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 14px;"><em><span style="color: rgb(89, 89, 89);letter-spacing: 1px;">https://redis.io/topics/faq#redis-is-single-threaded-how-can-i-exploit-multiple-cpu--cores</span></em></span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 14px;"><em><span style="color: rgb(89, 89, 89);letter-spacing: 1px;">https://juejin.im/post/5e9ae485f265da47b04d95d2</span></em></span></p></li> <li><p style="text-align: justify;margin-left: 8px;margin-right: 8px;line-height: 1.75em;"><span style="font-size: 14px;"><em><span style="color: rgb(89, 89, 89);letter-spacing: 1px;">https://www.cnblogs.com/gattaca/p/6929361.html</span></em></span></p></li> </ul> <section style="line-height: normal;"> <br> </section> <p style="white-space: normal;line-height: 1.75em;"><span style="color: rgb(89, 89, 89);letter-spacing: 1px;"><em><span style="font-size: 14px;">作者:<em><span style="line-height: 27.2px;">剑圣</span></em></span></em></span></p> <p style="white-space: normal;line-height: 1.75em;"><span style="color: rgb(89, 89, 89);letter-spacing: 1px;"><em><span style="font-size: 14px;">编辑:陶家龙</span></em></span><br></p> <p style="white-space: normal;line-height: 27.2px;text-align: start;"><em><span style="line-height: 1.75em;font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">出处:转载自微信公众号</span><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 0.544px;line-height: 20px;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">码大叔(ID:ma_dashu)</span></em></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.39375" src="/upload/eccf90ae5f48405df149baa3056d4bf3.gif" data-type="gif" data-w="640" style=""></p> <section style="box-sizing: border-box;font-size: 16px;"> <section style="margin-top: 0.5em;margin-bottom: 0.5em;box-sizing: border-box;" powered-by="xiumi.us"> <section style="font-size: 15px;border-style: solid;border-width: 0px 0px 1px;color: rgb(89, 89, 89);border-bottom-color: rgba(215, 215, 215, 0.960784);box-sizing: border-box;"> <p style="box-sizing: border-box;"><span style="letter-spacing: 1px;"><strong>精彩文章推荐:</strong></span></p> </section> </section> </section> <section style="white-space: normal;text-align: start;line-height: 2em;"> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655830852&idx=1&sn=907e9bc89a2b8a082b9064c63fba849b&chksm=bd748e938a0307858845a0f49579f746141e0aace701fd32757375f2d5ccedc453d760c5d846&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" style="font-size: 14px;letter-spacing: 1px;color: rgb(89, 89, 89);" data-linktype="2"><span style="font-size: 14px;letter-spacing: 1px;color: rgb(89, 89, 89);">与“数据中台”,来一次亲密接触</span></a> <br> </section> <p style="line-height: 2em;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655830888&idx=1&sn=472ba263d1d62a0a5cd201d59ac38fc7&chksm=bd748ebf8a0307a901cd53e6726637a3b87e990fff52c7c790261a93c0287450b3ebf8a6478c&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;" data-linktype="2"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">写了个Bug,误执行rm -fr /*,瞬间背后一凉!</span></a><br></p> <p style="line-height: 2em;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655830844&idx=3&sn=5d94cdd6653594e1d3f7edcb0458d56c&chksm=bd748eeb8a0307fd8fd654e05f2a88c5c9755f34d611625318c941d5b9b91510e78b71933c4a&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;" data-linktype="2"><span style="font-size: 14px;color: rgb(89, 89, 89);letter-spacing: 1px;">因用了Insert into select语句,同事被开除了!</span></a><br></p>
作者:微信小助手
<section style="display: none;" data-tools="新媒体管家" data-label="powered by xmt.cn"> <br> </section> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" src="/upload/f6e0f1b7f3ed32cb7668604f80452b62.jpg" data-cropx1="0" data-cropx2="1280" data-cropy1="192.66435986159172" data-cropy2="726.3667820069205" data-ratio="0.4171875" data-s="300,640" src="https://mmbiz.qpic.cn/sz_mmbiz_jpg/qdzZBE73hWsoeQib6rCaTTtqR3ZMWGW4qd4hgwa8JJST6uORu5u7UAXR3n1MTlbltibSPicQXr8KpOLGTibQibm4vzw/640?wx_fmt=jpeg" data-type="jpeg" data-w="1280" style="width: 578px;height: 241px;"></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: right;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;letter-spacing: 0.544px;color: rgb(178, 178, 178);font-size: 13px;box-sizing: border-box !important;overflow-wrap: break-word !important;">Photo @ Priscilla Du Preez</span> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: right;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(0, 122, 170);box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 13px;box-sizing: border-box !important;overflow-wrap: break-word !important;">文 | 常意</span></strong></span></p> <h2 cid="n2" mdtype="heading" style="line-height: 1.75em;"><span style="color: rgb(0, 122, 170);"><strong><span style="color: rgb(0, 122, 170);font-size: 17px;"><br></span></strong></span><br></h2> <h2 cid="n2" mdtype="heading" style="line-height: 1.75em;"><span style="color: rgb(0, 122, 170);"><strong><span style="color: rgb(0, 122, 170);font-size: 17px;">前言</span></strong></span></h2> <article tabindex="0" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <hr style="max-width: 100%;white-space: normal;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;border-style: solid;border-right-width: 0px;border-bottom-width: 0px;border-left-width: 0px;border-color: rgba(0, 0, 0, 0.1);transform-origin: 0px 0px 0px;transform: scale(1, 0.5);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p dir="ltr" style="max-width: 100%;min-height: 1em;white-space: normal;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> </article> <p><span style="font-size: 15px;">古语有云:</span><br></p> <blockquote cid="n4" mdtype="blockquote"> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">道为术之灵,术为道之体;以道统术,以术得道。</span> </section> </blockquote> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">其中:“道”指“规律、道理、理论”,“术”指“方法、技巧、技术”。意思是:“道”是“术”的灵魂,“术”是“道”的肉体;可以用“道”来统管“术”,也可以从“术”中获得“道”。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;"><br></span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">在拜读大佬“孤尽”的文章</span> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU4NzU0MDIzOQ==&mid=2247489170&idx=1&sn=e47dcf2227517172ff97105e8a0543d0&chksm=fdeb24f2ca9cade4985b11abd05d4c8e2fdf2cf9b5a73dbe27d320a036d684563679e8d5c565&token=1498852714&lang=zh_CN&scene=21#wechat_redirect" textvalue="《Code Review是苦涩但有意思的修行》" tab="innerlink" data-linktype="2"><span style="font-size: 15px;">《Code Review是苦涩但有意思的修行》</span></a> <span style="font-size: 15px;">时,感受最深的一句话就是:“优质的代码一定是少即是多的精兵原则”,这就是大佬的代码精简之“道”。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;"><br></span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">工匠追求“术”到极致,其实就是在寻“道”,且离悟“道”也就不远了,亦或是已经得道,这就是“工匠精神”——一种追求“以术得道”的精神。如果一个工匠只满足于“术”,不能追求“术”到极致去悟“道”,那只是一个靠“术”养家糊口的工匠而已。作者根据多年来的实践探索,总结了大量的 Java 代码精简之“术”,试图阐述出心中的 Java 代码精简之“道”。</span> </section> <section style="line-height: 1.75em;"> <br> </section> <section style="line-height: 1.75em;"> <br> </section> <h2 cid="n10" mdtype="heading" style="line-height: 1.75em;"><span style="color: rgb(0, 122, 170);"><strong><span style="color: rgb(0, 122, 170);font-size: 17px;">1.利用语法</span></strong></span></h2> <article tabindex="0" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <hr style="max-width: 100%;white-space: normal;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;border-style: solid;border-right-width: 0px;border-bottom-width: 0px;border-left-width: 0px;border-color: rgba(0, 0, 0, 0.1);transform-origin: 0px 0px 0px;transform: scale(1, 0.5);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p dir="ltr" style="max-width: 100%;min-height: 1em;white-space: normal;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></p> </article> <h3 cid="n11" mdtype="heading" style="line-height: 1.75em;"><strong><span style="font-size: 16px;">1.1.利用三元表达式</span></strong></h3> <p><strong><span style="font-size: 16px;"><br></span></strong></p> <section style="line-height: 1.75em;"> <strong><span style="font-size: 15px;">普通:</span></strong> </section> <pre spellcheck="false" cid="n13" mdtype="fences"> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="nginx"><code><span class="code-snippet_outer">String title;</span></code><code><span class="code-snippet_outer">if (isMember(phone)) {</span></code><code><span class="code-snippet_outer"> title = "会员";</span></code><code><span class="code-snippet_outer">} else {</span></code><code><span class="code-snippet_outer"> title = "游客";</span></code><code><span class="code-snippet_outer">}</span></code></pre> </section> <section style="line-height: 1.75em;"> <br> </section></pre> <section style="line-height: 1.75em;"> <strong><span style="font-size: 15px;">精简:</span></strong> </section> <pre spellcheck="false" cid="n15" mdtype="fences"> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="javascript"><code><span class="code-snippet_outer">String title = isMember(phone) ? "会员" : "游客";</span></code></pre> </section> <section style="line-height: 1.75em;"> <br> </section></pre> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">注意:对于包装类型的算术计算,需要注意避免拆包时的空指针问题。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;"><br></span> </section> <h3 cid="n17" mdtype="heading" style="line-height: 1.75em;"><strong><span style="font-size: 16px;">1.2.利用 for-each 语句</span></strong></h3> <p><strong><span style="font-size: 16px;"><br></span></strong></p> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">从 Java 5 起,提供了 for-each 循环,简化了数组和集合的循环遍历。 for-each 循环允许你无需保持传统 for 循环中的索引就可以遍历数组,或在使用迭代器时无需在 while 循环中调用 hasNext 方法和 next 方法就可以遍历集合。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;"><br></span> </section> <section style="line-height: 1.75em;"> <strong><span style="font-size: 15px;">普通:</span></strong> </section> <pre spellcheck="false" cid="n20" mdtype="fences"> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="cs"><code><span class="code-snippet_outer">double[] values = ...;</span></code><code><span class="code-snippet_outer">for(int i = 0; i < values.length; i++) {</span></code><code><span class="code-snippet_outer"> double value = values[i];</span></code><code><span class="code-snippet_outer"> // TODO: 处理value</span></code><code><span class="code-snippet_outer">}</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer">List<Double> valueList = ...;</span></code><code><span class="code-snippet_outer">Iterator<Double> iterator = valueList.iterator();</span></code><code><span class="code-snippet_outer">while (iterator.hasNext()) {</span></code><code><span class="code-snippet_outer"> Double value = iterator.next();</span></code><code><span class="code-snippet_outer"> // TODO: 处理value</span></code><code><span class="code-snippet_outer">}</span></code></pre> </section> <section style="line-height: 1.75em;"> <br> </section></pre> <section style="line-height: 1.75em;"> <strong><span style="font-size: 15px;">精简:</span></strong> </section> <pre spellcheck="false" cid="n22" mdtype="fences"> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="cs"><code><span class="code-snippet_outer">double[] values = ...;</span></code><code><span class="code-snippet_outer">for(double value : values) {</span></code><code><span class="code-snippet_outer"> // TODO: 处理value</span></code><code><span class="code-snippet_outer">}</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer">List<Double> valueList = ...;</span></code><code><span class="code-snippet_outer">for(Double value : valueList) {</span></code><code><span class="code-snippet_outer"> // TODO: 处理value</span></code><code><span class="code-snippet_outer">}</span></code></pre> </section> <section style="line-height: 1.75em;"> <br> </section></pre> <h3 cid="n23" mdtype="heading" style="line-height: 1.75em;"><span style="font-size: 16px;"><strong>1.3.利用 try-with-resource 语句</strong></span></h3> <p><span style="font-size: 16px;"><strong><br></strong></span></p> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">所有实现 Closeable 接口的“资源”,均可采用 try-with-resource 进行简化。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;"><br></span> </section> <section style="line-height: 1.75em;"> <strong><span style="font-size: 15px;">普通:</span></strong> </section> <pre spellcheck="false" cid="n26" mdtype="fences"> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="javascript"><code><span class="code-snippet_outer">BufferedReader reader = null;</span></code><code><span class="code-snippet_outer">try {</span></code><code><span class="code-snippet_outer"> reader = new BufferedReader(new FileReader("cities.csv"));</span></code><code><span class="code-snippet_outer"> String line;</span></code><code><span class="code-snippet_outer"> while ((line = reader.readLine()) != null) {</span></code><code><span class="code-snippet_outer"> // TODO: 处理line</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer">} catch (IOException e) {</span></code><code><span class="code-snippet_outer"> log.error("读取文件异常", e);</span></code><code><span class="code-snippet_outer">} finally {</span></code><code><span class="code-snippet_outer"> if (reader != null) {</span></code><code><span class="code-snippet_outer"> try {</span></code><code><span class="code-snippet_outer"> reader.close();</span></code><code><span class="code-snippet_outer"> } catch (IOException e) {</span></code><code><span class="code-snippet_outer"> log.error("关闭文件异常", e);</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer">}</span></code></pre> </section> <section style="line-height: 1.75em;"> <br> </section></pre> <section style="line-height: 1.75em;"> <strong><span style="font-size: 15px;">精简:</span></strong> </section> <pre spellcheck="false" cid="n28" mdtype="fences"> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="javascript"><code><span class="code-snippet_outer">try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {</span></code><code><span class="code-snippet_outer"> String line;</span></code><code><span class="code-snippet_outer"> while ((line = reader.readLine()) != null) {</span></code><code><span class="code-snippet_outer"> // TODO: 处理line</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer">} catch (IOException e) {</span></code><code><span class="code-snippet_outer"> log.error("读取文件异常", e);</span></code><code><span class="code-snippet_outer">}</span></code></pre> </section> <section style="line-height: 1.75em;"> <br> </section></pre> <h3 cid="n29" mdtype="heading" style="line-height: 1.75em;"><strong><span style="font-size: 16px;">1.4.利用 return 关键字</span></strong></h3> <p><strong><span style="font-size: 16px;"><br></span></strong></p> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">利用 return 关键字,可以提前函数返回,避免定义中间变量。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;"><br></span> </section> <section style="line-height: 1.75em;"> <strong><span style="font-size: 15px;">普通:</span></strong> </section> <pre spellcheck="false" cid="n32" mdtype="fences"> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="typescript"><code><span class="code-snippet_outer">public static boolean hasSuper(@NonNull List<UserDO> userList) {</span></code><code><span class="code-snippet_outer"> boolean hasSuper = false;</span></code><code><span class="code-snippet_outer"> for (UserDO user : userList) {</span></code><code><span class="code-snippet_outer"> if (Boolean.TRUE.equals(user.getIsSuper())) {</span></code><code><span class="code-snippet_outer"> hasSuper = true;</span></code><code><span class="code-snippet_outer"> break;</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> return hasSuper;</span></code><code><span class="code-snippet_outer">}</span></code></pre> </section> <section style="line-height: 1.75em;"> <br> </section></pre> <section style="line-height: 1.75em;"> <strong><span style="font-size: 15px;">精简:</span></strong> </section> <pre spellcheck="false" cid="n34" mdtype="fences"> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="typescript"><code><span class="code-snippet_outer">public static boolean hasSuper(@NonNull List<UserDO> userList) {</span></code><code><span class="code-snippet_outer"> for (UserDO user : userList) {</span></code><code><span class="code-snippet_outer"> if (Boolean.TRUE.equals(user.getIsSuper())) {</span></code><code><span class="code-snippet_outer"> return true;</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer"> return false;</span></code><code><span class="code-snippet_outer">}</span></code></pre> </section> <section style="line-height: 1.75em;"> <br> </section></pre> <h3 cid="n35" mdtype="heading" style="line-height: 1.75em;"><strong><span style="font-size: 16px;">1.5.利用 static 关键字</span></strong></h3> <p><strong><span style="font-size: 16px;"><br></span></strong></p> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">利用 static 关键字,可以把字段变成静态字段,也可以把函数变为静态函数,调用时就无需初始化类对象。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;"><br></span> </section> <section style="line-height: 1.75em;"> <strong><span style="font-size: 15px;">普通:</span></strong> </section> <pre spellcheck="false" cid="n38" mdtype="fences"> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="java"><code><span class="code-snippet_outer">public final class GisHelper {</span></code><code><span class="code-snippet_outer"> public double distance(double lng1, double lat1, double lng2, double lat2) {</span></code><code><span class="code-snippet_outer"> // 方法实现代码</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer">}</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer">GisHelper gisHelper = new GisHelper();</span></code><code><span class="code-snippet_outer">double distance = gisHelper.distance(116.178692D, 39.967115D, 116.410778D, 39.899721D);</span></code></pre> </section><p><br></p></pre> <section style="line-height: 1.75em;"> <strong><span style="font-size: 15px;">精简:</span></strong> </section> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="java"><code><span class="code-snippet_outer">public final class GisHelper {</span></code><code><span class="code-snippet_outer"> public static double distance(double lng1, double lat1, double lng2, double lat2) {</span></code><code><span class="code-snippet_outer"> // 方法实现代码</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer">}</span></code><code><span class="code-snippet_outer"><br></span></code><code><span class="code-snippet_outer">double distance = GisHelper.distance(116.178692D, 39.967115D, 116.410778D, 39.899721D);</span></code></pre> </section> <h3 cid="n41" mdtype="heading" style="line-height: 1.75em;"><span style="font-size: 15px;"><br></span></h3> <h3 cid="n41" mdtype="heading" style="line-height: 1.75em;"><strong><span style="font-size: 16px;">1.6.利用 lambda 表达式</span></strong></h3> <p><strong><span style="font-size: 16px;"><br></span></strong></p> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">Java 8 发布以后,lambda 表达式大量替代匿名内部类的使用,在简化了代码的同时,更突出了原有匿名内部类中真正有用的那部分代码。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;"><br></span> </section> <section style="line-height: 1.75em;"> <strong><span style="font-size: 15px;">普通:</span></strong> </section> <pre spellcheck="false" cid="n44" mdtype="fences"> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="cs"><code><span class="code-snippet_outer">new Thread(new Runnable() {</span></code><code><span class="code-snippet_outer"> public void run() {</span></code><code><span class="code-snippet_outer"> // 线程处理代码</span></code><code><span class="code-snippet_outer"> }</span></code><code><span class="code-snippet_outer">}).start();</span></code></pre> </section> <section style="line-height: 1.75em;"> <br> </section></pre> <section style="line-height: 1.75em;"> <strong><span style="font-size: 15px;">精简:</span></strong> </section> <pre spellcheck="false" cid="n46" mdtype="fences"> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="javascript"><code><span class="code-snippet_outer">new Thread(() -> {</span></code><code><span class="code-snippet_outer"> // 线程处理代码</span></code><code><span class="code-snippet_outer">}).start();</span></code></pre> </section> <section style="line-height: 1.75em;"> <br> </section></pre> <h3 cid="n47" mdtype="heading" style="line-height: 1.75em;"><strong><span style="font-size: 16px;">1.7.利用方法引用</span></strong></h3> <p><strong><span style="font-size: 16px;"><br></span></strong></p> <section style="line-height: 1.75em;"> <span style="font-size: 15px;">方法引用(::),可以简化 lambda 表达式,省略变量声明和函数调用。</span> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;"><br></span> </section> <section style="line-height: 1.75em;"> <strong><span style="font-size: 15px;">普通:</span></strong> </section> <pre spellcheck="false" cid="n50" mdtype="fences"> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="swift"><code><span class="code-snippet_outer">Arrays.sort(nameArray, (a, b) -> a.compareToIgnoreCase(b));</span></code><code><span class="code-snippet_outer">List<Long> userIdList = userList.stream()</span></code><code><span class="code-snippet_outer"> .map(user -> user.getId())</span></code><code><span class="code-snippet_outer"> .collect(Collectors.toList());</span></code></pre> </section> <section style="line-height: 1.75em;"> <br> </section> <section style="line-height: 1.75em;"> <span style="font-size: 15px;"><strong><span style="font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;text-align: left;white-space: pre;background-color: rgba(0, 0, 0, 0.03);">精简:</span></strong></span> </section></pre> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="php"><code><span class="code-snippet_outer">Arrays.sort(nameArray, String::compareToIgnoreCase);</span></code><code><span class="code-snippet_outer">List<Long> userIdList = userList.stream()</span></code><code><span class="code-snippet_outer"> .map(UserDO::getId)</span></code><code><span class="code-snippet_outer"> .collect(Collectors.toList());</span></code></pre> </section> <section style="line-height: 1.75em;"> <section style="line-height: 1.75em;"> <br> </section> </section> <h3 cid="n53" mdtype="heading" style="line-height: 1.75em;"><strong><span style="font-size: 16px;">1.8.利用静态导入</span></strong></h3> <p><strong><span style="font-
作者:微信小助手
<section style="display: none;" data-tools="新媒体管家" data-label="powered by xmt.cn" data-mpa-powered-by="yiban.io"> <br> </section> <section data-role="outer" label="Powered by 135editor.com" style="font-size: 16px;"> <section style="box-sizing: border-box;padding-right: 5px;padding-left: 5px;"> <section data-role="paragraph" style="font-family: sans-serif;"> <section data-role="paragraph"> <section data-role="paragraph"> <section data-role="paragraph" style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;font-family: sans-serif;font-size: 16px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></p> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(19, 139, 213);font-weight: 700;letter-spacing: 0.544px;caret-color: red;font-family: Helvetica, Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;">作者介绍</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> </section> <section data-role="paragraph" style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;font-family: sans-serif;font-size: 16px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section label="Copyright © 2015 Yead All Rights Reserved." style="margin: 5px auto;max-width: 100%;box-sizing: border-box;letter-spacing: 0.544px;font-size: 14px;color: rgb(62, 62, 62);line-height: 25.6px;font-family: 微软雅黑;overflow-wrap: break-word !important;"> <section style="padding-top: 5px;padding-bottom: 5px;max-width: 100%;box-sizing: border-box;width: 667px;text-decoration: inherit;overflow-wrap: break-word !important;"> <section style="padding-bottom: 5px;padding-left: 20px;max-width: 100%;box-sizing: border-box;border-left: 3px solid rgb(153, 153, 153);overflow-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-family: Helvetica, Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 16px;box-sizing: border-box !important;overflow-wrap: break-word !important;">李猛(ynuosoft),</span></strong><span style="max-width: 100%;text-decoration: inherit;letter-spacing: 0.544px;caret-color: red;box-sizing: border-box !important;overflow-wrap: break-word !important;">Elastic-stack产品深度用户,ES认证工程师,2012年接触Elasticsearch,对Elastic-Stack开发、架构、运维等方面有深入体验,实践过多种Elasticsearch项目,最暴力的大数据分析应用,最复杂的业务系统应用;业余为企业提供Elastic-stack咨询培训以及调优实施。</span></span></p> </section> </section> </section> </section> <p><br></p> </section> <section data-tools="135编辑器" data-id="86318" data-color="#138bde" data-custom="#138bde"> <section style="margin-right: auto;margin-left: auto;"> <section style="margin-top: 2em;padding-top: 0.5em;padding-bottom: 0.5em;font-size: 1em;font-weight: inherit;line-height: 22.4px;border-style: solid none none;border-top-width: 1px;border-top-color: rgb(204, 204, 204);text-decoration: inherit;color: rgb(166, 166, 166);box-sizing: border-box;font-family: inherit;"> <section style="margin-top: -1.2em;text-align: center;border-width: initial;border-style: none;border-color: initial;line-height: 1.4;box-sizing: border-box;"> <span style="font-family: Helvetica, Arial, sans-serif;"><strong><span style="padding: 8px 23px;border-radius: 25px;color: rgb(255, 255, 255);font-weight: inherit;text-decoration: inherit;border-color: rgb(19, 139, 222);background-color: rgb(19, 139, 222);" data-brushtype="text">序言</span></strong></span> </section> </section> </section> </section> <section data-role="paragraph"> <p><br></p> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="0.3659244917715392" data-s="300,640" src="/upload/1162e11707940eb0a6768c5f153ca349.png" data-type="png" data-w="1033" style=""></p> </section> <section data-role="paragraph"> <p style="text-align: center;line-height: 1.75em;"><span style="color: #7f7f7f;font-size: 12px;">Elasticsearch当前热度排名很高</span></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">青出于蓝,而胜于蓝。</span></p> <p style="line-height: 1.75em;"><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">入行Elastic-Stack技术栈很久很久,为了免于知识匮乏眼光局限,有必要到外面的世界看看,丰富自己的世界观。本篇内容从Elastic的竞争产品角度分析探讨。</span></p> <p><br></p> <section data-role="list"> <ul class="list-paddingleft-2" style="padding-left: 30px;"> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">哪些应用场景下使用Elasticsearch最佳?</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">哪些应用场景下不使用Elasticsearch最好?</span></p></li> </ul> </section> <p style="line-height: 1.75em;"><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">本文仅代表个人的观点,不代表社区技术阵营观点,无意口水之争,限于本人的经验知识有限,可能与读者观点认知不一致。</span></p> <section data-role="paragraph"> <p><br></p> </section> <section data-tools="135编辑器" data-id="86318" data-color="#138bde" data-custom="#138bde"> <section style="margin-right: auto;margin-left: auto;"> <section style="margin-top: 2em;padding-top: 0.5em;padding-bottom: 0.5em;font-size: 1em;font-weight: inherit;line-height: 22.4px;border-style: solid none none;border-top-width: 1px;border-top-color: rgb(204, 204, 204);text-decoration: inherit;color: rgb(166, 166, 166);box-sizing: border-box;font-family: inherit;"> <section style="margin-top: -1.2em;text-align: center;border-width: initial;border-style: none;border-color: initial;line-height: 1.4;box-sizing: border-box;"> <span style="font-family: Helvetica, Arial, sans-serif;"><strong><span style="padding: 8px 23px;border-radius: 25px;color: rgb(255, 255, 255);font-weight: inherit;text-decoration: inherit;border-color: rgb(19, 139, 222);background-color: rgb(19, 139, 222);" data-brushtype="text">竞争产品</span></strong></span> </section> </section> </section> </section> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">Elasticseach从做搜索引擎开始,到现在主攻大数据分析领域,逐步进化成了一个全能型的数据产品,在Elasticsearch诸多优秀的功能中,与很多数据产品有越来越多的交叉竞争,有的功能很有特色,有的功能只是附带,了解这些产品特点有助于更好的应用于业务需求。</span></p> <p><br></p> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="0.9761092150170648" data-s="300,640" src="/upload/a49fee90f479f047ca30c4864b70e363.png" data-type="png" data-w="586" style=""></p> <p style="text-align: center;line-height: 1.75em;"><span style="color: #7f7f7f;font-size: 12px;">图片:Elasticsearch竞争图谱示意图</span></p> <p><br></p> <section data-tools="135编辑器" data-id="39" style="border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;" data-color="#138bde" data-custom="#138bde"> <section style="max-width: 100%;margin-top: 0.8em;margin-bottom: 0.5em;overflow: hidden;text-align: left;"> <section data-brushtype="text" placeholder="请输入标题" style="height: 36px;display: inline-block;color: rgb(255, 255, 255);font-weight: bold;padding-right: 10px;padding-left: 10px;line-height: 36px;vertical-align: top;background-color: rgb(19, 139, 222);box-sizing: border-box !important;"> <span style="font-family: Helvetica, Arial, sans-serif;">1、Lucene</span> </section> <section style="display: inline-block;height: 36px;vertical-align: top;border-left: 9px solid #138bde;box-sizing: border-box !important;border-top: 18px solid transparent !important;border-bottom: 18px solid transparent !important;overflow: hidden;"> <br> </section> </section> </section> <p style="line-height: 1.75em;"><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">Lucene是一个搜索的核心库,Elastic也是在Lucene基础之上构建,它们之间的竞争关系是由Lucene本身决定的。</span></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">在互联网2.0时代,考验各互联网公司最简单的技术要求,就是看他们的搜索做的怎么样,那时大家的做法几乎一样,都基于Lucene核心库构建一套搜索引擎,剩下的就看各公司的开发者们的水平。笔者有幸在2012年之前,基于Lucene做过垂直行业的搜索引擎,遇到很多问题有必要说一下:</span></p> <p><br></p> <section data-role="list"> <ul class="list-paddingleft-2" style="padding-left: 30px;"> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">项目基于Lucene包装,业务代码与核心库一起构建发布,代码耦合度很高,每次有数据字段变更,都需要重新编译打包发布,这个过程非常的繁琐,且相当危险。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">程序重新发布,需要关闭原有的程序,涉及到进程切换问题。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">索引数据定期全量重新生成,也涉及到新旧索引切换,索引实时刷新等问题,都需要设计一套复杂的程序机制保障</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">每个独立业务线需求,都需要单独构建一个Lucene索引进程,业务线多了之后,管理是个麻烦的事情</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">当单个Lucene索引数据超过单实例限制之后,需要做分布式,这个原有Lucene是没有办法的,所以常规的做法也是按照某特定分类,拆分成多个索引进程,客户端查询时带上特定分类,后端根据特定分类路由到具体的索引。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">Lucene库本身的掌控难度,对于功力尚浅的开发工程师,需要考虑的因素实在太多了,稍微不慎,就会出现很大的程序问题。</span></p></li> </ul> </section> <p><br></p> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="0.6527777777777778" data-s="300,640" src="/upload/5bf0d068df1f66dd9c3b4d221dc1a89e.png" data-type="png" data-w="504" style=""></p> <p style="text-align: center;line-height: 1.75em;"><span style="color: #7f7f7f;font-size: 12px;">图示:Lucene内部索引构建与查询过程</span></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">Elasticsearch与Lucene核心库竞争的优势在于:</span></p> <p><br></p> <section data-role="list"> <ul class="list-paddingleft-2" style="padding-left: 30px;"> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">完美封装了Lucene核心库,设计了友好的Restful-API,开发者无需过多关注底层机制,直接开箱即用。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">分片与副本机制,直接解决了集群下性能与高可用问题。</span></p></li> </ul> </section> <p style="line-height: 1.75em;"><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">Elastic近年的快速发展,市面上已经很少发现基于Lucene构建搜索引擎的项目,几乎清一色选择Elasticsearch作为基础数据库服务,由于其开源特性,广大云厂商也在此基础上定制开发,与自己的云平台深度集成,但也没有独自发展一个分支。</span></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">本次的竞争中,Elasticsearch完胜。</span></p> <p style="line-height: 1.75em;"><br></p> <section data-tools="135编辑器" data-id="39" style="border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;" data-color="#138bde" data-custom="#138bde"> <section style="max-width: 100%;margin-top: 0.8em;margin-bottom: 0.5em;overflow: hidden;text-align: left;"> <section data-brushtype="text" placeholder="请输入标题" style="height: 36px;display: inline-block;color: rgb(255, 255, 255);font-weight: bold;padding-right: 10px;padding-left: 10px;line-height: 36px;vertical-align: top;background-color: rgb(19, 139, 222);box-sizing: border-box !important;"> <span style="font-family: Helvetica, Arial, sans-serif;">2、Solr</span> </section> <section style="display: inline-block;height: 36px;vertical-align: top;border-left: 9px solid #138bde;box-sizing: border-box !important;border-top: 18px solid transparent !important;border-bottom: 18px solid transparent !important;overflow: hidden;"> <br> </section> </section> </section> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">Solr是第一个基于Lucene核心库功能完备的搜索引擎产品,诞生远早于Elasticsearch,早期在全文搜索领域,Solr有非常大的优势,几乎完全压倒Elastic,在近几年大数据发展时代,Elastic由于其分布式特性,满足了很多大数据的处理需求,特别是后面ELK这个概念的流行,几乎完全忘记了Solr的存在,虽然也推出了Solr-Coud分布式产品,但已经基本无优势。</span><br></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">接触过几个数据类公司,全文搜索都基于Solr构建,且是单节点模式,偶然出现一些问题,找咨询顾问排查问题,人员难找,后面都迁移到Elasticsearch之上。</span></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">现在市面上几乎大大小小公司都在使用Elasticsearch,除了老旧系统有的基于Solr的,新系统项目应该全部是Elasticsearch。</span></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">个人认为有以下几个原因:</span></p> <p><br></p> <section data-role="list"> <ul class="list-paddingleft-2" style="padding-left: 30px;"> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">ES比Solr更加友好简洁,门槛更低。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">ES比Solr产品功能特点更加丰富,分片机制,数据分析能力。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">ES生态发展,Elastic-stack整个技术栈相当全,与各种数据系统都很容易集成。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">ES社区发展更加活跃,Solr几乎没有专门的技术分析大会。</span></p></li> </ul> </section> <p><br></p> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="0.7510316368638239" data-s="300,640" src="/upload/76b1fc527f952865e230e46a8963ed50.png" data-type="png" data-w="727" style=""></p> <p style="text-align: center;line-height: 1.75em;"><span style="font-size: 12px;color: #7f7f7f;">图示:Solr产品功能模块内部架构图</span></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">本次竞争中,Elasticsearch完胜。</span></p> <p style="line-height: 1.75em;"><br></p> <section data-tools="135编辑器" data-id="39" style="border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;" data-color="#138bde" data-custom="#138bde"> <section style="max-width: 100%;margin-top: 0.8em;margin-bottom: 0.5em;overflow: hidden;text-align: left;"> <section data-brushtype="text" placeholder="请输入标题" style="height: 36px;display: inline-block;color: rgb(255, 255, 255);font-weight: bold;padding-right: 10px;padding-left: 10px;line-height: 36px;vertical-align: top;background-color: rgb(19, 139, 222);box-sizing: border-box !important;"> <span style="font-family: Helvetica, Arial, sans-serif;">3、RDBMS</span> </section> <section style="display: inline-block;height: 36px;vertical-align: top;border-left: 9px solid #138bde;box-sizing: border-box !important;border-top: 18px solid transparent !important;border-bottom: 18px solid transparent !important;overflow: hidden;"> <br> </section> </section> </section> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">关系型数据库与Elasticsarch相比主要优点是事务隔离机制无可替代,但其局限性很明显,如下:</span></p> <p><br></p> <section data-role="list"> <ul class="list-paddingleft-2" style="padding-left: 30px;"> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">关系型数据库查询性能,数据量超过百万级千万级之后下降厉害,本质是索引的算法效率不行,B+树算法不如倒排索引算法高效。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">关系型数据库索引最左原则限制,查询条件字段不能任意组合,否则索引失效,相反Elasticserach可以任意组合,此场景在数据表关联查询时特别明显,Elasticsearch可以采用大宽表解决,而关系型数据库不能。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">关系型数据库分库分表之后多条件查询,难于实现,Elasticsearch天然分布式设计,多个索引多个分片皆可联合查询。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">关系型数据库聚合性能低下,数据量稍微多点,查询列基数多一点性能下降很快,Elasticsearch在聚合上采用的是列式存储,效率极高。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">关系型数据库侧重均衡性,Elasticsearch侧重专一查询速度。</span></p><p style="line-height: 1.75em;"><br></p></li> </ul> </section> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">若数据无需严格事务机制隔离,个人认为都可以采用Elasticsearch替代。若数据既要事务隔离,也要查询性能,可以采用DB与ES混合实现,详细见笔者的博客文章</span><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI2NDExNTk5Mg==&mid=2247490872&idx=1&sn=7300df8624942cb4d0cb9c683d2d5bcb&chksm=eab0df4fddc75659da47ad562c243c9fb0946c1cfd744e754f7466b324d141dfa33f10b7bb2c&scene=21#wechat_redirect" textvalue="《DB与ES混合应用之数据实时同步》" data-itemshowtype="0" tab="innerlink" data-linktype="2"><span style="color: rgb(62, 62, 62);font-size: 15px;text-decoration: underline;">《DB与ES混合应用之数据实时同步》</span></a><span style="color: rgb(62, 62, 62);font-size: 15px;text-decoration: underline;"></span></p> <p><br></p> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="0.5427251732101617" data-s="300,640" src="/upload/ce99ada3ecab20658eea46d2596bd02f.png" data-type="png" data-w="433" style=""></p> <p style="text-align: center;line-height: 1.75em;"><span style="color: #7f7f7f;font-size: 12px;">图示:RDBMS与ES各自优势示意图</span></p> <p><br></p> <section data-tools="135编辑器" data-id="39" style="border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;" data-color="#138bde" data-custom="#138bde"> <section style="max-width: 100%;margin-top: 0.8em;margin-bottom: 0.5em;overflow: hidden;text-align: left;"> <section data-brushtype="text" placeholder="请输入标题" style="height: 36px;display: inline-block;color: rgb(255, 255, 255);font-weight: bold;padding-right: 10px;padding-left: 10px;line-height: 36px;vertical-align: top;background-color: rgb(19, 139, 222);box-sizing: border-box !important;"> <span style="font-family: Helvetica, Arial, sans-serif;">4、OpenTSDB</span> </section> <section style="display: inline-block;height: 36px;vertical-align: top;border-left: 9px solid #138bde;box-sizing: border-box !important;border-top: 18px solid transparent !important;border-bottom: 18px solid transparent !important;overflow: hidden;"> <br> </section> </section> </section> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">OpenTSDB内部基于<span style="color: rgb(62, 62, 62);font-family: sans-serif;font-size: 15px;">HB</span><span style="color: rgb(62, 62, 62);font-family: sans-serif;font-size: 15px;">ase</span>实现,属于时间序列数据库,主要针对具有时间特性和需求的数据,进行过数据结构的优化和处理,从而适合存储具有时间特性的数据,如监控数据、温度变化数据等,小米公司开源监控体系open-falcon的就是基于OpenTSDB实现。</span></p> <p><br></p> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="0.5677603423680456" data-s="300,640" src="/upload/17ae612920090dfdb016536af6fc6fba.png" data-type="png" data-w="701" style=""></p> <p style="text-align: center;line-height: 1.75em;"><span style="color: #7f7f7f;font-size: 12px;">图示:OpenTSDB时间序列数据库内部实现</span></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">Elastic产品本身无意时间序列这个领域,随着ELK的流行,很多公司采用ELK来构建监控体系,虽然在数值类型上不像时间序列数据库做过特别处理,但由于其便利的使用,以及生态技术栈的优势,我们也接受了这样的事实。</span></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">Elasticsearch构建时间序列很简单,性能也相当不错:</span></p> <p><br></p> <section data-role="list"> <ul class="list-paddingleft-2" style="padding-left: 30px;"> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">索引创建规则,可以按年、按月、按周、按星期、按天、按小时等都创建索引,非常便利。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;"></span><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">数据填充方面,定制一个时间字段做区分排序,其余的字段无需。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">数据查询方面,除了按实际序列查询外,还可以有更多的搜索条件。</span></p></li> </ul> </section> <p style="line-height: 1.75em;"><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">除非对于时间序列数据有非常苛刻的监控需求,否则选择Elasticsearch会更加合适一些。</span></p> <p style="line-height: 1.75em;"><br></p> <section data-tools="135编辑器" data-id="39" style="border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;" data-color="#138bde" data-custom="#138bde"> <section style="max-width: 100%;margin-top: 0.8em;margin-bottom: 0.5em;overflow: hidden;text-align: left;"> <section data-brushtype="text" placeholder="请输入标题" style="height: 36px;display: inline-block;color: rgb(255, 255, 255);font-weight: bold;padding-right: 10px;padding-left: 10px;line-height: 36px;vertical-align: top;background-color: rgb(19, 139, 222);box-sizing: border-box !important;"> <span style="font-family: Helvetica, Arial, sans-serif;">5、HBase</span> </section> <section style="display: inline-block;height: 36px;vertical-align: top;border-left: 9px solid #138bde;box-sizing: border-box !important;border-top: 18px solid transparent !important;border-bottom: 18px solid transparent !important;overflow: hidden;"> <br> </section> </section> </section> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">HBase是列式数据库的代表,其内部有几个致命设计大大限制了它的应用范围:</span></p> <p><br></p> <section data-role="list"> <ul class="list-paddingleft-2" style="padding-left: 30px;"> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">访问<span style="color: rgb(62, 62, 62);font-family: sans-serif;font-size: 15px;">HB</span><span style="color: rgb(62, 62, 62);font-family: sans-serif;font-size: 15px;">ase</span>数据只能基于Rowkey,Rowkey设计的好坏直接决定了<span style="color: rgb(62, 62, 62);font-family: sans-serif;font-size: 15px;">HB</span><span style="color: rgb(62, 62, 62);font-family: sans-serif;font-size: 15px;">ase</span>使用优劣。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">本身不支持二级索引,若要实现,则需要引入第三方。</span></p></li> </ul> </section> <p style="line-height: 1.75em;"><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">关于其各种技术原理就不多说了,说说它的一些使用情况。</span></p> <p style="line-height: 1.75em;"><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">公司所属物流速运行业,一个与车辆有关的项目,记录所有车辆行驶轨迹,车载设备会定时上报车子的轨迹信息,后端数据存储基于HBase,数据量在几十TB级以上,由于业务端需要依据车辆轨迹信息计算它的公里油耗以及相关成本,所以要按查询条件批量查询数据,查询条件有一些非rowkey的字段,如时间范围,车票号,城市编号等,这几乎无法实现,原来暴力的做过,性能问题堪忧。此项目的问题首先也在于rowkey难设计满足查询条件的需求,其次是二级索引问题,查询的条件很多。</span></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">如果用列式数据库仅限于Rowkey访问场景,其实采用Elastic也可以,只要设计好 _id,与<span style="color: rgb(62, 62, 62);font-family: sans-serif;font-size: 15px;">HB</span><span style="color: rgb(62, 62, 62);font-family: sans-serif;font-size: 15px;">ase</span>可以达到相同的效果。</span></p> <p style="line-height: 1.75em;"><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">如果用列式数据库查询还需要引入三方组件,那还不如直接在Elasticsearch上构建更直接。</span></p> <p style="line-height: 1.75em;"><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">除非对使用列式数据库有非常苛刻的要求,否则Elasticsearch更具备通用性,业务需求场景适用性更多。</span></p> <p><br></p> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="0.658203125" data-s="300,640" src="/upload/43ebc3d49ef38da6b0fbf11cc89d7205.png" data-type="png" data-w="512" style=""></p> <p style="text-align: center;line-height: 1.75em;"><span style="font-size: 12px;color: #7f7f7f;">图示:列式数据库内部数据结构示意图</span></p> <p style="text-align: center;line-height: 1.75em;"><br></p> <section data-tools="135编辑器" data-id="39" style="border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;" data-color="#138bde" data-custom="#138bde"> <section style="max-width: 100%;margin-top: 0.8em;margin-bottom: 0.5em;overflow: hidden;text-align: left;"> <section data-brushtype="text" placeholder="请输入标题" style="height: 36px;display: inline-block;color: rgb(255, 255, 255);font-weight: bold;padding-right: 10px;padding-left: 10px;line-height: 36px;vertical-align: top;background-color: rgb(19, 139, 222);box-sizing: border-box !important;"> <span style="font-family: Helvetica, Arial, sans-serif;">6、MongoDB</span> </section> <section style="display: inline-block;height: 36px;vertical-align: top;border-left: 9px solid #138bde;box-sizing: border-box !important;border-top: 18px solid transparent !important;border-bottom: 18px solid transparent !important;overflow: hidden;"> <br> </section> </section> </section> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">MongoDB是文档型数据库的代表,数据模型基于Bson,而Elasticsearch的文档数据模型是Json,Bson本质是Json的一种扩展,可以相互直接转换,且它们的数据模式都是可以自由扩展的,基本无限制。MongoDB本身定位与关系型数据库竞争,支持严格的事务隔离机制,在这个层面实际上与Elasticsearch产品定位不一样,但实际工作中,几乎没有公司会将核心业务数据放在MongoDB上,关系型数据库依然是第一选择。若超出这个定位,则Elasticsearh相比MongoDB有如下优点:</span></p> <p><br></p> <section data-role="list"> <ul class="list-paddingleft-2" style="padding-left: 30px;"> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">文档查询性能,倒排索引/KDB-Tree比B+Tree厉害。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">数据的聚合分析能力,ES本身提供了列式数据doc_value,比Mongo的行式要快不少。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">集群分片副本机制,ES架构设计更胜一筹。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">ES特色功能比MongoDB提供的更多,适用的场景范围更宽泛。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;"></span><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">文档数据样例,ObjectId由MongoDB内置自动生成。</span></p></li> </ul> </section> <p><br></p> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="0.2178329571106095" data-s="300,640" src="/upload/2a89e5d24cb3fd752dadd57491428d3.png" data-type="png" data-w="886" style=""></p> <p><br></p> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="0.8106194690265487" data-s="300,640" src="/upload/b20d3cac03e125eba6535b9fe17d1355.png" data-type="png" data-w="565" style=""></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;"><br></span></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">公司刚好有个项目,原来数据层基于MongoDB设计构建的,查询问题不少 ,后面成功迁移到Elasticsearch平台上,服务器数据量从15台降低到3台,查询性能还大幅度提升十倍,详细可阅读笔者另一篇文章</span><span style="color: rgb(62, 62, 62);font-size: 15px;caret-color: red;text-decoration: underline;">《<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA5MTc0NTMwNQ==&mid=2650719816&idx=1&sn=bef9f351b35d20326b6240f7e2df1608&chksm=887ddb3ebf0a522822082391254b2cd6ca8276d8015ead35dc7adbd21bd17a459d84a4727ba6&scene=21#wechat_redirect" textvalue="从MongoDB迁移到ES后,我们减少了80%的服务器" data-itemshowtype="11" tab="innerlink" data-linktype="2">从MongoDB迁移到ES后,我们减少了80%的服务器</a>》</span><br></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">抛开数据事务隔离,Elasticsearch可以完全替代MongoDB。</span></p> <p style="line-height: 1.75em;"><br></p> <section data-tools="135编辑器" data-id="39" style="border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;" data-color="#138bde" data-custom="#138bde"> <section style="max-width: 100%;margin-top: 0.8em;margin-bottom: 0.5em;overflow: hidden;text-align: left;"> <section data-brushtype="text" placeholder="请输入标题" style="height: 36px;display: inline-block;color: rgb(255, 255, 255);font-weight: bold;padding-right: 10px;padding-left: 10px;line-height: 36px;vertical-align: top;background-color: rgb(19, 139, 222);box-sizing: border-box !important;"> <span style="font-family: Helvetica, Arial, sans-serif;">7、ClickHouse</span> </section> <section style="display: inline-block;height: 36px;vertical-align: top;border-left: 9px solid #138bde;box-sizing: border-box !important;border-top: 18px solid transparent !important;border-bottom: 18px solid transparent !important;overflow: hidden;"> <br> </section> </section> </section> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">ClickHouse是一款MPP查询分析型数据库,近几年活跃度很高,很多头部公司都引入其中。我们为什么要引入呢,原因可能跟其他头部公司不太一样,如下:</span></p> <p><br></p> <section data-role="list"> <ul class="list-paddingleft-2" style="padding-left: 30px;"> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">笔者长期从事大数据工作,经常会碰到数据聚合的实时查询需求,早期我们会选择一款关系型数据库来做做聚合查询,如MySQL/PostgreSQL,稍微不注意就很容易出现性能瓶颈。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">后面引入Elasticsearch产品,其基于列式设计以及分片架构,性能各方面确实明显优于单节点的关系型数据库。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">Elasticsearch局限性也很明显,一是数据量超过千万或者亿级时,若聚合的列数太多,性能也到达瓶颈;二是不支持深度二次聚合,导致一些复杂的聚合需求,需要人工编写代码在外部实现,这又增加很多开发工作量。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;"></span><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">后面引入了ClickHouse,替代Elasticserach做深度聚合需求,性能表现不错,在数据量千万级亿级表现很好,且资源消耗相比之前降低不少,同样的服务器资源可以承担更多的业务需求。</span></p></li> </ul> </section> <p style="line-height: 1.75em;"><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">ClickHouse与Elasticsearch一样,都采用列式存储结构,都支持副本分片,不同的是ClickHouse底层有一些独特的实现,如下:</span></p> <p><br></p> <section data-role="list"> <ul class="list-paddingleft-2" style="padding-left: 30px;"> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">MergeTree 合并树表引擎,提供了数据分区、一级索引、二级索引。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;"></span><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">Vector Engine 向量引擎,数据不仅仅按列存储,同时还按向量(列的一部分)进行处理,这样可以更加高效地使用CPU。</span></p></li> </ul> </section> <p><br></p> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="0.8106194690265487" data-s="300,640" src="/upload/b20d3cac03e125eba6535b9fe17d1355.png" data-type="png" data-w="565" style=""></p> <p style="text-align: center;line-height: 1.75em;"><span style="color: #7f7f7f;font-size: 12px;">图示:ClickHouse在大数据平台中的位置</span><br></p> <p><br></p> <section data-tools="135编辑器" data-id="39" style="border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;" data-color="#138bde" data-custom="#138bde"> <section style="max-width: 100%;margin-top: 0.8em;margin-bottom: 0.5em;overflow: hidden;text-align: left;"> <section data-brushtype="text" placeholder="请输入标题" style="height: 36px;display: inline-block;color: rgb(255, 255, 255);font-weight: bold;padding-right: 10px;padding-left: 10px;line-height: 36px;vertical-align: top;background-color: rgb(19, 139, 222);box-sizing: border-box !important;"> <span style="font-family: Helvetica, Arial, sans-serif;">8、Druid</span> </section> <section style="display: inline-block;height: 36px;vertical-align: top;border-left: 9px solid #138bde;box-sizing: border-box !important;border-top: 18px solid transparent !important;border-bottom: 18px solid transparent !important;overflow: hidden;"> <br> </section> </section> </section> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">Durid是一个大数据MPP查询型数据产品,核心功能Rollup,所有的需要Rollup原始数据必须带有时间序列字段。Elasticsearch在6.3.X版本之后推出了此功能,此时两者产品形成竞争关系,谁高谁下,看应用场景需求。</span></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">Druid样本数据,必须带有time时间字段。</span></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="0.5896279594137542" data-s="300,640" src="/upload/ba5af36354da03bcbce2188fbcc0b4dd.png" data-type="png" data-w="887" style=""></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">笔者之前负责过公司所有Elasticsearch技术栈相关数据项目,当时也有碰到一些实时聚合查询返回部分数据的需求,但我们的需求不太一样,索引数据属于离线型更新,每天都会全部删除并重新创建索引插入数据,此时使用Elastic的版本是6.8.X,仅支持离线型数据Rollup,所以此功能没用上,Elastic在7.2.X版本之后才推出实时Rollup功能。</span></p> <p><br></p> <section data-role="list"> <ul class="list-paddingleft-2" style="padding-left: 30px;"> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">Druid更加专注,产品设计围绕Rollup展开,Elastic只是附带;</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">Druid支持多种外接数据,直接可以对接Kafka数据流,也可以直接对接平台自身内部数据;而Elastic仅支持内部索引数据,外部数据需要借助三方工具导入到索引里;</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">Druid在数据Rollup之后,会丢弃原始数据;Elastic在原有索引基础之后,生成新的Rollup之后的索引数据;</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">Druid与Elastic的技术架构非常类似,都支持节点职责分离,都支持横向扩展;</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">Druid与Elastic在数据模型上都支持倒排索引,基于此的搜索与过滤。</span></p></li> </ul> </section> <p><br></p> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="0.5625" data-s="300,640" src="/upload/a4e2b1eeb800cc35c424bd2b775322ba.png" data-type="png" data-w="1280" style=""></p> <p style="text-align: center;line-height: 1.75em;"><span style="color: #7f7f7f;font-size: 12px;">图示:Druid产品技术架构体系示意图</span></p> <p><br></p> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">关于Rollup这个大数据分析领域,若有大规模的Rollup的场景需求,个人更倾向于Druid。</span></p> <section data-role="paragraph"> <p><br></p> </section> <section data-tools="135编辑器" data-id="86318" data-color="#138bde" data-custom="#138bde"> <section style="margin-right: auto;margin-left: auto;"> <section style="margin-top: 2em;padding-top: 0.5em;padding-bottom: 0.5em;font-size: 1em;font-weight: inherit;line-height: 22.4px;border-style: solid none none;border-top-width: 1px;border-top-color: rgb(204, 204, 204);text-decoration: inherit;color: rgb(166, 166, 166);box-sizing: border-box;font-family: inherit;"> <section style="margin-top: -1.2em;text-align: center;border-width: initial;border-style: none;border-color: initial;line-height: 1.4;box-sizing: border-box;"> <span style="font-family: Helvetica, Arial, sans-serif;"><strong><span style="padding: 8px 23px;border-radius: 25px;color: rgb(255, 255, 255);font-weight: inherit;text-decoration: inherit;border-color: rgb(19, 139, 222);background-color: rgb(19, 139, 222);" data-brushtype="text">结语</span></strong></span> </section> </section> </section> </section> <p><br></p> <p style="line-height: 1.75em;"><strong><span style="color: #3e3e3e;font-size: 15px;">总结:</span></strong></p> <section data-role="list"> <ul class="list-paddingleft-2" style="padding-left: 30px;"> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">Elasticsearch产品功能全面,适用范围广,性能也不错,综合应用是首选。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">Elasticsearch在搜索查询领域,几乎完胜所有竞争产品,在笔者的技术栈看来,关系型数据库解决数据事务问题,Elasticsearch几乎解决一切搜索查询问题。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">Elasticsearch在数据分析领域,产品能力偏弱一些,简单通用的场景需求可以大规模使用,但在特定业务场景领域,还是要选择更加专业的数据产品,如前文中提到的复杂聚合、大规模Rollup、大规模的Key-Value。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">Elasticsearch越来越不像一个搜索引擎,更像是一个全能型的数据产品,几乎所有行业都在使用,业界非常受欢迎。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;"><span style="color: rgb(62, 62, 62);font-family: sans-serif;font-size: 15px;caret-color: rgb(255, 0, 0);">Elasticsearch</span>用得好,下班下得早。</span></p></li> </ul> </section> <p style="line-height: 1.75em;"><br></p> <p style="line-height: 1.75em;"><strong><span style="color: #3e3e3e;font-size: 15px;">注:</span></strong></p> <section data-role="list"> <ul class="list-paddingleft-2" style="padding-left: 30px;"> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;">内容来源于笔者实际工作中运用多种技术栈实现场景需求,得出的一些实战经验与总结思考,提供后来者借鉴参考。</span></p></li> <li><p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;">本文围绕Elastic的竞争产品对比仅限概要性分析,粒度较粗,深度有限,之后会有更加专业深入竞争产品分析文章,敬请期待。</span></p></li> </ul> <p style="line-height: 1.75em;"><span style="color: #3e3e3e;font-size: 15px;caret-color: red;"></span></p> </section> <p><br></p> <section style="font-size: 16px;letter-spacing: 0px;text-align: center;widows: 1;color: rgb(62, 62, 62);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;line-height: 1.6;background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%), linear-gradient(360deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%);background-size: 20px 20px;background-position: center center;"> <section powered-by="xiumi.us" style="transform: rotate(0deg);"> <section style="padding-right: 10px;padding-left: 10px;"> <section style="padding-right: 10px;padding-left: 10px;font-size: 15px;letter-spacing: 1px;"> <section powered-by="xiumi.us"> <section data-source="bj.96weixin.com" style="letter-spacing: 0.544px;font-size: 16px;color: rgb(63, 63, 63);"> <section style="text-align: inherit;border-width: 1px;border-style: solid;border-color: rgb(0, 187, 236);font-family: inherit;font-weight: inherit;text-decoration: inherit;background-color: rgb(239, 239, 239);"> <section style="margin-top: -1em;margin-right: 16px;margin-left: 16px;font-size: 1em;border-width: initial;border-style: none;border-color: initial;line-height: 1.4;"> <span style="padding: 3px 8px;display: inline-block;border-radius: 4px;color: rgb(255, 255, 255);font-family: inherit;font-weight: inherit;text-decoration: inherit;border-color: rgb(0, 187, 236);background-color: rgb(0, 187, 236);font-size: 14px;"> <section> 猜你喜欢 </section></span> </section> <section style="padding: 16px;line-height: 1.4;font-family: inherit;"> <p style="letter-spacing: 0.544px;white-space: pre-wrap;text-align: left;"><span style="font-size: 12px;letter-spacing: 0.544px;font-family: inherit;font-weight: inherit;text-align: inherit;text-decoration: inherit;">1、<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA5MTc0NTMwNQ==&mid=2650719816&idx=1&sn=bef9f351b35d20326b6240f7e2df1608&chksm=887ddb3ebf0a522822082391254b2cd6ca8276d8015ead35dc7adbd21bd17a459d84a4727ba6&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2">从MongoDB迁移到ES后,我们减少了80%的服务器</a></span></p> <p style="letter-spacing: 0.544px;white-space: pre-wrap;text-align: left;"><span style="font-size: 12px;letter-spacing: 0.544px;font-family: inherit;font-weight: inherit;text-align: inherit;text-decoration: inherit;">2、<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA5MTc0NTMwNQ==&mid=2650719856&idx=1&sn=7fcaf26b2df1268da8eef42204b99d22&chksm=887ddb06bf0a52107d0679cdae535c96b0ff52024e727453972b5a04416668a6ed80f33acdb8&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2">Redis 6.0 稳定版发布,支持多线程 IO</a></span></p> <p style="letter-spacing: 0.544px;white-space: pre-wrap;text-align: left;"><span style="font-size: 12px;">3、<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA5MTc0NTMwNQ==&mid=2650719852&idx=1&sn=a8bcbfac406a1afa1f0a1a75a6a516b8&chksm=887ddb1abf0a520c6c31a2e6242e9767db5ba7f539ef0302de64bbabefbb710c28d11ad6fb81&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2">Apache Flink 1.9新功能介绍及使用</a></span></p> <p style="letter-spacing: 0.544px;white-space: pre-wrap;text-align: left;"><span style="font-size: 12px;">4、<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzA5MTc0NTMwNQ==&mid=2650719847&idx=1&sn=5cbc20ae39756e39552a9a056c133a80&chksm=887ddb11bf0a52074f71202b954fb5c6c59d738bab798050f532d280f1b122f4b18306b22bcc&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2">32 道常见的 Kafka 面试题你都会吗?附答案</a></span></p> </section> </section> </section> </section> </section> </section> </section> </section> <p><br></p> <p style="font-size: 16px;letter-spacing: 0.544px;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: center;widows: 1;color: rgb(62, 62, 62);"><img class="rich_pages" data-ratio="0.7071942446043166" data-s="300,640" data-type="png" data-w="1390" src="/upload/9cf14aa6ee2a067d3da22c9381926a18.png" style="box-sizing: border-box !important;visibility: visible !important;width: 677px !important;"></p> <p style="font-size: 16px;letter-spacing: 0.544px;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: center;widows: 1;color: rgb(62, 62, 62);"><span style="color: rgb(255, 76, 0);">过往记忆大数据微信群,请添加微信:</span><span style="color: rgb(255, 76, 0);">fangzhen0219,备注【进群】</span></p> </section> </section> </section> </section> </section>
作者:微信小助手
<section style="line-height: 1.75em;" data-mpa-powered-by="yiban.io"> <span style="letter-spacing: 1px;font-size: 15px;">最近,有朋友问我说:</span> </section> <blockquote class="js_blockquote_wrap" data-type="2" data-source-title="" data-content-utf8-length="75" data-author-name="" data-url=""> <section class="js_blockquote_digest"> <section> <section style="line-height: 1.75em;"> <em><span style="letter-spacing: 1px;font-size: 15px;">沈老师,期权到底值不值钱,offer中允诺的期权,到底值多少钱,期权到底要关注哪些属性?</span></em> </section> <section style="line-height: 1.75em;"> <em><span style="letter-spacing: 1px;font-size: 15px;"><br></span></em> </section> <section style="line-height: 1.75em;"> <em><span style="letter-spacing: 1px;font-size: 15px;">公司发了期权,融资稀释了,上市合股了,个人利益到底是否受损?</span></em> </section> </section> </section> </blockquote> <p><span style="letter-spacing: 1px;font-size: 15px;">今天和大家聊聊期权,帮大家避坑。</span></p> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">提问:什么是期权(Option)?</span></strong> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">本质是一种权益,赋予持有人“以较低的价格购买股票,以获取差价收益”的权益。</span> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);letter-spacing: 1px;font-size: 15px;">画外音:不善于名词解释,暂且这么理解吧。</span></em></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">提问:公司发的期权,跳槽offer里HR承诺的期权,需要重点关注哪些要素?</span></strong> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">这三点,大家务必重点关注:</span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">(1)归属周期,归属节奏</span></strong> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">归属周期</span></strong> <span style="letter-spacing: 1px;font-size: 15px;">:期权需要过一段时间才能获取,通常是4年或5年归属;</span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">归属节奏</span></strong> <span style="letter-spacing: 1px;font-size: 15px;">:时间周期与归属比例;</span> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);letter-spacing: 1px;font-size: 15px;">画外音:目的是为了留住人才,用做长期激励。</span></em></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">例如,玩法一:</span></strong> <span style="letter-spacing: 1px;font-size: 15px;"></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">分4年成熟,每年成熟25%。</span> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);letter-spacing: 1px;font-size: 15px;">画外音:这是最常见的。</span></em></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">又例如:玩法二:</span></strong> <span style="letter-spacing: 1px;font-size: 15px;"></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">分4年成熟,头两年成熟50%,未来每半年成熟12.5%。</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 15px;">要规避的坑:看上去很美,但归属周期很长,例如8年。</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">(2)行权价格</span></strong> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">期权是要购买的,一般来说,公司上市前,行权价更低;公司上市后,行权价高。</span> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);letter-spacing: 1px;font-size: 15px;">画外音:风险与收益成正比。</span></em></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 15px;">要规避的坑:别只关注股数,要关注行权价。</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">(3)行权收益</span></strong> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">期权收益本质是赚取差价,所以不但要关注行权价,还要关注行权后股票的价值。</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">当然,如果股票价格低于行权价,可以选择不行权。</span> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);letter-spacing: 1px;font-size: 15px;">画外音:听说RRen网,当时有这个情况,巨坑。</span></em></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">案例:</span></strong> <span style="letter-spacing: 1px;font-size: 15px;"></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">SK,11年入职A公司,当时公司还未上市,SK判断,A公司有很强的上市预期,于是选择了降薪,但争取到6000股期权,分4年成熟,每年成熟25%,行权价0.1美元,每股价值约2美元。</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"><br></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">SK可以粗略的认为,期权部分,</span> <span style="letter-spacing: 1px;font-size: 15px;color: rgb(255, 76, 0);">每年</span> <span style="letter-spacing: 1px;font-size: 15px;">的价值是:</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">6000*25%*(2-0.1)*7=2W</span> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);letter-spacing: 1px;font-size: 15px;">画外音:公司做得好,每股是会升值的。</span></em></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">A公司于13年上市,上市当天收盘价27美金,16年,股价涨到80美金。</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"><br></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">此时,SK在A公司已经呆满4年,期权已经全部归属,可以粗略的认为,其期权</span> <span style="letter-spacing: 1px;font-size: 15px;color: rgb(255, 76, 0);">总收益</span> <span style="letter-spacing: 1px;font-size: 15px;">为:</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">6000*(80-0.1)*7=448W</span> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);letter-spacing: 1px;font-size: 15px;">画外音:平均每年112W左右。</span></em></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">见识到期权的威力了吧?</span></strong> <span style="letter-spacing: 1px;font-size: 15px;"></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">案例二:</span></strong> <span style="letter-spacing: 1px;font-size: 15px;"></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">XXOO,13年入职A公司,当时公司已经上市,争取到6000股期权,分4年成熟,每年成熟25%,行权价20美金,当时A公司股价为30美金。</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"><br></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">XXOO可以粗略的认为,期权部分,</span> <span style="letter-spacing: 1px;font-size: 15px;color: rgb(255, 76, 0);">每年</span> <span style="letter-spacing: 1px;font-size: 15px;">的价值是:</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">600*25%*(30-20)*7=10W</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">同样是6000股,期权收益却大不相同。</span> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);letter-spacing: 1px;font-size: 15px;">画外音:上市前风险高,上市后无风险,收益当然也不一样。</span></em></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">提问:公司融资了,期权比例稀释了,权益会受损吗?</span></strong> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 15px;">答案是,不会。</span> <span style="letter-spacing: 1px;font-size: 15px;">虽然融资会发行发行新股,比例会稀释,但收益不会变化。</span> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);letter-spacing: 1px;font-size: 15px;">画外音:本质是,融资后,投后估值会增加。</span></em></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">案例三:</span></strong> <span style="letter-spacing: 1px;font-size: 15px;"></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">A公司,估值10亿美金,发行了5亿股(每股价值约2美金),SK拥有6000股期权,价值约1.2W美金。</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"><br></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">12年,A公司融资1亿美金,新发行了5KW股(每股价值还是2美金),投后估值变为了11亿美金,虽然总股数增多了,但投后估值也增加了,对于员工来说,6000股仍价值1.2W美金。</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">提问:公司上市的时候合股了,3股合成一股,对于员工来说,股数减少了,收益会受损吗?</span></strong> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(255, 76, 0);letter-spacing: 1px;font-size: 15px;">答案是,不会。</span> <span style="letter-spacing: 1px;font-size: 15px;">虽然合股了,股数减少了,但价值翻倍了,收益仍不会变化。</span> <br> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">案例四:</span></strong> <span style="letter-spacing: 1px;font-size: 15px;"></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">A公司,5亿股,每股2美金,SK拥有6000股期权,价值约1.2W美金。</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"><br></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">13年,A公司上市了,3股合1股,SK就只拥有2000股了,但每股值6美金了,总价值仍是1.2W美金,收益仍不变。</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">好了,希望能解决大家一些疑问。</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">也希望,大家在拿期权,谈offer的时候,多关注归属周期,行权价格,行权收益,避免采坑。</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">另外,我不是期权专家,可能有些地方说的不准确,如果大家想对期权有更多了解,推荐我司<strong>人力资源总监</strong></span> <span style="letter-spacing: 1px;font-size: 15px;color: rgb(255, 76, 0);">杰西姐姐</span> <span style="letter-spacing: 1px;font-size: 15px;">,她是知乎大V,写了N篇关于期权的文章,解释得十分透彻,<strong>欢迎关注她的知乎专栏。</strong></span> </section> <section style="text-align: center;line-height: normal;"> <img class="rich_pages js_insertlocalimg" style="width: 243px;height: 302px;" data-ratio="1.2426614481409001" data-type="png" data-w="511" data-s="300,640" src="/upload/e213184ac07e228dbf47a22cb08c1df3.png"> </section> <section style="text-align: center;line-height: normal;"> <span style="font-size:13px;">扫码<span style="letter-spacing: 1px;">关注,不要问是不是单身,</span></span> <span style="letter-spacing: 1px;font-size: 13px;color: rgb(255, 76, 0);">撩就完了</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"><span style="font-size:13px;"></span> </span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">末了,有朋友问我,11年2美金,13年上市,16年80美金,40倍,哪个公司这么牛逼。</span> <span style="letter-spacing: 1px;font-size: 15px;">你猜呢?</span> </section> <section style="line-height: 1.75em;"> <span style="color: rgb(0, 82, 255);"><em><span style="color: rgb(0, 82, 255);letter-spacing: 1px;font-size: 15px;">画外音:只可惜,11年SK还是个一线小兵,只有6000股。</span></em></span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"> </span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;">希望大家加盟一家好公司,拿到几万期权,和公司一同成长,上市,翻40倍,实现财务自由。</span> </section> <section style="line-height: 1.75em;"> <span style="letter-spacing: 1px;font-size: 15px;"><br></span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">调研</span></strong> <span style="letter-spacing: 1px;font-size: 15px;">:你被期权坑过么?</span> </section> <section style="line-height: 1.75em;"> <strong><span style="letter-spacing: 1px;font-size: 15px;">作业</span></strong> <span style="letter-spacing: 1px;font-size: 15px;">:为什么上市时要合股,拆股?</span> </section>
作者:微信小助手
<p style="white-space: normal;text-align: center;"><span style="font-size: 14px;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);color: rgb(255, 76, 65);"></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.6395833333333333" data-s="300,640" src="/upload/6c811649f7717be6755ee26d99a7faa4.jpg" data-type="jpeg" data-w="960" style=""></p> <p style="white-space: normal;text-align: center;"><span style="text-align: left;font-size: 14px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;color: rgb(136, 136, 136);"></span>来自:码大叔</p> <p style="white-space: normal;text-align: center;"><span style="text-align: left;font-size: 14px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;color: rgb(136, 136, 136);"><br></span></p> <section style="white-space: normal;max-width: 100%;color: rgb(62, 62, 62);font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;text-align: start;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin: 10px auto;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;display: flex;justify-content: flex-start;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-left: 3px;max-width: 100%;box-sizing: border-box;border-width: 1px;border-style: solid;border-color: rgb(182, 139, 88);display: inline-block;overflow-wrap: break-word !important;"> <section style="max-width: 100%;width: 0px;height: 0px;border-bottom: 6px solid transparent;border-left: 6px solid rgb(182, 139, 88);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br> </section> </section> <section style="margin-left: 3px;max-width: 100%;box-sizing: border-box;border-width: 1px;border-style: solid;border-color: rgb(182, 139, 88);display: inline-block;overflow-wrap: break-word !important;"> <section style="max-width: 100%;width: 0px;height: 0px;border-bottom: 6px solid transparent;border-right: 6px solid rgb(182, 139, 88);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br> </section> </section> <section style="margin-left: 3px;max-width: 100%;box-sizing: border-box;background-color: rgb(182, 139, 88);height: 1px;flex: 1 1 0%;overflow-wrap: break-word !important;"> <br> </section> </section> <section style="padding-top: 1em;max-width: 100%;text-align: justify;line-height: 1.75em;letter-spacing: 1.5px;font-size: 14px;color: rgb(127, 92, 50);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">导读:支持多线程的Redis6.0版本于2020-05-02终于发布了,为什么Redis忽然要支持多线程?如何开启多线程?开启后性能提升效果如何?线程数量该如何设置?开启多线程后会不会有线程安全问题?多线程的实现原理是怎样的?带着这些疑问,我们来开启Redis新特性-多线程连环13问。</p> </section> </section> <section style="max-width: 100%;display: flex;justify-content: flex-start;align-items: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-right: 3px;max-width: 100%;box-sizing: border-box;background-color: rgb(182, 139, 88);height: 1px;flex: 1 1 0%;overflow-wrap: break-word !important;"> <br> </section> <section style="max-width: 100%;width: 35px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;width: 35px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.5555555555555556" src="/upload/70324b127228924f3edadd7dc8d3c54b.png" data-type="png" data-w="54" style="width: 35px;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"> </section> </section> </section> </section> <p style="white-space: normal;text-align: center;"><br></p> <section style="white-space: normal;max-width: 100%;box-sizing: border-box;color: rgb(62, 62, 62);font-size: 16px;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <section powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"> <section style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"> <section style="padding-right: 20px;padding-left: 20px;max-width: 100%;box-sizing: border-box;line-height: 0.8;overflow-wrap: break-word !important;"> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;text-align: center;overflow-wrap: break-word !important;"><br></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;text-align: center;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;color: rgb(0, 122, 170);font-size: 18px;overflow-wrap: break-word !important;"><br></span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;text-align: center;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;color: rgb(0, 122, 170);font-size: 18px;overflow-wrap: break-word !important;">Redis 6.0 来了</span></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;text-align: center;overflow-wrap: break-word !important;"><br></p> <p style="max-width: 100%;box-sizing: border-box;min-height: 1em;text-align: center;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;letter-spacing: 0px;font-size: 20px;color: rgb(0, 122, 170);overflow-wrap: break-word !important;">—</span></p> </section> </section> </section> </section> <section style="white-space: normal;text-indent: 2em;"> <br> </section> <p style="white-space: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);"> 在全国一片祥和IT民工欢度五一节假日的时候,Redis 6.0不声不响地于5 月 2 日正式发布了,吓得我赶紧从床上爬起来,学无止境!学无止境!</span></p> <p style="white-space: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);"> 对于6.0版本,Redis之父Antirez在RC1版本发布时(2019-12-19)在他的博客上连续用了几个“EST”词语来评价: </span></p> <p style="white-space: normal;"><br></p> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="150" data-source-title=""> <section class="js_blockquote_digest"> <section> <p style="white-space: normal;"><span style="font-size: 15px;">the most “enterprise” Redis version to date // 最”企业级”的</span></p> <p style="white-space: normal;"><span style="font-size: 15px;">the largest release of Redis ever as far as I can tell // 最大的</span></p> <p style="white-space: normal;"><span style="font-size: 15px;">the one where the biggest amount of people participated // 参与人数最多的</span></p> </section> </section> </blockquote> <p style="white-space: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);"> </span></p> <p style="white-space: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);">这个版本提供了诸多令人心动的新特性及功能改进,比如新网络协议RESP3,新的集群代理,ACL等,其中关注度最高的应该是“多线程”了,笔者也第一时间体验了一下,带着众多疑问,我们<span style="color: rgb(0, 0, 0);font-size: 15px;">来</span>一起开始“Redis 6.0 新特性-多线程连环13问”。</span></p> <p style="white-space: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.4059500959692898" data-s="300,640" src="/upload/9d5f9482bfdd755ba1799790c3738bc0.png" data-type="png" data-w="1042" style="width: 527px;height: 214px;"></p> <section style="white-space: normal;text-indent: 2em;"> <br> </section> <p style="color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);max-width: 100%;box-sizing: border-box;min-height: 1em;text-align: center;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;color: rgb(0, 122, 170);font-size: 18px;overflow-wrap: break-word !important;">Redis 6.0 多线程连环13问</span></p> <p style="color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);max-width: 100%;box-sizing: border-box;min-height: 1em;text-align: center;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box;color: rgb(0, 122, 170);font-size: 20px;text-align: center;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;">—</span></p> <p style="color: rgb(62, 62, 62);font-size: 16px;white-space: normal;background-color: rgb(255, 255, 255);max-width: 100%;box-sizing: border-box;min-height: 1em;text-align: center;overflow-wrap: break-word !important;"><br></p> <p><span style="color: rgb(255, 76, 65);"><strong><span style="font-size: 15px;">1.Redis6.0之前的版本真的是单线程吗?</span></strong></span></p> <p><span style="font-size: 15px;"> Redis在处理客户端的请求时,包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理,这就是所谓的“单线程”。但如果严格来讲从Redis4.0之后并不是单线程,除了主线程外,它也有后台线程在处理一些较为缓慢的操作,例如清理脏数据、无用连接的释放、大 key 的删除等等。</span></p> <p><span style="font-size: 15px;"><br></span></p> <p><span style="color: rgb(255, 76, 65);"><strong><span style="font-size: 15px;">2.Redis6.0之前为什么一直不使用多线程?</span></strong></span></p> <section style="text-indent: 2em;"> <span style="font-size: 15px;"> 官方曾做过类似问题的回复:使用Redis时,几乎不存在CPU成为瓶颈的情况, Redis主要受限于内存和网络。例如在一个普通的Linux系统上,Redis通过使用pipelining每秒可以处理100万个请求,所以如果应用程序主要使用O(N)或O(log(N))的命令,它几乎不会占用太多CPU。</span> </section> <section style="text-indent: 2em;"> <span style="font-size: 15px;">使用了单线程后,可维护性高。多线程模型虽然在某些方面表现优异,但是它却引入了程序执行顺序的不确定性,带来了并发读写的一系列问题,增加了系统复杂度、同时可能存在线程切换、甚至加锁解锁、死锁造成的性能损耗。Redis通过AE事件模型以及IO多路复用等技术,处理性能非常高,因此没有必要使用多线程。单线程机制使得 Redis 内部实现的复杂度大大降低,Hash 的惰性 Rehash、Lpush 等等 “线程不安全” 的命令都可以无锁进行。</span> </section> <p><span style="font-size: 15px;"><br></span></p> <p><span style="color: rgb(255, 76, 65);"><strong><span style="font-size: 15px;">3.Redis6.0为什么要引入多线程呢?</span></strong></span></p> <p><span style="font-size: 15px;"> Redis将所有数据放在内存中,内存的响应时长大约为100纳秒,对于小数据包,Redis服务器可以处理80,000到100,000 QPS,这也是Redis处理的极限了,对于80%的公司来说,单线程的Redis已经足够使用了。</span></p> <p><span style="font-size: 15px;"> 但随着越来越复杂的业务场景,有些公司动不动就上亿的交易量,因此需要更大的QPS。常见的解决方案是在分布式架构中对数据进行分区并采用多个服务器,但该方案有非常大的缺点,例如要管理的Redis服务器太多,维护代价大;某些适用于单个Redis服务器的命令不适用于数据分区<span style="font-size: 15px;">;</span>数据分区无法解决热点读/写问题<span style="font-size: 15px;">;</span>数据偏斜,重新分配和放大/缩小变得更加复杂等等。</span></p> <p><span style="font-size: 15px;"> 从Redis自身角度来说,因为读写网络的read/write系统调用占用了Redis执行期间大部分CPU时间,瓶颈主要在于网络的 IO 消耗, 优化主要有两个方向:</span></p> <p><span style="font-size: 15px;"> • 提高网络 IO 性能,典型的实现比如使用 DPDK 来替代内核网络栈的方式</span></p> <p><span style="font-size: 15px;"> • 使用多线程充分利用多核,典型的实现比如 Memcached。</span></p> <p><span style="font-size: 15px;"> 协议栈优化的这种方式跟 Redis 关系不大,支持多线程是一种最有效最便捷的操作方式。所以总结起来,redis支持多线程主要就是两个原因:</span></p> <p><span style="font-size: 15px;"> • 可以充分利用服务器 CPU 资源,目前主线程只能利用一个核</span></p> <p><span style="font-size: 15px;"> • 多线程任务可以分摊 Redis 同步 IO 读写负荷</span></p> <p><span style="font-size: 15px;"><br></span></p> <p><span style="color: rgb(255, 76, 65);"><strong><span style="font-size: 15px;">4.Redis6.0默认是否开启了多线程? </span></strong></span></p> <p><span style="font-size: 15px;"> Redis6.0的多线程默认是禁用的,只使用主线程。如需开启需要修改redis.conf配置文件:io-threads-do-reads yes</span></p> <p><span style="font-size: 15px;"> </span></p> <p style="text-align: center;"><img class="rich_pages" src="/upload/d208814a0c9db25d62db6e4699f32c2b.png" data-cropx1="1.7098765432098766" data-cropx2="291.53395061728395" data-cropy1="79.50925925925927" data-cropy2="118.83641975308642" data-ratio="0.13793103448275862" data-s="300,640" src="https://mmbiz.qpic.cn/mmbiz_jpg/DkA0VYrOHvtWkvO02tIickx6ibOgCywvlibpOoSj6Fd9SaGQNcjsvDUHl2gVep84hxRDXmiaWIq8MLd07zWUPZTj3g/640?wx_fmt=jpeg" data-type="jpeg" data-w="290" style="width: 402px;height: 55px;"></p> <p><br></p> <p><span style="color: rgb(255, 76, 65);"><strong><span style="font-size: 15px;">5.Redis6.0多线程开启时,线程数如何设置?</span></strong></span></p> <p><span style="font-size: 15px;"> 开启多线程后,还需要设置线程数,否则是不生效的。同样修改redis.conf配置文件</span></p> <p><span style="font-size: 15px;"> </span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.142433234421365" data-s="300,640" src="/upload/1445afecaeb7748c155943101d61b738.png" data-type="png" data-w="337" style=""></p> <p><br></p> <p><span style="font-size: 15px;"> 关于线程数的设置,官方有一个建议:4核的机器建议设置为2或3个线程,8核的建议设置为6个线程,线程数一定要小于机器核数。还需要注意的是,线程数并不是越大越好,官方认为超过了8个基本就没什么意义了。</span></p> <p><span style="font-size: 15px;"><br></span></p> <p><span style="color: rgb(255, 76, 65);"><strong><span style="font-size: 15px;">6.Redis6.0采用多线程后,性能的提升效果如何?</span></strong></span></p> <p><span style="font-size: 15px;"> Redis 作者 antirez 在 RedisConf 2019分享时曾提到:Redis 6 引入的多线程 IO 特性对性能提升至少是一倍以上。国内也有大牛曾使用unstable版本在阿里云esc进行过测试,GET/SET 命令在4线程 IO时性能相比单线程是几乎是翻倍了。</span></p> <p><br></p> <p><span style="font-size: 15px;"><strong>测试环境:</strong></span></p> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="133" data-source-title=""> <section class="js_blockquote_digest"> <section> <p><span style="font-size: 15px;">Redis Server: 阿里云 Ubuntu 18.04,8 CPU 2.5 GHZ, 8G 内存,主机型号 ecs.ic5.2xlarge</span></p> <p><span style="font-size: 15px;">Redis Benchmark Client: 阿里云 Ubuntu 18.04,8 2.5 GHZ CPU, 8G 内存,主机型号 ecs.ic5.2xlarge</span></p> </section> </section> </blockquote> <p><strong><span style="font-size: 15px;">测试结果:</span></strong></p> <p><span style="font-size: 15px;"> </span></p> <p style="text-align: center;"><img class="rich_pages" data-cropselx1="0" data-cropselx2="530" data-cropsely1="0" data-cropsely2="183" data-ratio="0.34641068447412354" data-s="300,640" src="/upload/8f16594760c6336370939515510cc88b.png" data-type="png" data-w="1198" style="width: 530px;height: 184px;"></p> <p><br></p> <p><span style="font-size: 15px;">详见:https://zhuanlan.zhihu.com/p/76788470</span></p> <p><span style="font-size: 15px;"><br></span></p> <p><strong><span style="font-size: 15px;">说明1</span></strong><span style="font-size: 15px;">:这些性能验证的测试并没有针对严谨的延时控制和不同并发的场景进行压测。数据仅供验证参考而不能作为线上指标。</span></p> <p><strong><span style="font-size: 15px;">说明2</span></strong><span style="font-size: 15px;">:如果开启多线程,至少要4核的机器,且Redis实例已经占用相当大的CPU耗时的时候才建议采用,否则使用多线程没有意义。所以估计80%的公司开发人员看看就好。</span></p> <p><strong><span style="font-size: 15px;"><br></span></strong></p> <p><span style="color: rgb(255, 76, 65);"><strong><span style="font-size: 15px;">7.Redis6.0多线程的实现机制? </span></strong></span></p> <p><span style="color: rgb(255, 76, 65);"><strong><span style="font-size: 15px;"><br></span></strong></span></p> <p style="text-align: center;"><img class="rich_pages" data-cropselx1="0" data-cropselx2="554" data-cropsely1="0" data-cropsely2="394" data-ratio="0.724972497249725" data-s="300,640" src="/upload/e16c00a17a0abda311f7d8713a3ca134.png" data-type="png" data-w="909" style="width: 554px;height: 402px;"></p> <p style="text-align: center;"><br></p> <p><strong><span style="font-size: 15px;">流程简述如下:</span></strong></p> <p><span style="font-size: 15px;">1、主线程负责接收建立连接请求,获取 socket 放入全局等待读处理队列</span></p> <p><span style="font-size: 15px;">2、主线程处理完读事件之后,通过 RR(Round Robin) 将这些连接分配给这些 IO 线程</span></p> <p><span style="font-size: 15px;">3、主线程阻塞等待 IO 线程读取 socket 完毕</span></p> <p><span style="font-size: 15px;">4、主线程通过单线程的方式执行请求命令,请求数据读取并解析完成,但并不执行</span></p> <p><span style="font-size: 15px;">5、主线程阻塞等待 IO 线程将数据回写 socket 完毕</span></p> <p><span style="font-size: 15px;">6、解除绑定,清空等待队列</span></p> <p><span style="font-size: 15px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="1.2375601926163724" data-s="300,640" src="/upload/b8e3794dfca5d03dc1caa9e9a861f216.png" data-type="png" data-w="623" style=""></p> <p style="text-align: center;"><span style="font-size: 12px;color: rgb(136, 136, 136);">(图片来源:https://ruby-china.org/topics/38957)</span></p> <p><span style="font-size: 15px;"><br></span></p> <p><span style="font-size: 15px;"><strong>该设计有如下特点:</strong></span></p> <p><span style="font-size: 15px;">1、IO 线程要么同时在读 socket,要么同时在写,不会同时读或写</span></p> <p><span style="font-size: 15px;">2、IO 线程只负责读写 socket 解析命令,不负责命令处理</span></p> <p><span style="font-size: 15px;"><br></span></p> <p><span style="color: rgb(255, 76, 65);"><strong><span style="font-size: 15px;">8.开启多线程后,是否会存在线程并发安全问题? </span></strong></span></p> <section style="text-indent: 2em;"> <span style="font-size: 15px;">从上面的实现机制可以看出,Redis的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程顺序执行。所以我们不需要去考虑控制 key、lua、事务,LPUSH/LPOP 等等的并发及线程安全问题。</span> </section> <p><span style="font-size: 15px;"><br></span></p> <p style="white-space: normal;"><span style="color: rgb(255, 76, 65);"><strong><span style="font-size: 15px;">9.Linux环境上如何安装Redis6.0.1(6.0的正式版是6.0.1)? </span></strong></span></p> <section style="white-space: normal;text-indent: 2em;"> <span style="font-size: 15px;">这个和安装其他版本的redis没有任何区别,整个流程跑下来也没有任何的坑,所以这里就不做描述了。唯一要注意的就是配置多线程数一定要小于cpu的核心数,查看核心数量命令:<br></span> </section> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="makefile"><code><span class="code-snippet_outer">[root@centos7.5 ~]<span class="code-snippet__comment"># lscpu</span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__section">Architecture: x86_64</span></span></code><code><span class="code-snippet_outer">CPU op-mode(s): 32-bit, 64-bit</span></code><code><span class="code-snippet_outer">Byte Order: Little Endian</span></code><code><span class="code-snippet_outer"><span class="code-snippet__section">CPU(s): 4</span></span></code><code><span class="code-snippet_outer">On-line CPU(s) list: 0-3</span></code></pre> </section> <p><br></p> <p><strong><span style="font-size: 15px;color: rgb(255, 76, 65);">10.Redis6.0的多线程和Memcached多线程模型进行对比</span></strong></p> <section style="text-indent: 2em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);font-family: Verdana, Arial, Helvetica, sans-serif;text-align: start;background-color: rgb(255, 255, 255);">前些年<span style="font-family: Verdana, Arial, Helvetica, sans-serif;text-align: start;text-indent: 34px;background-color: rgb(255, 255, 255);">memcached 是各大互联网公司常用的缓存方案</span>,因此redis 和 memcached 的区别基本成了面试官缓存方面必问的面试题,最近几年memcached用的少了,基本都是 redis。不过随着Redis6.0加入了多线程特性,类似的问题可能还会出现,接下来我们只针对多线程模型来简单比较一下。</span> </section> <p><br></p> <p style="text-align: center;"><img class="rich_pages js_insertlocalimg" data-ratio="0.7531645569620253" data-s="300,640" src="/upload/642f0773ecea36c2d22e3fed3ccd79de.png" data-type="png" data-w="948" style=""></p> <p style="text-align: center;"><br></p> <p><span style="font-size: 15px;">如上图所示:Memcached 服务器采用 master-woker 模式进行工作,服务端采用 socket 与客户端通讯。主线程、工作线程 采用 pipe管道进行通讯。主线程采用 libevent 监听 listen、accept 的读事件,事件响应后将连接信息的数据结构封装起来,根据算法选择合适的工作线程,将连接任务携带连接信息分发出去,相应的线程利用连接描述符建立与客户端的socket连接 并进行后续的存取数据操作。</span></p> <p><span style="font-size: 15px;"><br></span></p> <p><span style="font-size: 15px;">Redis6.0与Memcached多线程模型对比:</span></p> <p><br></p> <p><span style="font-size: 15px;">相同点:都采用了 master线程-worker 线程的模型</span></p> <p><span style="font-size: 15px;">不同点:Memcached 执行主逻辑也是在 worker 线程里,模型更加简单,实现了真正的线程隔离,符合我们对线程隔离的常规理解。而 Redis 把处理逻辑交还给 master 线程,虽然一定程度上增加了模型复杂度,但也解决了线程并发安全等问题。</span></p> <p><span style="font-size: 15px;"><br></span></p> <p><span style="font-size: 15px;color: rgb(255, 76, 65);"><strong>11.Redis作者是如何点评 “多线程”这个新特性的?</strong></span></p> <section style="text-indent: 2em;"> <span style="font-size: 15px;">关于多线程这个特性,在6.0 RC1时,Antirez曾做过说明:</span> </section> <section style="text-indent: 2em;"> <span style="font-size: 15px;">Redis支持多线程有2种可行的方式:第一种就是像“memcached”那样,一个Redis实例开启多个线程,从而提升GET/SET等简单命令中每秒可以执行的操作。这涉及到I/O、命令解析等多线程处理,因此,我们将其称之为“I/O threading”。另一种就是允许在不同的线程中执行较耗时较慢的命令,以确保其它客户端不被阻塞,我们将这种线程模型称为“Slow commands threading”。</span> </section> <p><span style="font-size: 15px;">经过深思熟虑,Redis不会采用“I/O threading”,redis在运行时主要受制于网络和内存,所以提升redis性能主要是通过在多个redis实例,特别是redis集群。接下来我们主要会考虑改进两个方面:</span></p> <p><span style="font-size: 15px;">1. Redis集群的多个实例通过编排能够合理地使用本地实例的磁盘,避免同时重写AOF。</span></p> <p><span style="font-size: 15px;">2.提供一个Redis集群代理,便于用户在没有较好的集群协议客户端时抽象出一个集群。</span></p> <p><span style="font-size: 15px;">补充说明一下,Redis和memcached一样是一个内存系统,但不同于Memcached。多线程是复杂的,必须考虑使用简单的数据模型,执行LPUSH的线程需要服务其他执行LPOP的线程。</span></p> <p><span style="font-size: 15px;">我真正期望的实际是“slow operations threading”,在redis6或redis7中,将提供“key-level locking”,使得线程可以完全获得对键的控制以处理缓慢的操作。</span></p> <p><span style="font-size: 15px;">详见:http://antirez.com/news/126</span></p> <p><span style="font-size: 15px;"><br></span></p> <p><span style="color: rgb(255, 76, 65);"><strong><span style="font-size: 15px;">12.Redis线程中经常提到IO多路复用,如何理解?</span></strong></span></p> <p><span style="color: rgb(255, 76, 65);"><strong><span style="font-size: 15px;"><br></span></strong></span></p> <section style="text-indent: 2em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;">这是IO模型的一种,即经典的Reactor设计模式,有时也称为异步阻塞IO。</span> </section> <section style="text-indent: 2em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span> </section> <p style="text-align: center;"><img class="rich_pages" src="/upload/6273aa6a1a4333fb5599e89222ac09b4.jpg" data-cropx1="0" data-cropx2="649.0000000000001" data-cropy1="1.1499766573295984" data-cropy2="341.54306722689074" data-ratio="0.5254237288135594" data-s="300,640" src="https://mmbiz.qpic.cn/mmbiz_jpg/DkA0VYrOHvtWkvO02tIickx6ibOgCywvlibW8ELDCn2rxX7pJPbhkhJt1U01WTpI6uw5NWyA4iaB1iaXVxL8VunHZMQ/640?wx_fmt=jpeg" data-type="jpeg" data-w="649" style="width: 561px;height: 296px;"></p> <p style="text-align: center;"><br></p> <p style="text-indent: 2em;"><span style="font-size: 15px;">多路指的是多个socket连接,复用指的是复用一个线程。多路复用主要有三种技术:select,poll,epoll。epoll是最新的也是目前最好的多路复用技术。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗),且Redis在内存中操作数据的速度非常快(内存内的操作不会成为这里的性能瓶颈),主要以上两点造就了Redis具有很高的吞吐量。</span></p> <p style="text-indent: 2em;"><br></p> <p style="white-space: normal;"><span style="color: rgb(255, 76, 65);"><strong><span style="font-size: 15px;">13.你知道Redis的彩蛋LOLWUT吗?</span></strong></span></p> <section style="white-space: normal;text-indent: 2em;"> <span style="font-size: 15px;">这个其实从Redis5.0就开始有了,但是原谅我刚刚知道。作者是这么描述这个功能的《LOLWUT: a piece of art inside a database command<span style="font-size: 15px;text-indent: 34px;">》</span>,“数据库命令中的一件艺术品<span style="font-size: 15px;text-indent: 34px;">”</span>。你可以把它称之为情怀,也可以称之为彩蛋,具体是什么,我就不透露了。和我一样不清楚是什么的小伙伴可以参见:<span style="font-size: 15px;text-indent: 34px;">http://antirez.com/news/123,每次运行都会随机生成的噢。</span></span> </section> <section style="white-space: normal;text-indent: 2em;"> <span style="font-size: 15px;"><span style="font-size: 15px;text-indent: 34px;"><br></span></span> </section> <section style="white-space: normal;text-indent: 0em;"> <img data-ratio="0.595" src="/upload/bc97d5b02077b3b641da4f692d2da2d.png" data-type="png" data-w="800" style="text-align: left;text-indent: 2em;width: 458px;height: 274px;"> </section> <section style="white-space: normal;text-indent: 2em;text-align: left;"> <span style="color: rgb(0, 0, 0);font-size: 15px;text-indent: 2em;"></span> </section> <section style="white-space: normal;text-indent: 2em;"> <span style="text-indent: 34px;"></span> </section> <section style="white-space: normal;text-indent: 2em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"></span> </section> <section style="white-space: normal;text-indent: 2em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span> </section> <p style="white-space: normal;text-align: left;"><strong><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 14px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);color: rgb(136, 136, 136);">| 参考、致谢</span></strong><br></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">Rdis作者Antirez的博客:http://antirez.com</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">https://www.zhihu.com/question/26943938/answer/68773398</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">https://zhuanlan.zhihu.com/p/76788470</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">http://www.web-lovers.com/redis-source-6-rc-mult-thread.html</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">https://ruby-china.org/topics/38957</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">https://redis.io/topics/faq#redis-is-single-threaded-how-can-i-exploit-multiple-cpu--cores</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">https://juejin.im/post/5e9ae485f265da47b04d95d2</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">https://www.cnblogs.com/gattaca/p/6929361.html</span></p> <p style="white-space: normal;text-align: left;"><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);color: rgb(136, 136, 136);font-size: 12px;">本文图片来自互联网,版权归原作者所有</span></p> <p style="text-align: center;"><br></p> <p style="white-space: normal;text-align: center;"><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 14px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);color: rgb(136, 136, 136);">< END ></span></p> <p style="white-space: normal;text-align: center;"><br></p> <pre ng-bind-html="message.MMActualContent" style="max-width: 100%;color: rgb(62, 62, 62);letter-spacing: 0.544px;background-color: rgb(255, 255, 255);font-size: 15px;word-spacing: 2px;white-space: pre-wrap;word-break: normal;box-sizing: border-box !important;word-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-align: left;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(255, 76, 0);box-sizing: border-box !important;word-wrap: break-word !important;">特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:</span></p><p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;"><img class="rich_pages" data-ratio="0.5555555555555556" data-s="300,640" data-type="png" data-w="900" src="/upload/c86a3619353fb9ac25fa19df4ec53cb1.png" style="box-sizing: border-box !important;word-wrap: break-word !important;visibility: visible !important;width: 677px !important;"></p><pre ng-bind-html="message.MMActualContent" style="max-width: 100%;letter-spacing: 0.544px;font-size: 16px;text-align: left;white-space: pre-wrap;word-break: normal;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;">长按订阅更多精彩▼</p><p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-align: center;box-sizing: border-box !important;word-wrap: break-word !important;"><img class="rich_pages" data-ratio="1" data-s="300,640" data-type="jpeg" data-w="258" width="205px" src="/upload/cff6d4b6b063076da067005708088611.jpg" style="box-shadow: rgb(170, 170, 170) 0px 0px 14px 0px;box-sizing: border-box !important;word-wrap: break-word !important;visibility: visible !important;width: 205px !important;"></p><p style="max-width: 100%;min-height: 1em;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;text-align: right;line-height: 2em;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;word-wrap: break-word !important;">如有收获,点个在看,诚挚感谢</span></p></pre></pre>