面试Redis

<body><div id="juejin" data-v-2a21baac=""><div class="global-component-box" data-v-2a21baac=""><!----><div data-v-7b82dbda="" data-v-2a21baac="" class="alert-list alert-list"></div><div data-v-14e6422e="" data-v-2a21baac="" class="suspension-panel suspension-panel"><button data-v-14e6422e="" title="回到顶部" class="btn to-top-btn" style=""><i data-v-14e6422e="" class="ion-android-arrow-dropup"></i></button><button data-v-14e6422e="" title="建议反馈" class="btn meiqia-btn" style=""><i data-v-14e6422e="" class="ion-chatbubble-working"></i></button></div><!----><!----><div class="emoji-barrage" data-v-3bcc3fe1="" data-v-2a21baac=""><!----></div><div class="book-new-user-award-popup" style="display:none;" data-v-4b0794bc="" data-v-2a21baac=""><div class="content-box" style="display:;" data-v-4b0794bc=""><div class="close ion-close-round" data-v-4b0794bc=""></div><div class="header" data-v-4b0794bc=""><div class="icon" data-v-4b0794bc=""><img src="https://b-gold-cdn.xitu.io/v3/static/img/icon.a87e5ae.svg" data-v-4b0794bc=""></div><div class="txt" data-v-4b0794bc="">新人专享好礼</div></div><div class="desc" data-v-4b0794bc="">凡未购买过小册的用户,均可领取三张 5 折新人专享券,购买小册时自动使用专享券,最高可节省 45 元。</div><div class="tickets" data-v-4b0794bc=""><div class="ticket" data-v-4b0794bc=""><div class="ticket__inner" data-v-4b0794bc=""><div class="enjoy" data-v-4b0794bc=""><span class="new-title" data-v-4b0794bc="">小册新人 5 折券</span></div><div class="sale" data-v-4b0794bc="">最高可省 15 元</div></div></div><div class="ticket" data-v-4b0794bc=""><div class="ticket__inner" data-v-4b0794bc=""><div class="enjoy" data-v-4b0794bc=""><span class="new-title" data-v-4b0794bc="">小册新人 5 折券</span></div><div class="sale" data-v-4b0794bc="">最高可省 15 元</div></div></div><div class="ticket" data-v-4b0794bc=""><div class="ticket__inner" data-v-4b0794bc=""><div class="enjoy" data-v-4b0794bc=""><span class="new-title" data-v-4b0794bc="">小册新人 5 折券</span></div><div class="sale" data-v-4b0794bc="">最高可省 15 元</div></div></div></div><div class="remark" data-v-4b0794bc="">注:专享券的使用期限在领券的七天内。</div><div class="submit-btn" data-v-4b0794bc="">一键领取</div></div><div class="model success" style="display:none;" data-v-4b0794bc=""><div class="heading" data-v-4b0794bc="">领取成功</div><div class="content-text" data-v-4b0794bc="">购买小册时自动使用专享券</div><div class="btn-success-footer" data-v-4b0794bc=""><div class="btn-ok" data-v-4b0794bc="">知道了</div><div class="btn-ok btn-link" data-v-4b0794bc="">前往小册首页</div></div></div><div class="model fail" style="display:none;" data-v-4b0794bc=""><div class="heading" data-v-4b0794bc="">领取失败</div><div class="content-text" data-v-4b0794bc="">本活动仅适用于小册新用户</div><div class="btn-ok" data-v-4b0794bc="">知道了</div></div></div><!----><!----><div class="bind-phone-number-modal-box" data-v-3b825027="" data-v-2a21baac=""><div st:block="bindPhoneNumberModal" class="modal-mask" style="display:none;" data-v-3b825027=""></div><form class="bind-phone-number-form" style="display:none;" data-v-3b825027=""><i title="关闭" class="close-btn ion-close-round" data-v-3b825027=""></i><h1 class="title" data-v-3b825027="">提示</h1><h2 class="hint" data-v-3b825027="">根据我国<a href="http://www.cac.gov.cn/2017-08/25/c_1121541842.htm" target="_blank" style="color:#007fff">《互联网跟帖评论服务管理规定》</a>,您需要绑定手机号后才可在掘金社区内发布内容。</h2><div class="input-group" data-v-3b825027=""><div class="input-box" data-v-3b825027=""><input maxlength="64" placeholder="请输入要绑定的手机号码" value="" class="input" data-v-3b825027=""></div><!----><!----></div><button st:name="bindBtn" class="btn" data-v-3b825027="">绑定手机</button></form></div></div><!----><div data-v-23c7d456="" data-v-7407bc26="" data-v-2a21baac="" class="view-container"><div data-v-23c7d456="" class="main-header-box"><header data-v-26abcca9="" data-v-23c7d456="" class="main-header main-header unauthorized visible"><div data-v-26abcca9="" class="container"><a data-v-26abcca9="" href="/" class="logo"><img data-v-26abcca9="" src="https://b-gold-cdn.xitu.io/v3/static/img/logo.a7995ad.svg" alt="掘金" class="logo-img"><img data-v-26abcca9="" src="https://b-gold-cdn.xitu.io/v3/static/img/simplify-logo.3e3c253.svg" alt="掘金" class="mobile"></a><nav data-v-26abcca9="" role="navigation" class="main-nav"><ul data-v-26abcca9="" class="nav-list"><li data-v-26abcca9="" class="main-nav-list"><div data-v-26abcca9="" class="phone-show-menu"><span data-v-26abcca9="">首页</span><div data-v-26abcca9="" class="icon ion-arrow-down-b"></div></div><ul data-v-26abcca9="" class="phone-hide"><li data-v-26abcca9="" class="nav-item link-item route-active"><a data-v-26abcca9="" href="/">首页</a></li><li data-v-26abcca9="" class="nav-item link-item activities"><a data-v-26abcca9="" href="/pins">沸点</a></li><li data-v-26abcca9="" class="nav-item link-item"><a data-v-26abcca9="" href="/topics">话题</a></li><li data-v-26abcca9="" class="nav-item link-item book"><a data-v-26abcca9="" href="/books">小册</a></li><li data-v-26abcca9="" class="nav-item link-item"><a data-v-26abcca9="" href="/events/all">活动</a></li></ul></li><li data-v-26abcca9="" class="nav-item search"><form data-v-26abcca9="" role="search" class="search-form"><input data-v-26abcca9="" type="search" maxlength="32" placeholder="搜索掘金" class="search-input"><img data-v-26abcca9="" src="https://b-gold-cdn.xitu.io/v3/static/img/juejin-search-icon.6f8ba1b.svg" alt="搜索" class="search-icon"></form></li><!----><!----><!----><li data-v-26abcca9="" class="nav-item submit"><img data-v-26abcca9="" src="https://b-gold-cdn.xitu.io/v3/static/img/submit-icon.53f4253.svg" class="icon"><span data-v-26abcca9="">写文章</span><!----></li><li data-v-26abcca9="" class="nav-item auth"><span data-v-26abcca9="" class="login">登录</span><span data-v-26abcca9="" class="register">注册</span></li></ul></nav></div></header></div><main data-v-23c7d456="" class="container main-container"><div data-v-7407bc26="" data-v-23c7d456="" class="view column-view"><div data-v-7407bc26="" data-v-23c7d456="" class="main-area article-area shadow"><article data-v-7407bc26="" itemscope="itemscope" itemtype="http://schema.org/Article" class="article" data-v-23c7d456=""><meta itemprop="url" content="https://juejin.im/post/5e7b43945188255dda23d1e3"><meta itemprop="headline" content="妈妈再也不担心我面试被Redis问得脸都绿了"><meta itemprop="keywords" content="Redis"><meta itemprop="datePublished" content="2020-03-25T11:42:35.881Z"><meta itemprop="image" content="https://b-gold-cdn.xitu.io/icon/icon-128.png"><div itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person"><meta itemprop="name" content="我没有三颗心脏"><meta itemprop="url" content="https://juejin.im/user/5cfb61a36fb9a07ef819ef3a"></div><div itemprop="publisher" itemscope="itemscope" itemtype="http://schema.org/Organization"><meta itemprop="name" content="掘金"><div itemprop="logo" itemscope="itemscope" itemtype="https://schema.org/ImageObject"><meta itemprop="url" content="https://b-gold-cdn.xitu.io/icon/icon-white-180.png"><meta itemprop="width" content="180"><meta itemprop="height" content="180"></div></div><div data-v-7407bc26="" class="author-info-block"><a data-v-7407bc26="" href="/user/5cfb61a36fb9a07ef819ef3a" target="_blank" rel="" class="avatar-link"><div data-v-292b3648="" data-v-11331c20="" data-v-7407bc26="" data-src="https://user-gold-cdn.xitu.io/2019/6/8/16b35f5985473ab9?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1" class="lazy avatar avatar loaded" style="background-image: url(&quot;https://user-gold-cdn.xitu.io/2019/6/8/16b35f5985473ab9?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1&quot;);"></div></a><div data-v-7407bc26="" class="author-info-box"><a data-v-44e95489="" data-v-7407bc26="" href="/user/5cfb61a36fb9a07ef819ef3a" target="_blank" rel="" class="username username ellipsis">我没有三颗心脏<a data-v-00e1e43c="" data-v-44e95489="" href="/book/5c90640c5188252d7941f5bb/section/5c9065385188252da6320022" target="_blank" rel="" class="rank"><img data-v-00e1e43c="" src="https://b-gold-cdn.xitu.io/v3/static/img/lv-2.f597b88.svg" alt="lv-2"></a></a><div data-v-7407bc26="" class="meta-box"><time data-v-7407bc26="" datetime="2020-03-25T11:42:35.881Z" title="Wed Mar 25 2020 19:42:35 GMT+0800 (中国标准时间)" class="time">2020年03月25日</time><span data-v-7407bc26="" class="views-count">阅读 1915</span><!----></div></div><button data-v-fa88a374="" data-v-7407bc26="" class="follow-button follow">关注</button></div><!----><h1 data-v-7407bc26="" class="article-title">妈妈再也不担心我面试被Redis问得脸都绿了</h1><div data-v-7407bc26="" data-id="5e7b43ab6fb9a07cde650099" itemprop="articleBody" class="article-content"><section style="font-size: 16px; color: black; padding: 0 10px; line-height: 1.6; word-spacing: 0px; letter-spacing: 0px; word-break: break-word; word-wrap: break-word; text-align: left; font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif; margin-top: -10px;" data-website="https://www.mdnice.com" data-tool="mdnice编辑器" id="nice"><figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117fe8d350c9a?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="527" src="https://user-gold-cdn.xitu.io/2020/3/25/171117fe8d350c9a?imageView2/0/w/1280/h/960/format/webp/ignore-error/1"></figure> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;">长文前排提醒,收藏向前排提醒,素质三连 <strong style="font-weight: bold; color: #BF360C;">(转发 + 在看 + 留言)</strong> 前排提醒!</p> </blockquote> <h1 style="font-weight: bold; font-size: 1.6em; background-color: rgb(0, 150, 136); margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; color: rgb(255, 255, 255) !important; padding: 1px 8px !important;" data-tool="mdnice编辑器" data-id="heading-0"><span style="display: none;" class="prefix"></span><span class="content">前言</span><span class="suffix"></span></h1> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117fe8d2f466f?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="583" data-height="318" src="https://user-gold-cdn.xitu.io/2020/3/25/171117fe8d2f466f?imageView2/0/w/1280/h/960/format/webp/ignore-error/1"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><strong style="font-weight: bold; color: #BF360C;">Redis</strong> 作为一个开源的,高级的键值存储和一个适用的解决方案,已经越来越在构建 <strong style="font-weight: bold; color: #BF360C;">「高性能」</strong>、<strong style="font-weight: bold; color: #BF360C;">「可扩展」</strong> 的 Web 应用上发挥着举足轻重的作用。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">当今互联网技术架构中 <strong style="font-weight: bold; color: #BF360C;">Redis</strong> 已然成为了应用得最广泛的中间件之一,它也是中高级后端工程 <strong style="font-weight: bold; color: #BF360C;">技术面试</strong> 中面试官最喜欢问的工程技能之一,不仅仅要求着我们对 <strong style="font-weight: bold; color: #BF360C;">基本的使用</strong> 进行掌握,更要深层次地理解 Redis <strong style="font-weight: bold; color: #BF360C;">内部实现</strong> 的细节原理。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">熟练掌握 Redis,甚至可以毫不夸张地说已经半只脚踏入心仪的公司了。下面我们一起来盘点回顾一下 Redis 的面试经典问题,就不要再被面试官问得 <strong style="font-weight: bold; color: #BF360C;">脸都绿了</strong> 呀!</p> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117fe8fd1d10e?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="81" data-height="69" src="https://user-gold-cdn.xitu.io/2020/3/25/171117fe8fd1d10e?imageView2/0/w/1280/h/960/format/webp/ignore-error/1"></figure> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">Ps</strong>: 我把 <strong style="font-weight: bold; color: #BF360C;">重要的知识点</strong> 都做成了 <strong style="font-weight: bold; color: #BF360C;">图片</strong>,希望各位 <strong style="font-weight: bold; color: #BF360C;">"用餐愉快"</strong>。<em style="font-style: italic; color: #009688;">(不错记得付餐费.. 点个赞留个言..)</em></section></li></ul> <h1 style="font-weight: bold; font-size: 1.6em; background-color: rgb(0, 150, 136); margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; color: rgb(255, 255, 255) !important; padding: 1px 8px !important;" data-tool="mdnice编辑器" data-id="heading-1"><span style="display: none;" class="prefix"></span><span class="content">一、基础篇</span><span class="suffix"></span></h1> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117fe92812777?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="388" src="https://user-gold-cdn.xitu.io/2020/3/25/171117fe92812777?imageView2/0/w/1280/h/960/format/webp/ignore-error/1"></figure> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-2"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">什么是 Redis ?</span><span class="suffix"></span></h2> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-3"><span style="display: none;" class="prefix"></span><span class="content">先解释 Redis 基本概念</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><strong style="font-weight: bold; color: #BF360C;">Redis</strong> (<strong style="font-weight: bold; color: #BF360C;">Re</strong>mote <strong style="font-weight: bold; color: #BF360C;">Di</strong>ctionary <strong style="font-weight: bold; color: #BF360C;">S</strong>erver) 是一个使用 <strong style="font-weight: bold; color: #BF360C;">C 语言</strong> 编写的,开源的 <em style="font-style: italic; color: #009688;">(BSD许可)</em> 高性能 <strong style="font-weight: bold; color: #BF360C;">非关系型</strong> <em style="font-style: italic; color: #009688;">(NoSQL)</em> 的 <strong style="font-weight: bold; color: #BF360C;">键值对数据库</strong>。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-4"><span style="display: none;" class="prefix"></span><span class="content">简单提一下 Redis 数据结构</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><strong style="font-weight: bold; color: #BF360C;">Redis</strong> 可以存储 <strong style="font-weight: bold; color: #BF360C;">键</strong> 和 <strong style="font-weight: bold; color: #BF360C;">不同类型数据结构值</strong> 之间的映射关系。键的类型只能是字符串,而值除了支持最 <strong style="font-weight: bold; color: #BF360C;">基础的五种数据类型</strong> 外,还支持一些 <strong style="font-weight: bold; color: #BF360C;">高级数据类型</strong>:</p> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117fe92d4283c?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="814" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;814&quot;></svg>"></figure> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;">一定要说出一些高级数据结构 <em style="font-style: italic; color: #009688;">(当然你自己也要了解.. 下面会说到的别担心)</em>,这样面试官的眼睛才会亮。</p> </blockquote> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-5"><span style="display: none;" class="prefix"></span><span class="content">Redis 小总结</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">与传统数据库不同的是 <strong style="font-weight: bold; color: #BF360C;">Redis</strong> 的数据是 <strong style="font-weight: bold; color: #BF360C;">存在内存</strong> 中的,所以 <strong style="font-weight: bold; color: #BF360C;">读写速度</strong> 非常 <strong style="font-weight: bold; color: #BF360C;">快</strong>,因此 Redis 被广泛应用于 <strong style="font-weight: bold; color: #BF360C;">缓存</strong> 方向,每秒可以处理超过 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">10</code> 万次读写操作,是已知性能最快的 Key-Value 数据库。另外,Redis 也经常用来做 <strong style="font-weight: bold; color: #BF360C;">分布式锁</strong>。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">除此之外,Redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。</p> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-6"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">Redis 优缺点</span><span class="suffix"></span></h2> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-7"><span style="display: none;" class="prefix"></span><span class="content">优点</span><span style="display: none;" class="suffix"></span></h4> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">读写性能优异</strong>, Redis能读的速度是 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">110000</code> 次/s,写的速度是 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">81000</code> 次/s。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">支持数据持久化</strong>,支持 AOF 和 RDB 两种持久化方式。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">支持事务</strong>,Redis 的所有操作都是原子性的,同时 Redis 还支持对几个操作合并后的原子性执行。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">数据结构丰富</strong>,除了支持 string 类型的 value 外还支持 hash、set、zset、list 等数据结构。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">支持主从复制</strong>,主机会自动将数据同步到从机,可以进行读写分离。</section></li></ul> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-8"><span style="display: none;" class="prefix"></span><span class="content">缺点</span><span style="display: none;" class="suffix"></span></h4> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">数据库 <strong style="font-weight: bold; color: #BF360C;">容量受到物理内存的限制</strong>,不能用作海量数据的高性能读写,因此 Redis 适合的场景主要局限在较小数据量的高性能操作和运算上。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Redis <strong style="font-weight: bold; color: #BF360C;">不具备自动容错和恢复功能</strong>,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的 IP 才能恢复。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">主机宕机,宕机前有部分数据未能及时同步到从机,切换 IP 后还会引入数据不一致的问题,降低了 <strong style="font-weight: bold; color: #BF360C;">系统的可用性</strong>。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">Redis 较难支持在线扩容</strong>,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费。</section></li></ul> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-9"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">为什么要用缓存?为什么使用 Redis?</span><span class="suffix"></span></h2> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-10"><span style="display: none;" class="prefix"></span><span class="content">提一下现在 Web 应用的现状</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">在日常的 Web 应用对数据库的访问中,<strong style="font-weight: bold; color: #BF360C;">读操作的次数远超写操作</strong>,比例大概在 <strong style="font-weight: bold; color: #BF360C;">1:9</strong> 到 <strong style="font-weight: bold; color: #BF360C;">3:7</strong>,所以需要读的可能性是比写的可能大得多的。当我们使用 SQL 语句去数据库进行读写操作时,数据库就会 <strong style="font-weight: bold; color: #BF360C;">去磁盘把对应的数据索引取回来</strong>,这是一个相对较慢的过程。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-11"><span style="display: none;" class="prefix"></span><span class="content">使用 Redis or 使用缓存带来的优势</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">如果我们把数据放在 Redis 中,也就是直接放在内存之中,让服务端直接去读取内存中的数据,那么这样 <strong style="font-weight: bold; color: #BF360C;">速度</strong> 明显就会快上不少 <em style="font-style: italic; color: #009688;">(高性能)</em>,并且会 <strong style="font-weight: bold; color: #BF360C;">极大减小数据库的压力</strong> <em style="font-style: italic; color: #009688;">(特别是在高并发情况下)</em>。</p> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;">记得是 <strong style="font-weight: bold; color: #BF360C;">两个角度</strong> 啊.. <strong style="font-weight: bold; color: #BF360C;">高性能</strong> 和 <strong style="font-weight: bold; color: #BF360C;">高并发</strong>..</p> </blockquote> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-12"><span style="display: none;" class="prefix"></span><span class="content">也要提一下使用缓存的考虑</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">但是使用内存进行数据存储开销也是比较大的,<strong style="font-weight: bold; color: #BF360C;">限于成本</strong> 的原因,一般我们只是使用 Redis 存储一些 <strong style="font-weight: bold; color: #BF360C;">常用和主要的数据</strong>,比如用户登录的信息等。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">一般而言在使用 Redis 进行存储的时候,我们需要从以下几个方面来考虑:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">业务数据常用吗?命中率如何?</strong> 如果命中率很低,就没有必要写入缓存;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">该业务数据是读操作多,还是写操作多?</strong> 如果写操作多,频繁需要写入数据库,也没有必要使用缓存;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">业务数据大小如何?</strong> 如果要存储几百兆字节的文件,会给缓存带来很大的压力,这样也没有必要;</section></li></ul> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">在考虑了这些问题之后,如果觉得有必要使用缓存,那么就使用它!</p> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-13"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">使用缓存会出现什么问题?</span><span class="suffix"></span></h2> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">一般来说有如下几个问题,回答思路遵照 <strong style="font-weight: bold; color: #BF360C;">是什么</strong> → <strong style="font-weight: bold; color: #BF360C;">为什么</strong> → <strong style="font-weight: bold; color: #BF360C;">怎么解决</strong>:</p> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">缓存雪崩问题;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">缓存穿透问题;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">缓存和数据库双写一致性问题;</section></li></ol> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-14"><span style="display: none;" class="prefix"></span><span class="content">缓存雪崩问题</span><span style="display: none;" class="suffix"></span></h4> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117fe93ea2d5e?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="655" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;655&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">另外对于 <strong style="font-weight: bold; color: #BF360C;">"Redis 挂掉了,请求全部走数据库"</strong> 这样的情况,我们还可以有如下的思路:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">事发前</strong>:实现 Redis 的高可用(主从架构 + Sentinel 或者 Redis Cluster),尽量避免 Redis 挂掉这种情况发生。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">事发中</strong>:万一 Redis 真的挂了,我们可以设置本地缓存(ehcache) + 限流(hystrix),尽量避免我们的数据库被干掉(起码能保证我们的服务还是能正常工作的)</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">事发后</strong>:Redis 持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据。</section></li></ul> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-15"><span style="display: none;" class="prefix"></span><span class="content">缓存穿透问题</span><span style="display: none;" class="suffix"></span></h4> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117febf166a4f?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="655" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;655&quot;></svg>"></figure> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-16"><span style="display: none;" class="prefix"></span><span class="content">缓存与数据库双写一致问题</span><span style="display: none;" class="suffix"></span></h4> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117fec2ebfc6e?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="655" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;655&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">双写一致性上图还是稍微粗糙了些,你还需要知道两种方案 <em style="font-style: italic; color: #009688;">(先操作数据库和先操作缓存)</em> 分别都有什么优势和对应的问题,这里不作赘述,可以参考一下下方的文章,写得非常详细。</p> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <ul style="margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc; margin-top: -20px !important;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">面试前必须要知道的Redis面试题 | Java3y - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://mp.weixin.qq.com/s/3Fmv7h5p2QDtLxc9n1dp5A" target="_blank" rel="nofollow noopener noreferrer">mp.weixin.qq.com/s/3Fmv7h5p2…</a></section></li></ul> </blockquote> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-17"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">Redis 为什么早期版本选择单线程?</span><span class="suffix"></span></h2> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-18"><span style="display: none;" class="prefix"></span><span class="content">官方解释</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">因为 Redis 是基于内存的操作,<strong style="font-weight: bold; color: #BF360C;">CPU 不是 Redis 的瓶颈</strong>,Redis 的瓶颈最有可能是 <strong style="font-weight: bold; color: #BF360C;">机器内存的大小</strong> 或者 <strong style="font-weight: bold; color: #BF360C;">网络带宽</strong>。既然单线程容易实现,而且 CPU 不会成为瓶颈,那就顺理成章地采用单线程的方案了。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-19"><span style="display: none;" class="prefix"></span><span class="content">简单总结一下</span><span style="display: none;" class="suffix"></span></h4> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">使用单线程模型能带来更好的 <strong style="font-weight: bold; color: #BF360C;">可维护性</strong>,方便开发和调试;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">使用单线程模型也能 <strong style="font-weight: bold; color: #BF360C;">并发</strong> 的处理客户端的请求;<em style="font-style: italic; color: #009688;">(I/O 多路复用机制)</em></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Redis 服务中运行的绝大多数操作的 <strong style="font-weight: bold; color: #BF360C;">性能瓶颈都不是 CPU</strong>;</section></li></ol> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;"><strong style="font-weight: bold; color: #BF360C;">强烈推荐</strong> 各位亲看一下这篇文章:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">为什么 Redis 选择单线程模型 · Why's THE Design? - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://draveness.me/whys-the-design-redis-single-thread" target="_blank" rel="nofollow noopener noreferrer">draveness.me/whys-the-de…</a></section></li></ul> </blockquote> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-20"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">Redis 为什么这么快?</span><span class="suffix"></span></h2> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">简单总结:</p> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">纯内存操作</strong>:读取不需要进行磁盘 I/O,所以比传统数据库要快上不少;<em style="font-style: italic; color: #009688;">(但不要有误区说磁盘就一定慢,例如 Kafka 就是使用磁盘顺序读取但仍然较快)</em></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">单线程,无锁竞争</strong>:这保证了没有线程的上下文切换,不会因为多线程的一些操作而降低性能;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">多路 I/O 复用模型,非阻塞 I/O</strong>:采用多路 I/O 复用技术可以让单个线程高效的处理多个网络连接请求(尽量减少网络 IO 的时间消耗);</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">高效的数据结构,加上底层做了大量优化</strong>:Redis 对于底层的数据结构和内存占用做了大量的优化,例如不同长度的字符串使用不同的结构体表示,HyperLogLog 的密集型存储结构等等..</section></li></ol> <h1 style="font-weight: bold; font-size: 1.6em; background-color: rgb(0, 150, 136); margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; color: rgb(255, 255, 255) !important; padding: 1px 8px !important;" data-tool="mdnice编辑器" data-id="heading-21"><span style="display: none;" class="prefix"></span><span class="content">二、数据结构篇</span><span class="suffix"></span></h1> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117fec6ddbb34?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="388" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;388&quot;></svg>"></figure> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-22"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">简述一下 Redis 常用数据结构及实现?</span><span class="suffix"></span></h2> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">首先在 Redis 内部会使用一个 <strong style="font-weight: bold; color: #BF360C;">RedisObject</strong> 对象来表示所有的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">key</code> 和 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">value</code>:</p> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117fecc28565b?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="446" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;446&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">其次 Redis 为了 <strong style="font-weight: bold; color: #BF360C;">平衡空间和时间效率</strong>,针对 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">value</code> 的具体类型在底层会采用不同的数据结构来实现,下图展示了他们之间的映射关系:<em style="font-style: italic; color: #009688;">(好像乱糟糟的,但至少能看清楚..)</em></p> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117fed19ccdfe?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="531" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;531&quot;></svg>"></figure> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-23"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">Redis 的 SDS 和 C 中字符串相比有什么优势?</span><span class="suffix"></span></h2> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-24"><span style="display: none;" class="prefix"></span><span class="content">先简单总结一下</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">C 语言使用了一个长度为 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">N+1</code> 的字符数组来表示长度为 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">N</code> 的字符串,并且字符数组最后一个元素总是 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">\0</code>,这种简单的字符串表示方式 <strong style="font-weight: bold; color: #BF360C;">不符合 Redis 对字符串在安全性、效率以及功能方面的要求</strong>。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-25"><span style="display: none;" class="prefix"></span><span class="content">再来说 C 语言字符串的问题</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">这样简单的数据结构可能会造成以下一些问题:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">获取字符串长度为 O(N) 级别的操作</strong> → 因为 C 不保存数组的长度,每次都需要遍历一遍整个数组;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">不能很好的杜绝 <strong style="font-weight: bold; color: #BF360C;">缓冲区溢出/内存泄漏</strong> 的问题 → 跟上述问题原因一样,如果执行拼接 or 缩短字符串的操作,如果操作不当就很容易造成上述问题;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">C 字符串 <strong style="font-weight: bold; color: #BF360C;">只能保存文本数据</strong> → 因为 C 语言中的字符串必须符合某种编码(比如 ASCII),例如中间出现的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">'\0'</code> 可能会被判定为提前结束的字符串而识别不了;</section></li></ul> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-26"><span style="display: none;" class="prefix"></span><span class="content">Redis 如何解决的 | SDS 的优势</span><span style="display: none;" class="suffix"></span></h4> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117fed1c791b5?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="372" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;372&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">如果去看 Redis 的源码 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">sds.h/sdshdr</code> 文件,你会看到 SDS 完整的实现细节,这里简单来说一下 Redis 如何解决的:</p> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">多增加 len 表示当前字符串的长度</strong>:这样就可以直接获取长度了,复杂度 O(1);</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">自动扩展空间</strong>:当 SDS 需要对字符串进行修改时,首先借助于 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">len</code> 和 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">alloc</code> 检查空间是否满足修改所需的要求,如果空间不够的话,SDS 会自动扩展空间,避免了像 C 字符串操作中的覆盖情况;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">有效降低内存分配次数</strong>:C 字符串在涉及增加或者清除操作时会改变底层数组的大小造成重新分配,SDS 使用了 <strong style="font-weight: bold; color: #BF360C;">空间预分配</strong> 和 <strong style="font-weight: bold; color: #BF360C;">惰性空间释放</strong> 机制,简单理解就是每次在扩展时是成倍的多分配的,在缩容是也是先留着并不正式归还给 OS;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">二进制安全</strong>:C 语言字符串只能保存 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">ascii</code> 码,对于图片、音频等信息无法保存,SDS 是二进制安全的,写入什么读取就是什么,不做任何过滤和限制;</section></li></ol> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-27"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">字典是如何实现的?Rehash 了解吗?</span><span class="suffix"></span></h2> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-28"><span style="display: none;" class="prefix"></span><span class="content">先总体聊一下 Redis 中的字典</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">字典是 Redis 服务器中出现最为频繁的复合型数据结构。除了 <strong style="font-weight: bold; color: #BF360C;">hash</strong> 结构的数据会用到字典外,整个 Redis 数据库的所有 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">key</code> 和 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">value</code> 也组成了一个 <strong style="font-weight: bold; color: #BF360C;">全局字典</strong>,还有带过期时间的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">key</code> 也是一个字典。<em style="font-style: italic; color: #009688;">(存储在 RedisDb 数据结构中)</em></p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-29"><span style="display: none;" class="prefix"></span><span class="content">说明字典内部结构和 rehash</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><strong style="font-weight: bold; color: #BF360C;">Redis</strong> 中的字典相当于 Java 中的 <strong style="font-weight: bold; color: #BF360C;">HashMap</strong>,内部实现也差不多类似,都是通过 <strong style="font-weight: bold; color: #BF360C;">"数组 + 链表"</strong> 的 <strong style="font-weight: bold; color: #BF360C;">链地址法</strong> 来解决部分 哈希冲突,同时这样的结构也吸收了两种不同数据结构的优点。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">字典结构内部包含 <strong style="font-weight: bold; color: #BF360C;">两个 hashtable</strong>,通常情况下只有一个 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">hashtable</code> 有值,但是在字典扩容缩容时,需要分配新的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">hashtable</code>,然后进行 <strong style="font-weight: bold; color: #BF360C;">渐进式搬迁</strong> <em style="font-style: italic; color: #009688;">(rehash)</em>,这时候两个 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">hashtable</code> 分别存储旧的和新的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">hashtable</code>,待搬迁结束后,旧的将被删除,新的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">hashtable</code> 取而代之。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-30"><span style="display: none;" class="prefix"></span><span class="content">扩缩容的条件</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">正常情况下,当 hash 表中 <strong style="font-weight: bold; color: #BF360C;">元素的个数等于第一维数组的长度时</strong>,就会开始扩容,扩容的新数组是 <strong style="font-weight: bold; color: #BF360C;">原数组大小的 2 倍</strong>。不过如果 Redis 正在做 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">bgsave(持久化命令)</code>,为了减少内存也得过多分离,Redis 尽量不去扩容,但是如果 hash 表非常满了,<strong style="font-weight: bold; color: #BF360C;">达到了第一维数组长度的 5 倍了</strong>,这个时候就会 <strong style="font-weight: bold; color: #BF360C;">强制扩容</strong>。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">当 hash 表因为元素逐渐被删除变得越来越稀疏时,Redis 会对 hash 表进行缩容来减少 hash 表的第一维数组空间占用。所用的条件是 <strong style="font-weight: bold; color: #BF360C;">元素个数低于数组长度的 10%</strong>,缩容不会考虑 Redis 是否在做 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">bgsave</code>。</p> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-31"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">跳跃表是如何实现的?原理?</span><span class="suffix"></span></h2> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117fef3ce9ec6?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="599" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;599&quot;></svg>"></figure> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;">这是 Redis 中比较重要的一个数据结构,<strong style="font-weight: bold; color: #BF360C;">建议阅读</strong> 之前写过的文章,里面详细介绍了原理和一些细节:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Redis(2)——跳跃表 - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://www.wmyskxz.com/2020/02/29/redis-2-tiao-yue-biao/" target="_blank" rel="nofollow noopener noreferrer">www.wmyskxz.com/2020/02/29/…</a></section></li></ul> </blockquote> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-32"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">HyperLogLog 有了解吗?</span><span class="suffix"></span></h2> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;"><strong style="font-weight: bold; color: #BF360C;">建议阅读</strong> 之前的系列文章:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Redis(4)——神奇的HyperLoglog解决统计问题 - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://www.wmyskxz.com/2020/03/02/reids-4-shen-qi-de-hyperloglog-jie-jue-tong-ji-wen-ti/" target="_blank" rel="nofollow noopener noreferrer">www.wmyskxz.com/2020/03/02/…</a></section></li></ul> </blockquote> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-33"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">布隆过滤器有了解吗?</span><span class="suffix"></span></h2> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;"><strong style="font-weight: bold; color: #BF360C;">建议阅读</strong> 之前的系列文章:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Redis(5)——亿级数据过滤和布隆过滤器 - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://www.wmyskxz.com/2020/03/11/redis-5-yi-ji-shu-ju-guo-lu-he-bu-long-guo-lu-qi/" target="_blank" rel="nofollow noopener noreferrer">www.wmyskxz.com/2020/03/11/…</a></section></li></ul> </blockquote> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-34"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">GeoHash 了解吗?</span><span class="suffix"></span></h2> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;"><strong style="font-weight: bold; color: #BF360C;">建议阅读</strong> 之前的系列文章:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Redis(6)——GeoHash查找附近的人 - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://www.wmyskxz.com/2020/03/12/redis-6-geohash-cha-zhao-fu-jin-de-ren/" target="_blank" rel="nofollow noopener noreferrer">www.wmyskxz.com/2020/03/12/…</a></section></li></ul> </blockquote> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-35"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">压缩列表了解吗?</span><span class="suffix"></span></h2> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">这是 Redis <strong style="font-weight: bold; color: #BF360C;">为了节约内存</strong> 而使用的一种数据结构,<strong style="font-weight: bold; color: #BF360C;">zset</strong> 和 <strong style="font-weight: bold; color: #BF360C;">hash</strong> 容器对象会在元素个数较少的时候,采用压缩列表(ziplist)进行存储。压缩列表是 <strong style="font-weight: bold; color: #BF360C;">一块连续的内存空间</strong>,元素之间紧挨着存储,没有任何冗余空隙。</p> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;">因为之前自己也没有学习过,所以找了一篇比较好比较容易理解的文章:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">图解Redis之数据结构篇——压缩列表 - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://mp.weixin.qq.com/s/nba0FUEAVRs0vi24KUoyQg" target="_blank" rel="nofollow noopener noreferrer">mp.weixin.qq.com/s/nba0FUEAV…</a></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">这一篇稍微底层稍微硬核一点:<a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="http://www.web-lovers.com/redis-source-ziplist.html" target="_blank" rel="nofollow noopener noreferrer">www.web-lovers.com/redis-sourc…</a></section></li></ul> </blockquote> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-36"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">快速列表 quicklist 了解吗?</span><span class="suffix"></span></h2> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">Redis 早期版本存储 list 列表数据结构使用的是压缩列表 ziplist 和普通的双向链表 linkedlist,也就是说当元素少时使用 ziplist,当元素多时用 linkedlist。但考虑到链表的附加空间相对较高,<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">prev</code> 和 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">next</code> 指针就要占去 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">16</code> 个字节(64 位操作系统占用 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">8</code> 个字节),另外每个节点的内存都是单独分配,会家具内存的碎片化,影响内存管理效率。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">后来 Redis 新版本(3.2)对列表数据结构进行了改造,使用 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">quicklist</code> 代替了 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">ziplist</code> 和 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">linkedlist</code>。</p> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;">同上..建议阅读一下以下的文章:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Redis列表list 底层原理 - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://zhuanlan.zhihu.com/p/102422311" target="_blank" rel="nofollow noopener noreferrer">zhuanlan.zhihu.com/p/102422311</a></section></li></ul> </blockquote> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-37"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">Stream 结构有了解吗?</span><span class="suffix"></span></h2> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><strong style="font-weight: bold; color: #BF360C;">Redis Stream</strong> 从概念上来说,就像是一个 <strong style="font-weight: bold; color: #BF360C;">仅追加内容</strong> 的 <strong style="font-weight: bold; color: #BF360C;">消息链表</strong>,把所有加入的消息都一个一个串起来,每个消息都有一个唯一的 ID 和内容,这很简单,让它复杂的是从 Kafka 借鉴的另一种概念:<strong style="font-weight: bold; color: #BF360C;">消费者组(Consumer Group)</strong> <em style="font-style: italic; color: #009688;">(思路一致,实现不同)</em>:</p> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117fef43ceea6?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="577" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;577&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">上图就展示了一个典型的 <strong style="font-weight: bold; color: #BF360C;">Stream</strong> 结构。每个 Stream 都有唯一的名称,它就是 Redis 的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">key</code>,在我们首次使用 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">xadd</code> 指令追加消息时自动创建。我们对图中的一些概念做一下解释:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">Consumer Group</strong>:消费者组,可以简单看成记录流状态的一种数据结构。消费者既可以选择使用 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">XREAD</code> 命令进行 <strong style="font-weight: bold; color: #BF360C;">独立消费</strong>,也可以多个消费者同时加入一个消费者组进行 <strong style="font-weight: bold; color: #BF360C;">组内消费</strong>。同一个消费者组内的消费者共享所有的 Stream 信息,<strong style="font-weight: bold; color: #BF360C;">同一条消息只会有一个消费者消费到</strong>,这样就可以应用在分布式的应用场景中来保证消息的唯一性。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">last_delivered_id</strong>:用来表示消费者组消费在 Stream 上 <strong style="font-weight: bold; color: #BF360C;">消费位置</strong> 的游标信息。每个消费者组都有一个 Stream 内 <strong style="font-weight: bold; color: #BF360C;">唯一的名称</strong>,消费者组不会自动创建,需要使用 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">XGROUP CREATE</code> 指令来显式创建,并且需要指定从哪一个消息 ID 开始消费,用来初始化 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">last_delivered_id</code> 这个变量。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">pending_ids</strong>:每个消费者内部都有的一个状态变量,用来表示 <strong style="font-weight: bold; color: #BF360C;">已经</strong> 被客户端 <strong style="font-weight: bold; color: #BF360C;">获取</strong>,但是 <strong style="font-weight: bold; color: #BF360C;">还没有 ack</strong> 的消息。记录的目的是为了 <strong style="font-weight: bold; color: #BF360C;">保证客户端至少消费了消息一次</strong>,而不会在网络传输的中途丢失而没有对消息进行处理。如果客户端没有 ack,那么这个变量里面的消息 ID 就会越来越多,一旦某个消息被 ack,它就会对应开始减少。这个变量也被 Redis 官方称为 <strong style="font-weight: bold; color: #BF360C;">PEL</strong> <em style="font-style: italic; color: #009688;">(Pending Entries List)</em>。</section></li></ul> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-38"><span style="display: none;" class="prefix"></span><span class="content">Stream 消息太多怎么办?</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">很容易想到,要是消息积累太多,Stream 的链表岂不是很长,内容会不会爆掉就是个问题了。<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">xdel</code> 指令又不会删除消息,它只是给消息做了个标志位。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">Redis 自然考虑到了这一点,所以它提供了一个定长 Stream 功能。在 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">xadd</code> 的指令提供一个定长长度 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">maxlen</code>,就可以将老的消息干掉,确保最多不超过指定长度,使用起来也很简单:</p> <pre style="margin-top: 10px; margin-bottom: 10px; border-radius: 5px; padding: 0.5em; font-size: 1em; background-color: #2b2b2b!important;" data-tool="mdnice编辑器" class="custom"><code style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; border-style: none; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;" class="hljs copyable">&gt; XADD mystream MAXLEN 2 * value 1<br>1526654998691-0<br>&gt; XADD mystream MAXLEN 2 * value 2<br>1526654999635-0<br>&gt; XADD mystream MAXLEN 2 * value 3<br>1526655000369-0<br>&gt; XLEN mystream<br>(<span style="color: #e6c07b; line-height: 26px;" class="hljs-built_in">integer</span>) 2<br>&gt; XRANGE mystream - +<br>1) 1) 1526654999635-0<br> 2) 1) <span style="color: #98c379; line-height: 26px;" class="hljs-string">"value"</span><br> 2) <span style="color: #98c379; line-height: 26px;" class="hljs-string">"2"</span><br>2) 1) 1526655000369-0<br> 2) 1) <span style="color: #98c379; line-height: 26px;" class="hljs-string">"value"</span><br> 2) <span style="color: #98c379; line-height: 26px;" class="hljs-string">"3"</span><br><span class="copy-code-btn">复制代码</span></code></pre> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">如果使用 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">MAXLEN</code> 选项,当 Stream 的达到指定长度后,老的消息会自动被淘汰掉,因此 Stream 的大小是恒定的。目前还没有选项让 Stream 只保留给定数量的条目,因为为了一致地运行,这样的命令必须在很长一段时间内阻塞以淘汰消息。<em style="font-style: italic; color: #009688;">(例如在添加数据的高峰期间,你不得不长暂停来淘汰旧消息和添加新的消息)</em></p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">另外使用 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">MAXLEN</code> 选项的花销是很大的,Stream 为了节省内存空间,采用了一种特殊的结构表示,而这种结构的调整是需要额外的花销的。所以我们可以使用一种带有 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">~</code> 的特殊命令:</p> <pre style="margin-top: 10px; margin-bottom: 10px; border-radius: 5px; padding: 0.5em; font-size: 1em; background-color: #2b2b2b!important;" data-tool="mdnice编辑器" class="custom"><code style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; border-style: none; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;" class="hljs copyable">XADD mystream MAXLEN ~ 1000 * ... entry fields here ...<br><span class="copy-code-btn">复制代码</span></code></pre> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">它会基于当前的结构合理地对节点执行裁剪,来保证至少会有 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">1000</code> 条数据,可能是 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">1010</code> 也可能是 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">1030</code>。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-39"><span style="display: none;" class="prefix"></span><span class="content">PEL 是如何避免消息丢失的?</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">在客户端消费者读取 Stream 消息时,Redis 服务器将消息回复给客户端的过程中,客户端突然断开了连接,消息就丢失了。但是 PEL 里已经保存了发出去的消息 ID,待客户端重新连上之后,可以再次收到 PEL 中的消息 ID 列表。不过此时 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">xreadgroup</code> 的起始消息 ID 不能为参数 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">&gt;</code> ,而必须是任意有效的消息 ID,一般将参数设为 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">0-0</code>,表示读取所有的 PEL 消息以及自 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">last_delivered_id</code> 之后的新消息。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-40"><span style="display: none;" class="prefix"></span><span class="content">和 Kafka 对比起来呢?</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">Redis 基于内存存储,这意味着它会比基于磁盘的 Kafka 快上一些,也意味着使用 Redis 我们 <strong style="font-weight: bold; color: #BF360C;">不能长时间存储大量数据</strong>。不过如果您想以 <strong style="font-weight: bold; color: #BF360C;">最小延迟</strong> 实时处理消息的话,您可以考虑 Redis,但是如果 <strong style="font-weight: bold; color: #BF360C;">消息很大并且应该重用数据</strong> 的话,则应该首先考虑使用 Kafka。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">另外从某些角度来说,<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">Redis Stream</code> 也更适用于小型、廉价的应用程序,因为 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">Kafka</code> 相对来说更难配置一些。</p> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;"><strong style="font-weight: bold; color: #BF360C;">推荐阅读</strong> 之前的系列文章,里面 <strong style="font-weight: bold; color: #BF360C;">也对 Pub/ Sub 做了详细的描述</strong>:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Redis(8)——发布/订阅与Stream - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://www.wmyskxz.com/2020/03/15/redis-8-fa-bu-ding-yue-yu-stream/" target="_blank" rel="nofollow noopener noreferrer">www.wmyskxz.com/2020/03/15/…</a></section></li></ul> </blockquote> <h1 style="font-weight: bold; font-size: 1.6em; background-color: rgb(0, 150, 136); margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; color: rgb(255, 255, 255) !important; padding: 1px 8px !important;" data-tool="mdnice编辑器" data-id="heading-41"><span style="display: none;" class="prefix"></span><span class="content">三、持久化篇</span><span class="suffix"></span></h1> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff061a6034?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="388" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;388&quot;></svg>"></figure> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-42"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">什么是持久化?</span><span class="suffix"></span></h2> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-43"><span style="display: none;" class="prefix"></span><span class="content">先简单谈一谈是什么</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><strong style="font-weight: bold; color: #BF360C;">Redis</strong> 的数据 <strong style="font-weight: bold; color: #BF360C;">全部存储</strong> 在 <strong style="font-weight: bold; color: #BF360C;">内存</strong> 中,如果 <strong style="font-weight: bold; color: #BF360C;">突然宕机</strong>,数据就会全部丢失,因此必须有一套机制来保证 Redis 的数据不会因为故障而丢失,这种机制就是 Redis 的 <strong style="font-weight: bold; color: #BF360C;">持久化机制</strong>,它会将内存中的数据库状态 <strong style="font-weight: bold; color: #BF360C;">保存到磁盘</strong> 中。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-44"><span style="display: none;" class="prefix"></span><span class="content">解释一下持久化发生了什么</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">我们来稍微考虑一下 <strong style="font-weight: bold; color: #BF360C;">Redis</strong> 作为一个 <strong style="font-weight: bold; color: #BF360C;">"内存数据库"</strong> 要做的关于持久化的事情。通常来说,从客户端发起请求开始,到服务器真实地写入磁盘,需要发生如下几件事情:</p> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff0976311b?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="585" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;585&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><strong style="font-weight: bold; color: #BF360C;">详细版</strong> 的文字描述大概就是下面这样:</p> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">客户端向数据库 <strong style="font-weight: bold; color: #BF360C;">发送写命令</strong> <em style="font-style: italic; color: #009688;">(数据在客户端的内存中)</em></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">数据库 <strong style="font-weight: bold; color: #BF360C;">接收</strong> 到客户端的 <strong style="font-weight: bold; color: #BF360C;">写请求</strong> <em style="font-style: italic; color: #009688;">(数据在服务器的内存中)</em></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">数据库 <strong style="font-weight: bold; color: #BF360C;">调用系统 API</strong> 将数据写入磁盘 <em style="font-style: italic; color: #009688;">(数据在内核缓冲区中)</em></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">操作系统将 <strong style="font-weight: bold; color: #BF360C;">写缓冲区</strong> 传输到 <strong style="font-weight: bold; color: #BF360C;">磁盘控控制器</strong> <em style="font-style: italic; color: #009688;">(数据在磁盘缓存中)</em></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">操作系统的磁盘控制器将数据 <strong style="font-weight: bold; color: #BF360C;">写入实际的物理媒介</strong> 中 <em style="font-style: italic; color: #009688;">(数据在磁盘中)</em></section></li></ol> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-45"><span style="display: none;" class="prefix"></span><span class="content">分析如何保证持久化安全</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">如果我们故障仅仅涉及到 <strong style="font-weight: bold; color: #BF360C;">软件层面</strong> <em style="font-style: italic; color: #009688;">(该进程被管理员终止或程序崩溃)</em> 并且没有接触到内核,那么在 <em style="font-style: italic; color: #009688;">上述步骤 3</em> 成功返回之后,我们就认为成功了。即使进程崩溃,操作系统仍然会帮助我们把数据正确地写入磁盘。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">如果我们考虑 <strong style="font-weight: bold; color: #BF360C;">停电/ 火灾</strong> 等 <strong style="font-weight: bold; color: #BF360C;">更具灾难性</strong> 的事情,那么只有在完成了第 <strong style="font-weight: bold; color: #BF360C;">5</strong> 步之后,才是安全的。</p> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="机房”火了“" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff25b7b945?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="450" data-height="300" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;450&quot; height=&quot;300&quot;></svg>"><figcaption style="margin-top: 5px; text-align: center; color: #888; font-size: 14px;">机房”火了“</figcaption></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">所以我们可以总结得出数据安全最重要的阶段是:<strong style="font-weight: bold; color: #BF360C;">步骤三、四、五</strong>,即:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">数据库软件调用写操作将用户空间的缓冲区转移到内核缓冲区的频率是多少?</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">内核多久从缓冲区取数据刷新到磁盘控制器?</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">磁盘控制器多久把数据写入物理媒介一次?</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">注意:</strong> 如果真的发生灾难性的事件,我们可以从上图的过程中看到,任何一步都可能被意外打断丢失,所以只能 <strong style="font-weight: bold; color: #BF360C;">尽可能地保证</strong> 数据的安全,这对于所有数据库来说都是一样的。</section></li></ul> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">我们从 <strong style="font-weight: bold; color: #BF360C;">第三步</strong> 开始。Linux 系统提供了清晰、易用的用于操作文件的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">POSIX file API</code>,<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">20</code> 多年过去,仍然还有很多人对于这一套 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">API</code> 的设计津津乐道,我想其中一个原因就是因为你光从 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">API</code> 的命名就能够很清晰地知道这一套 API 的用途:</p> <pre style="margin-top: 10px; margin-bottom: 10px; border-radius: 5px; padding: 0.5em; font-size: 1em; background-color: #2b2b2b!important;" data-tool="mdnice编辑器" class="custom"><code style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; border-style: none; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;" class="hljs copyable"><span style="line-height: 26px;" class="hljs-function"><span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">int</span> <span style="color: #61aeee; line-height: 26px;" class="hljs-title">open</span><span style="line-height: 26px;" class="hljs-params">(<span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">const</span> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">char</span> *path, <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">int</span> oflag, ...<span style="color: #5c6370; font-style: italic; line-height: 26px;" class="hljs-comment">/*,mode_t mode */</span>)</span></span>;<br><span style="line-height: 26px;" class="hljs-function"><span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">int</span> <span style="color: #61aeee; line-height: 26px;" class="hljs-title">close</span> <span style="line-height: 26px;" class="hljs-params">(<span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">int</span> filedes)</span></span>;<span style="line-height: 26px;" class="hljs-function"><span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">int</span> <span style="color: #61aeee; line-height: 26px;" class="hljs-title">remove</span><span style="line-height: 26px;" class="hljs-params">( <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">const</span> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">char</span> *fname )</span></span>;<br><span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">ssize_t</span> write(<span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">int</span> fildes, <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">const</span> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">void</span> *buf, <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">size_t</span> nbyte);<br><span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">ssize_t</span> read(<span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">int</span> fildes, <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">void</span> *buf, <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">size_t</span> nbyte);<br><span class="copy-code-btn">复制代码</span></code></pre> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">参考自:API 设计最佳实践的思考 - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://www.cnblogs.com/yuanjiangw/p/10846560.html" target="_blank" rel="nofollow noopener noreferrer">www.cnblogs.com/yuanjiangw/…</a></section></li></ul> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">所以,我们有很好的可用的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">API</code> 来完成 <strong style="font-weight: bold; color: #BF360C;">第三步</strong>,但是对于成功返回之前,我们对系统调用花费的时间没有太多的控制权。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">然后我们来说说 <strong style="font-weight: bold; color: #BF360C;">第四步</strong>。我们知道,除了早期对电脑特别了解那帮人 <em style="font-style: italic; color: #009688;">(操作系统就这帮人搞的)</em>,实际的物理硬件都不是我们能够 <strong style="font-weight: bold; color: #BF360C;">直接操作</strong> 的,都是通过 <strong style="font-weight: bold; color: #BF360C;">操作系统调用</strong> 来达到目的的。为了防止过慢的 I/O 操作拖慢整个系统的运行,操作系统层面做了很多的努力,譬如说 <strong style="font-weight: bold; color: #BF360C;">上述第四步</strong> 提到的 <strong style="font-weight: bold; color: #BF360C;">写缓冲区</strong>,并不是所有的写操作都会被立即写入磁盘,而是要先经过一个缓冲区,默认情况下,Linux 将在 <strong style="font-weight: bold; color: #BF360C;">30 秒</strong> 后实际提交写入。</p> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff2cbb4b01?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="440" data-height="330" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;440&quot; height=&quot;330&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">但是很明显,<strong style="font-weight: bold; color: #BF360C;">30 秒</strong> 并不是 Redis 能够承受的,这意味着,如果发生故障,那么最近 30 秒内写入的所有数据都可能会丢失。幸好 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">PROSIX API</code> 提供了另一个解决方案:<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">fsync</code>,该命令会 <strong style="font-weight: bold; color: #BF360C;">强制</strong> 内核将 <strong style="font-weight: bold; color: #BF360C;">缓冲区</strong> 写入 <strong style="font-weight: bold; color: #BF360C;">磁盘</strong>,但这是一个非常消耗性能的操作,每次调用都会 <strong style="font-weight: bold; color: #BF360C;">阻塞等待</strong> 直到设备报告 IO 完成,所以一般在生产环境的服务器中,<strong style="font-weight: bold; color: #BF360C;">Redis</strong> 通常是每隔 1s 左右执行一次 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">fsync</code> 操作。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">到目前为止,我们了解到了如何控制 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">第三步</code> 和 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">第四步</code>,但是对于 <strong style="font-weight: bold; color: #BF360C;">第五步</strong>,我们 <strong style="font-weight: bold; color: #BF360C;">完全无法控制</strong>。也许一些内核实现将试图告诉驱动实际提交物理介质上的数据,或者控制器可能会为了提高速度而重新排序写操作,不会尽快将数据真正写到磁盘上,而是会等待几个多毫秒。这完全是我们无法控制的。</p> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;">普通人简单说一下第一条就过了,如果你详细地对后面两方面 <strong style="font-weight: bold; color: #BF360C;">侃侃而谈</strong>,那面试官就会对你另眼相看了。</p> </blockquote> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-46"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">Redis 中的两种持久化方式?</span><span class="suffix"></span></h2> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-47"><span style="display: none;" class="prefix"></span><span class="content">方式一:快照</span><span style="display: none;" class="suffix"></span></h4> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff32857d68?imageslim" data-width="286" data-height="286" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;286&quot; height=&quot;286&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><strong style="font-weight: bold; color: #BF360C;">Redis 快照</strong> 是最简单的 Redis 持久性模式。当满足特定条件时,它将生成数据集的时间点快照,例如,如果先前的快照是在 2 分钟前创建的,并且现在已经至少有 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">100</code> 次新写入,则将创建一个新的快照。此条件可以由用户配置 Redis 实例来控制,也可以在运行时修改而无需重新启动服务器。快照作为包含整个数据集的单个 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">.rdb</code> 文件生成。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-48"><span style="display: none;" class="prefix"></span><span class="content">方式二:AOF</span><span style="display: none;" class="suffix"></span></h4> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff39256e5e?imageslim" data-width="300" data-height="300" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;300&quot; height=&quot;300&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><strong style="font-weight: bold; color: #BF360C;">快照不是很持久</strong>。如果运行 Redis 的计算机停止运行,电源线出现故障或者您 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">kill -9</code> 的实例意外发生,则写入 Redis 的最新数据将丢失。尽管这对于某些应用程序可能不是什么大问题,但有些使用案例具有充分的耐用性,在这些情况下,快照并不是可行的选择。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><strong style="font-weight: bold; color: #BF360C;">AOF(Append Only File - 仅追加文件)</strong> 它的工作方式非常简单:每次执行 <strong style="font-weight: bold; color: #BF360C;">修改内存</strong> 中数据集的写操作时,都会 <strong style="font-weight: bold; color: #BF360C;">记录</strong> 该操作。假设 AOF 日志记录了自 Redis 实例创建以来 <strong style="font-weight: bold; color: #BF360C;">所有的修改性指令序列</strong>,那么就可以通过对一个空的 Redis 实例 <strong style="font-weight: bold; color: #BF360C;">顺序执行所有的指令</strong>,也就是 <strong style="font-weight: bold; color: #BF360C;">「重放」</strong>,来恢复 Redis 当前实例的内存数据结构的状态。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-49"><span style="display: none;" class="prefix"></span><span class="content">Redis 4.0 的混合持久化</span><span style="display: none;" class="suffix"></span></h4> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff40a9d286?imageslim" data-width="103" data-height="115" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;103&quot; height=&quot;115&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">重启 Redis 时,我们很少使用 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">rdb</code> 来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">rdb</code> 来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><strong style="font-weight: bold; color: #BF360C;">Redis 4.0</strong> 为了解决这个问题,带来了一个新的持久化选项——<strong style="font-weight: bold; color: #BF360C;">混合持久化</strong>。将 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">rdb</code> 文件的内容和增量的 AOF 日志文件存在一起。这里的 AOF 日志不再是全量的日志,而是 <strong style="font-weight: bold; color: #BF360C;">自持久化开始到持久化结束</strong> 的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小:</p> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff55981827?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="443" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;443&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">于是在 Redis 重启的时候,可以先加载 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">rdb</code> 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,重启效率因此大幅得到提升。</p> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;">关于两种持久化方式的更多细节 <em style="font-style: italic; color: #009688;">(原理)</em> 可以参考:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Redis(7)——持久化【一文了解】 - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://www.wmyskxz.com/2020/03/13/redis-7-chi-jiu-hua-yi-wen-liao-jie/" target="_blank" rel="nofollow noopener noreferrer">www.wmyskxz.com/2020/03/13/…</a></section></li></ul> </blockquote> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-50"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">RDB 和 AOF 各自有什么优缺点?</span><span class="suffix"></span></h2> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-51"><span style="display: none;" class="prefix"></span><span class="content">RDB | 优点</span><span style="display: none;" class="suffix"></span></h4> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">只有一个文件 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">dump.rdb</code>,<strong style="font-weight: bold; color: #BF360C;">方便持久化</strong>。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">容灾性好</strong>,一个文件可以保存到安全的磁盘。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">性能最大化</strong>,<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">fork</code> 子进程来完成写操作,让主进程继续处理命令,所以使 IO 最大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 Redis 的高性能</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">相对于数据集大时,比 AOF 的 <strong style="font-weight: bold; color: #BF360C;">启动效率</strong> 更高。</section></li></ol> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-52"><span style="display: none;" class="prefix"></span><span class="content">RDB | 缺点</span><span style="display: none;" class="suffix"></span></h4> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">数据安全性低</strong>。RDB 是间隔一段时间进行持久化,如果持久化之间 Redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候;</section></li></ol> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-53"><span style="display: none;" class="prefix"></span><span class="content">AOF | 优点</span><span style="display: none;" class="suffix"></span></h4> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">数据安全</strong>,aof 持久化可以配置 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">appendfsync</code> 属性,有 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">always</code>,每进行一次命令操作就记录到 aof 文件中一次。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据一致性问题。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令 进行合并重写),可以删除其中的某些命令(比如误操作的 flushall)</section></li></ol> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-54"><span style="display: none;" class="prefix"></span><span class="content">AOF | 缺点</span><span style="display: none;" class="suffix"></span></h4> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">AOF 文件比 RDB <strong style="font-weight: bold; color: #BF360C;">文件大</strong>,且 <strong style="font-weight: bold; color: #BF360C;">恢复速度慢</strong>。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">数据集大</strong> 的时候,比 rdb <strong style="font-weight: bold; color: #BF360C;">启动效率低</strong>。</section></li></ol> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-55"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">两种方式如何选择?</span><span class="suffix"></span></h2> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">一般来说, 如果想达到足以媲美 PostgreSQL 的 <strong style="font-weight: bold; color: #BF360C;">数据安全性</strong>,你应该 <strong style="font-weight: bold; color: #BF360C;">同时使用两种持久化功能</strong>。在这种情况下,当 Redis 重启的时候会优先载入 AOF 文件来恢复原始的数据,因为在通常情况下 AOF 文件保存的数据集要比 RDB 文件保存的数据集要完整。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">如果你非常关心你的数据, 但仍然 <strong style="font-weight: bold; color: #BF360C;">可以承受数分钟以内的数据丢失</strong>,那么你可以 <strong style="font-weight: bold; color: #BF360C;">只使用 RDB 持久化</strong>。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">有很多用户都只使用 AOF 持久化,但并不推荐这种方式,因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快,除此之外,使用 RDB 还可以避免 AOF 程序的 bug。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式。</section></li></ul> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-56"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">Redis 的数据恢复</span><span class="suffix"></span></h2> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><strong style="font-weight: bold; color: #BF360C;">Redis</strong> 的数据恢复有着如下的优先级:</p> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">如果只配置 AOF ,重启时加载 AOF 文件恢复数据;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">如果同时配置了 RDB 和 AOF ,启动只加载 AOF 文件恢复数据;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">如果只配置 RDB,启动将加载 dump 文件恢复数据。</section></li></ol> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">拷贝 <strong style="font-weight: bold; color: #BF360C;">AOF</strong> 文件到 Redis 的数据目录,启动 redis-server AOF 的数据恢复过程:Redis 虚拟一个客户端,读取 AOF 文件恢复 Redis 命令和参数,然后执行命令从而恢复数据,这些过程主要在 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">loadAppendOnlyFile()</code> 中实现。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">拷贝 <strong style="font-weight: bold; color: #BF360C;">RDB</strong> 文件到 Redis 的数据目录,启动 redis-server 即可,因为 RDB 文件和重启前保存的是真实数据而不是命令状态和参数。</p> <h1 style="font-weight: bold; font-size: 1.6em; background-color: rgb(0, 150, 136); margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; color: rgb(255, 255, 255) !important; padding: 1px 8px !important;" data-tool="mdnice编辑器" data-id="heading-57"><span style="display: none;" class="prefix"></span><span class="content">四、集群篇</span><span class="suffix"></span></h1> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff55a55478?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="388" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;388&quot;></svg>"></figure> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-58"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">主从同步了解吗?</span><span class="suffix"></span></h2> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff5767a190?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="390" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;390&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><strong style="font-weight: bold; color: #BF360C;">主从复制</strong>,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。前者称为 <strong style="font-weight: bold; color: #BF360C;">主节点(master)</strong>,后者称为 <strong style="font-weight: bold; color: #BF360C;">从节点(slave)</strong>。且数据的复制是 <strong style="font-weight: bold; color: #BF360C;">单向</strong> 的,只能由主节点到从节点。Redis 主从复制支持 <strong style="font-weight: bold; color: #BF360C;">主从同步</strong> 和 <strong style="font-weight: bold; color: #BF360C;">从从同步</strong> 两种,后者是 Redis 后续版本新增的功能,以减轻主节点的同步负担。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-59"><span style="display: none;" class="prefix"></span><span class="content">主从复制主要的作用</span><span style="display: none;" class="suffix"></span></h4> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">数据冗余:</strong> 主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">故障恢复:</strong> 当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复 <em style="font-style: italic; color: #009688;">(实际上是一种服务的冗余)</em>。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">负载均衡:</strong> 在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务 <em style="font-style: italic; color: #009688;">(即写 Redis 数据时应用连接主节点,读 Redis 数据时应用连接从节点)</em>,分担服务器负载。尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">高可用基石:</strong> 除了上述作用以外,主从复制还是哨兵和集群能够实施的 <strong style="font-weight: bold; color: #BF360C;">基础</strong>,因此说主从复制是 Redis 高可用的基础。</section></li></ul> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-60"><span style="display: none;" class="prefix"></span><span class="content">实现原理</span><span style="display: none;" class="suffix"></span></h4> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff62164caf?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="620" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;620&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">为了节省篇幅,我把主要的步骤都 <strong style="font-weight: bold; color: #BF360C;">浓缩</strong> 在了上图中,其实也可以 <strong style="font-weight: bold; color: #BF360C;">简化成三个阶段:准备阶段-数据同步阶段-命令传播阶段</strong>。</p> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;">更多细节 <strong style="font-weight: bold; color: #BF360C;">推荐阅读</strong> 之前的系列文章,不仅有原理讲解,还有实战环节:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Redis(9)——史上最强【集群】入门实践教程 - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://www.wmyskxz.com/2020/03/17/redis-9-shi-shang-zui-qiang-ji-qun-ru-men-shi-jian-jiao-cheng/" target="_blank" rel="nofollow noopener noreferrer">www.wmyskxz.com/2020/03/17/…</a></section></li></ul> </blockquote> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-61"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">哨兵模式了解吗?</span><span class="suffix"></span></h2> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff67d7d8b7?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="531" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;531&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><em style="font-style: italic; color: #009688;">上图</em> 展示了一个典型的哨兵架构图,它由两部分组成,哨兵节点和数据节点:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">哨兵节点:</strong> 哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的 Redis 节点,不存储数据;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">数据节点:</strong> 主节点和从节点都是数据节点;</section></li></ul> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">在复制的基础上,哨兵实现了 <strong style="font-weight: bold; color: #BF360C;">自动化的故障恢复</strong> 功能,下方是官方对于哨兵功能的描述:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">监控(Monitoring):</strong> 哨兵会不断地检查主节点和从节点是否运作正常。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">自动故障转移(Automatic failover):</strong> 当 <strong style="font-weight: bold; color: #BF360C;">主节点</strong> 不能正常工作时,哨兵会开始 <strong style="font-weight: bold; color: #BF360C;">自动故障转移操作</strong>,它会将失效主节点的其中一个 <strong style="font-weight: bold; color: #BF360C;">从节点升级为新的主节点</strong>,并让其他从节点改为复制新的主节点。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">配置提供者(Configuration provider):</strong> 客户端在初始化时,通过连接哨兵来获得当前 Redis 服务的主节点地址。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">通知(Notification):</strong> 哨兵可以将故障转移的结果发送给客户端。</section></li></ul> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">其中,监控和自动故障转移功能,使得哨兵可以及时发现主节点故障并完成转移。而配置提供者和通知功能,则需要在与客户端的交互中才能体现。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-62"><span style="display: none;" class="prefix"></span><span class="content">新的主服务器是怎样被挑选出来的?</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><strong style="font-weight: bold; color: #BF360C;">故障转移操作的第一步</strong> 要做的就是在已下线主服务器属下的所有从服务器中,挑选出一个状态良好、数据完整的从服务器,然后向这个从服务器发送 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">slaveof no one</code> 命令,将这个从服务器转换为主服务器。但是这个从服务器是怎么样被挑选出来的呢?</p> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff6d0a6a5a?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="322" data-height="232" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;322&quot; height=&quot;232&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">简单来说 Sentinel 使用以下规则来选择新的主服务器:</p> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">在失效主服务器属下的从服务器当中, 那些被标记为主观下线、已断线、或者最后一次回复 PING 命令的时间大于五秒钟的从服务器都会被 <strong style="font-weight: bold; color: #BF360C;">淘汰</strong>。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">在失效主服务器属下的从服务器当中, 那些与失效主服务器连接断开的时长超过 down-after 选项指定的时长十倍的从服务器都会被 <strong style="font-weight: bold; color: #BF360C;">淘汰</strong>。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">在 <strong style="font-weight: bold; color: #BF360C;">经历了以上两轮淘汰之后</strong> 剩下来的从服务器中, 我们选出 <strong style="font-weight: bold; color: #BF360C;">复制偏移量(replication offset)最大</strong> 的那个 <strong style="font-weight: bold; color: #BF360C;">从服务器</strong> 作为新的主服务器;如果复制偏移量不可用,或者从服务器的复制偏移量相同,那么 <strong style="font-weight: bold; color: #BF360C;">带有最小运行 ID</strong> 的那个从服务器成为新的主服务器。</section></li></ol> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;">更多细节 <strong style="font-weight: bold; color: #BF360C;">推荐阅读</strong> 之前的系列文章,不仅有原理讲解,还有实战环节:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Redis(9)——史上最强【集群】入门实践教程 - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://www.wmyskxz.com/2020/03/17/redis-9-shi-shang-zui-qiang-ji-qun-ru-men-shi-jian-jiao-cheng/" target="_blank" rel="nofollow noopener noreferrer">www.wmyskxz.com/2020/03/17/…</a></section></li></ul> </blockquote> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-63"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">Redis 集群使用过吗?原理?</span><span class="suffix"></span></h2> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff862c95a6?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="531" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;531&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><em style="font-style: italic; color: #009688;">上图</em> 展示了 <strong style="font-weight: bold; color: #BF360C;">Redis Cluster</strong> 典型的架构图,集群中的每一个 Redis 节点都 <strong style="font-weight: bold; color: #BF360C;">互相两两相连</strong>,客户端任意 <strong style="font-weight: bold; color: #BF360C;">直连</strong> 到集群中的 <strong style="font-weight: bold; color: #BF360C;">任意一台</strong>,就可以对其他 Redis 节点进行 <strong style="font-weight: bold; color: #BF360C;">读写</strong> 的操作。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-64"><span style="display: none;" class="prefix"></span><span class="content">基本原理</span><span style="display: none;" class="suffix"></span></h4> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff861ae188?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="531" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;531&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">Redis 集群中内置了 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">16384</code> 个哈希槽。当客户端连接到 Redis 集群之后,会同时得到一份关于这个 <strong style="font-weight: bold; color: #BF360C;">集群的配置信息</strong>,当客户端具体对某一个 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">key</code> 值进行操作时,会计算出它的一个 Hash 值,然后把结果对 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">16384</code> <strong style="font-weight: bold; color: #BF360C;">求余数</strong>,这样每个 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">key</code> 都会对应一个编号在 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">0-16383</code> 之间的哈希槽,Redis 会根据节点数量 <strong style="font-weight: bold; color: #BF360C;">大致均等</strong> 的将哈希槽映射到不同的节点。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">再结合集群的配置信息就能够知道这个 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">key</code> 值应该存储在哪一个具体的 Redis 节点中,如果不属于自己管,那么就会使用一个特殊的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">MOVED</code> 命令来进行一个跳转,告诉客户端去连接这个节点以获取数据:</p> <pre style="margin-top: 10px; margin-bottom: 10px; border-radius: 5px; padding: 0.5em; font-size: 1em; background-color: #2b2b2b!important;" data-tool="mdnice编辑器" class="custom"><code style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; border-style: none; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;" class="hljs copyable">GET x<br>-MOVED 3999 127.0.0.1:6381<br><span class="copy-code-btn">复制代码</span></code></pre> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">MOVED</code> 指令第一个参数 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">3999</code> 是 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">key</code> 对应的槽位编号,后面是目标节点地址,<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">MOVED</code> 命令前面有一个减号,表示这是一个错误的消息。客户端在收到 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">MOVED</code> 指令后,就立即纠正本地的 <strong style="font-weight: bold; color: #BF360C;">槽位映射表</strong>,那么下一次再访问 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">key</code> 时就能够到正确的地方去获取了。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-65"><span style="display: none;" class="prefix"></span><span class="content">集群的主要作用</span><span style="display: none;" class="suffix"></span></h4> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">数据分区:</strong> 数据分区 <em style="font-style: italic; color: #009688;">(或称数据分片)</em> 是集群最核心的功能。集群将数据分散到多个节点,<strong style="font-weight: bold; color: #BF360C;">一方面</strong> 突破了 Redis 单机内存大小的限制,<strong style="font-weight: bold; color: #BF360C;">存储容量大大增加</strong>;<strong style="font-weight: bold; color: #BF360C;">另一方面</strong> 每个主节点都可以对外提供读服务和写服务,<strong style="font-weight: bold; color: #BF360C;">大大提高了集群的响应能力</strong>。Redis 单机内存大小受限问题,在介绍持久化和主从复制时都有提及,例如,如果单机内存太大,<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">bgsave</code> 和 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">bgrewriteaof</code> 的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">fork</code> 操作可能导致主进程阻塞,主从环境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出……</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">高可用:</strong> 集群支持主从复制和主节点的 <strong style="font-weight: bold; color: #BF360C;">自动故障转移</strong> <em style="font-style: italic; color: #009688;">(与哨兵类似)</em>,当任一节点发生故障时,集群仍然可以对外提供服务。</section></li></ol> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-66"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">集群中数据如何分区?</span><span class="suffix"></span></h2> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">Redis 采用方案三。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-67"><span style="display: none;" class="prefix"></span><span class="content">方案一:哈希值 % 节点数</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">哈希取余分区思路非常简单:计算 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">key</code> 的 hash 值,然后对节点数量进行取余,从而决定数据映射到哪个节点上。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">不过该方案最大的问题是,<strong style="font-weight: bold; color: #BF360C;">当新增或删减节点时</strong>,节点数量发生变化,系统中所有的数据都需要 <strong style="font-weight: bold; color: #BF360C;">重新计算映射关系</strong>,引发大规模数据迁移。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-68"><span style="display: none;" class="prefix"></span><span class="content">方案二:一致性哈希分区</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">一致性哈希算法将 <strong style="font-weight: bold; color: #BF360C;">整个哈希值空间</strong> 组织成一个虚拟的圆环,范围是 <em style="font-style: italic; color: #009688;">[0 - 2<sup style="line-height: 0;">32 - 1</sup>]</em>,对于每一个数据,根据 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">key</code> 计算 hash 值,确数据在环上的位置,然后从此位置沿顺时针行走,找到的第一台服务器就是其应该映射到的服务器:</p> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff89a3a0cb?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="1240" data-height="655" src="data:image/svg+xml;utf8,<?xml version=&quot;1.0&quot;?><svg xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot; width=&quot;1240&quot; height=&quot;655&quot;></svg>"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">与哈希取余分区相比,一致性哈希分区将 <strong style="font-weight: bold; color: #BF360C;">增减节点的影响限制在相邻节点</strong>。以上图为例,如果在 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node1</code> 和 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node2</code> 之间增加 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node5</code>,则只有 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node2</code> 中的一部分数据会迁移到 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node5</code>;如果去掉 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node2</code>,则原 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node2</code> 中的数据只会迁移到 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node4</code> 中,只有 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node4</code> 会受影响。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">一致性哈希分区的主要问题在于,当 <strong style="font-weight: bold; color: #BF360C;">节点数量较少</strong> 时,增加或删减节点,<strong style="font-weight: bold; color: #BF360C;">对单个节点的影响可能很大</strong>,造成数据的严重不平衡。还是以上图为例,如果去掉 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node2</code>,<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node4</code> 中的数据由总数据的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">1/4</code> 左右变为 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">1/2</code> 左右,与其他节点相比负载过高。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-69"><span style="display: none;" class="prefix"></span><span class="content">方案三:带有虚拟节点的一致性哈希分区</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">该方案在 <strong style="font-weight: bold; color: #BF360C;">一致性哈希分区的基础上</strong>,引入了 <strong style="font-weight: bold; color: #BF360C;">虚拟节点</strong> 的概念。Redis 集群使用的便是该方案,其中的虚拟节点称为 <strong style="font-weight: bold; color: #BF360C;">槽(slot)</strong>。槽是介于数据和实际节点之间的虚拟概念,每个实际节点包含一定数量的槽,每个槽包含哈希值在一定范围内的数据。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">在使用了槽的一致性哈希分区中,<strong style="font-weight: bold; color: #BF360C;">槽是数据管理和迁移的基本单位</strong>。槽 <strong style="font-weight: bold; color: #BF360C;">解耦</strong> 了 <strong style="font-weight: bold; color: #BF360C;">数据和实际节点</strong> 之间的关系,增加或删除节点对系统的影响很小。仍以上图为例,系统中有 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">4</code> 个实际节点,假设为其分配 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">16</code> 个槽(0-15);</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">槽 0-3 位于 node1;4-7 位于 node2;以此类推....</section></li></ul> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">如果此时删除 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node2</code>,只需要将槽 4-7 重新分配即可,例如槽 4-5 分配给 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node1</code>,槽 6 分配给 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node3</code>,槽 7 分配给 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node4</code>;可以看出删除 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">node2</code> 后,数据在其他节点的分布仍然较为均衡。</p> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-70"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">节点之间的通信机制了解吗?</span><span class="suffix"></span></h2> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">集群的建立离不开节点之间的通信,例如我们在 <em style="font-style: italic; color: #009688;">快速体验</em> 中刚启动六个集群节点之后通过 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">redis-cli</code> 命令帮助我们搭建起来了集群,实际上背后每个集群之间的两两连接是通过了 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">CLUSTER MEET &lt;ip&gt; &lt;port&gt;</code> 命令发送 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">MEET</code> 消息完成的,下面我们展开详细说说。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-71"><span style="display: none;" class="prefix"></span><span class="content">两个端口</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">在 <strong style="font-weight: bold; color: #BF360C;">哨兵系统</strong> 中,节点分为 <strong style="font-weight: bold; color: #BF360C;">数据节点</strong> 和 <strong style="font-weight: bold; color: #BF360C;">哨兵节点</strong>:前者存储数据,后者实现额外的控制功能。在 <strong style="font-weight: bold; color: #BF360C;">集群</strong> 中,没有数据节点与非数据节点之分:<strong style="font-weight: bold; color: #BF360C;">所有的节点都存储数据,也都参与集群状态的维护</strong>。为此,集群中的每个节点,都提供了两个 TCP 端口:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">普通端口:</strong> 即我们在前面指定的端口 <em style="font-style: italic; color: #009688;">(7000等)</em>。普通端口主要用于为客户端提供服务 <em style="font-style: italic; color: #009688;">(与单机节点类似)</em>;但在节点间数据迁移时也会使用。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">集群端口:</strong> 端口号是普通端口 + 10000 <em style="font-style: italic; color: #009688;">(10000是固定值,无法改变)</em>,如 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">7000</code> 节点的集群端口为 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">17000</code>。<strong style="font-weight: bold; color: #BF360C;">集群端口只用于节点之间的通信</strong>,如搭建集群、增减节点、故障转移等操作时节点间的通信;不要使用客户端连接集群接口。为了保证集群可以正常工作,在配置防火墙时,要同时开启普通端口和集群端口。</section></li></ul> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-72"><span style="display: none;" class="prefix"></span><span class="content">Gossip 协议</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">节点间通信,按照通信协议可以分为几种类型:单对单、广播、Gossip 协议等。重点是广播和 Gossip 的对比。</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">广播是指向集群内所有节点发送消息。<strong style="font-weight: bold; color: #BF360C;">优点</strong> 是集群的收敛速度快(集群收敛是指集群内所有节点获得的集群信息是一致的),<strong style="font-weight: bold; color: #BF360C;">缺点</strong> 是每条消息都要发送给所有节点,CPU、带宽等消耗较大。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Gossip 协议的特点是:在节点数量有限的网络中,<strong style="font-weight: bold; color: #BF360C;">每个节点都 “随机” 的与部分节点通信</strong> <em style="font-style: italic; color: #009688;">(并不是真正的随机,而是根据特定的规则选择通信的节点)</em>,经过一番杂乱无章的通信,每个节点的状态很快会达到一致。Gossip 协议的 <strong style="font-weight: bold; color: #BF360C;">优点</strong> 有负载 <em style="font-style: italic; color: #009688;">(比广播)</em> 低、去中心化、容错性高 <em style="font-style: italic; color: #009688;">(因为通信有冗余)</em> 等;<strong style="font-weight: bold; color: #BF360C;">缺点</strong> 主要是集群的收敛速度慢。</section></li></ul> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-73"><span style="display: none;" class="prefix"></span><span class="content">消息类型</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">集群中的节点采用 <strong style="font-weight: bold; color: #BF360C;">固定频率(每秒10次)</strong> 的 <strong style="font-weight: bold; color: #BF360C;">定时任务</strong> 进行通信相关的工作:判断是否需要发送消息及消息类型、确定接收节点、发送消息等。如果集群状态发生了变化,如增减节点、槽状态变更,通过节点间的通信,所有节点会很快得知整个集群的状态,使集群收敛。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">节点间发送的消息主要分为 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">5</code> 种:<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">meet 消息</code>、<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">ping 消息</code>、<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">pong 消息</code>、<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">fail 消息</code>、<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">publish 消息</code>。不同的消息类型,通信协议、发送的频率和时机、接收节点的选择等是不同的:</p> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">MEET 消息:</strong> 在节点握手阶段,当节点收到客户端的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">CLUSTER MEET</code> 命令时,会向新加入的节点发送 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">MEET</code> 消息,请求新节点加入到当前集群;新节点收到 MEET 消息后会回复一个 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">PONG</code> 消息。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">PING 消息:</strong> 集群里每个节点每秒钟会选择部分节点发送 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">PING</code> 消息,接收者收到消息后会回复一个 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">PONG</code> 消息。<strong style="font-weight: bold; color: #BF360C;">PING 消息的内容是自身节点和部分其他节点的状态信息</strong>,作用是彼此交换信息,以及检测节点是否在线。<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">PING</code> 消息使用 Gossip 协议发送,接收节点的选择兼顾了收敛速度和带宽成本,<strong style="font-weight: bold; color: #BF360C;">具体规则如下</strong>:(1)随机找 5 个节点,在其中选择最久没有通信的 1 个节点;(2)扫描节点列表,选择最近一次收到 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">PONG</code> 消息时间大于 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">cluster_node_timeout / 2</code> 的所有节点,防止这些节点长时间未更新。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">PONG消息:</strong> <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">PONG</code> 消息封装了自身状态数据。可以分为两种:<strong style="font-weight: bold; color: #BF360C;">第一种</strong> 是在接到 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">MEET/PING</code> 消息后回复的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">PONG</code> 消息;<strong style="font-weight: bold; color: #BF360C;">第二种</strong> 是指节点向集群广播 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">PONG</code> 消息,这样其他节点可以获知该节点的最新信息,例如故障恢复后新的主节点会广播 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">PONG</code> 消息。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">FAIL 消息:</strong> 当一个主节点判断另一个主节点进入 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">FAIL</code> 状态时,会向集群广播这一 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">FAIL</code> 消息;接收节点会将这一 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">FAIL</code> 消息保存起来,便于后续的判断。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">PUBLISH 消息:</strong> 节点收到 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">PUBLISH</code> 命令后,会先执行该命令,然后向集群广播这一消息,接收节点也会执行该 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">PUBLISH</code> 命令。</section></li></ul> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-74"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">集群数据如何存储的有了解吗?</span><span class="suffix"></span></h2> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">节点需要专门的数据结构来存储集群的状态。所谓集群的状态,是一个比较大的概念,包括:集群是否处于上线状态、集群中有哪些节点、节点是否可达、节点的主从状态、槽的分布……</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">节点为了存储集群状态而提供的数据结构中,最关键的是 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">clusterNode</code> 和 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">clusterState</code> 结构:前者记录了一个节点的状态,后者记录了集群作为一个整体的状态。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-75"><span style="display: none;" class="prefix"></span><span class="content">clusterNode 结构</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">clusterNode</code> 结构保存了 <strong style="font-weight: bold; color: #BF360C;">一个节点的当前状态</strong>,包括创建时间、节点 id、ip 和端口号等。每个节点都会用一个 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">clusterNode</code> 结构记录自己的状态,并为集群内所有其他节点都创建一个 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">clusterNode</code> 结构来记录节点状态。</p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">下面列举了 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">clusterNode</code> 的部分字段,并说明了字段的含义和作用:</p> <pre style="margin-top: 10px; margin-bottom: 10px; border-radius: 5px; padding: 0.5em; font-size: 1em; background-color: #2b2b2b!important;" data-tool="mdnice编辑器" class="custom"><code style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; border-style: none; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;" class="hljs copyable"><span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">typedef</span> <span style="line-height: 26px;" class="hljs-class"><span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">struct</span> <span style="color: #e6c07b; line-height: 26px;" class="hljs-title">clusterNode</span> {</span><br> <span style="color: #5c6370; font-style: italic; line-height: 26px;" class="hljs-comment">//节点创建时间</span><br> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">mstime_t</span> ctime;<br> <span style="color: #5c6370; font-style: italic; line-height: 26px;" class="hljs-comment">//节点id</span><br> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">char</span> name[REDIS_CLUSTER_NAMELEN];<br> <span style="color: #5c6370; font-style: italic; line-height: 26px;" class="hljs-comment">//节点的ip和端口号</span><br> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">char</span> ip[REDIS_IP_STR_LEN];<br> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">int</span> port;<br> <span style="color: #5c6370; font-style: italic; line-height: 26px;" class="hljs-comment">//节点标识:整型,每个bit都代表了不同状态,如节点的主从状态、是否在线、是否在握手等</span><br> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">int</span> flags;<br> <span style="color: #5c6370; font-style: italic; line-height: 26px;" class="hljs-comment">//配置纪元:故障转移时起作用,类似于哨兵的配置纪元</span><br> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">uint64_t</span> configEpoch;<br> <span style="color: #5c6370; font-style: italic; line-height: 26px;" class="hljs-comment">//槽在该节点中的分布:占用16384/8个字节,16384个比特;每个比特对应一个槽:比特值为1,则该比特对应的槽在节点中;比特值为0,则该比特对应的槽不在节点中</span><br> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">unsigned</span> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">char</span> slots[<span style="color: #d19a66; line-height: 26px;" class="hljs-number">16384</span>/<span style="color: #d19a66; line-height: 26px;" class="hljs-number">8</span>];<br> <span style="color: #5c6370; font-style: italic; line-height: 26px;" class="hljs-comment">//节点中槽的数量</span><br> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">int</span> numslots;<br> …………<br>} clusterNode;<br><span class="copy-code-btn">复制代码</span></code></pre> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">除了上述字段,<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">clusterNode</code> 还包含节点连接、主从复制、故障发现和转移需要的信息等。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-76"><span style="display: none;" class="prefix"></span><span class="content">clusterState 结构</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器"><code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">clusterState</code> 结构保存了在当前节点视角下,集群所处的状态。主要字段包括:</p> <pre style="margin-top: 10px; margin-bottom: 10px; border-radius: 5px; padding: 0.5em; font-size: 1em; background-color: #2b2b2b!important;" data-tool="mdnice编辑器" class="custom"><code style="overflow-x: auto; padding: 16px; color: #abb2bf; background: #282c34; border-style: none; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; border-radius: 0px; font-size: 12px; -webkit-overflow-scrolling: touch;" class="hljs copyable"><span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">typedef</span> <span style="line-height: 26px;" class="hljs-class"><span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">struct</span> <span style="color: #e6c07b; line-height: 26px;" class="hljs-title">clusterState</span> {</span><br> <span style="color: #5c6370; font-style: italic; line-height: 26px;" class="hljs-comment">//自身节点</span><br> clusterNode *myself;<br> <span style="color: #5c6370; font-style: italic; line-height: 26px;" class="hljs-comment">//配置纪元</span><br> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">uint64_t</span> currentEpoch;<br> <span style="color: #5c6370; font-style: italic; line-height: 26px;" class="hljs-comment">//集群状态:在线还是下线</span><br> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">int</span> state;<br> <span style="color: #5c6370; font-style: italic; line-height: 26px;" class="hljs-comment">//集群中至少包含一个槽的节点数量</span><br> <span style="color: #c678dd; line-height: 26px;" class="hljs-keyword">int</span> size;<br> <span style="color: #5c6370; font-style: italic; line-height: 26px;" class="hljs-comment">//哈希表,节点名称-&gt;clusterNode节点指针</span><br> dict *nodes;<br> <span style="color: #5c6370; font-style: italic; line-height: 26px;" class="hljs-comment">//槽分布信息:数组的每个元素都是一个指向clusterNode结构的指针;如果槽还没有分配给任何节点,则为NULL</span><br> clusterNode *slots[<span style="color: #d19a66; line-height: 26px;" class="hljs-number">16384</span>];<br> …………<br>} clusterState;<br><span class="copy-code-btn">复制代码</span></code></pre> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">除此之外,<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">clusterState</code> 还包括故障转移、槽迁移等需要的信息。</p> <h1 style="font-weight: bold; font-size: 1.6em; background-color: rgb(0, 150, 136); margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; color: rgb(255, 255, 255) !important; padding: 1px 8px !important;" data-tool="mdnice编辑器" data-id="heading-77"><span style="display: none;" class="prefix"></span><span class="content">五、其他问题</span><span class="suffix"></span></h1> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-78"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">Redis 如何实现分布式锁?</span><span class="suffix"></span></h2> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <p style="padding-top: 8px; padding-bottom: 8px; font-family: 微软雅黑; margin: 0px; font-size: 0.95rem; color: rgba(68,68,68,0.9); line-height: 28px; margin-top: -20px !important;"><strong style="font-weight: bold; color: #BF360C;">推荐阅读</strong> 之前的系列文章: Redis(3)——分布式锁深入探究 - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://www.wmyskxz.com/2020/03/01/redis-3/" target="_blank" rel="nofollow noopener noreferrer">www.wmyskxz.com/2020/03/01/…</a></p> </blockquote> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-79"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">Redis 过期键的删除策略?</span><span class="suffix"></span></h2> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-80"><span style="display: none;" class="prefix"></span><span class="content">简单描述</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">先抛开 Redis 想一下几种可能的删除策略:</p> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">定时删除</strong>:在设置键的过期时间的同时,创建一个定时器 timer). 让定时器在键的过期时间来临时,立即执行对键的删除操作。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">惰性删除</strong>:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">定期删除</strong>:每隔一段时间程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。</section></li></ol> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">在上述的三种策略中定时删除和定期删除属于不同时间粒度的 <strong style="font-weight: bold; color: #BF360C;">主动删除</strong>,惰性删除属于 <strong style="font-weight: bold; color: #BF360C;">被动删除</strong>。</p> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-81"><span style="display: none;" class="prefix"></span><span class="content">三种策略都有各自的优缺点</span><span style="display: none;" class="suffix"></span></h4> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">定时删除对内存使用率有优势,但是对 CPU 不友好;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">惰性删除对内存不友好,如果某些键值对一直不被使用,那么会造成一定量的内存浪费;</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">定期删除是定时删除和惰性删除的折中。</section></li></ol> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-82"><span style="display: none;" class="prefix"></span><span class="content">Redis 中的实现</span><span style="display: none;" class="suffix"></span></h4> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">Reids 采用的是 <strong style="font-weight: bold; color: #BF360C;">惰性删除和定时删除</strong> 的结合,一般来说可以借助最小堆来实现定时器,不过 Redis 的设计考虑到时间事件的有限种类和数量,使用了无序链表存储时间事件,这样如果在此基础上实现定时删除,就意味着 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">O(N)</code> 遍历获取最近需要删除的数据。</p> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-83"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">Redis 的淘汰策略有哪些?</span><span class="suffix"></span></h2> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-84"><span style="display: none;" class="prefix"></span><span class="content">Redis 有六种淘汰策略</span><span style="display: none;" class="suffix"></span></h4> <table style="display: table; text-align: left; font-size: 1em; border-collapse: collapse; border-spacing: 0; overflow: hidden; border-top-left-radius: 6px; border-top-right-radius: 6px; border-bottom-right-radius: 6px; border-bottom-left-radius: 6px; width: 100%!important;" data-tool="mdnice编辑器"> <thead> <tr style="border: 0; border-top: 1px solid #ccc; background-color: white; border-width: 1px!important; border-style: solid!important; border-color: #009688!important;"> <th style="font-family: 微软雅黑; font-size: 16px; border: 1px solid #ccc; font-weight: bold; text-align: left; border-width: 1px!important; border-style: solid!important; border-color: #009688!important; padding: 5px 10px!important; background-color: #009688!important; border-bottom-width: 0!important; color: #fff!important;">策略</th> <th style="font-family: 微软雅黑; font-size: 16px; border: 1px solid #ccc; font-weight: bold; text-align: left; border-width: 1px!important; border-style: solid!important; border-color: #009688!important; padding: 5px 10px!important; background-color: #009688!important; border-bottom-width: 0!important; color: #fff!important;">描述</th> </tr> </thead> <tbody style="border: 0;"> <tr style="border: 0; border-top: 1px solid #ccc; background-color: white; border-width: 1px!important; border-style: solid!important; border-color: #009688!important;"> <td style="font-family: 微软雅黑; font-weight: bold; font-size: 16px; border: 1px solid #ccc; text-align: left; color: #7F8C8D!important; background-color: #ddd!important; padding: 5px 10px!important;">volatile-lru</td> <td style="font-family: 微软雅黑; font-weight: bold; font-size: 16px; border: 1px solid #ccc; text-align: left; color: #7F8C8D!important; background-color: #ddd!important; padding: 5px 10px!important;">从已设置过期时间的 KV 集中优先对最近最少使用(less recently used)的数据淘汰</td> </tr> <tr style="border: 0; border-top: 1px solid #ccc; background-color: #F8F8F8; border-width: 1px!important; border-style: solid!important; border-color: #009688!important;"> <td style="font-family: 微软雅黑; font-weight: bold; font-size: 16px; border: 1px solid #ccc; text-align: left; color: #7F8C8D!important; background-color: #ddd!important; padding: 5px 10px!important;">volitile-ttl</td> <td style="font-family: 微软雅黑; font-weight: bold; font-size: 16px; border: 1px solid #ccc; text-align: left; color: #7F8C8D!important; background-color: #ddd!important; padding: 5px 10px!important;">从已设置过期时间的 KV 集中优先对剩余时间短(time to live)的数据淘汰</td> </tr> <tr style="border: 0; border-top: 1px solid #ccc; background-color: white; border-width: 1px!important; border-style: solid!important; border-color: #009688!important;"> <td style="font-family: 微软雅黑; font-weight: bold; font-size: 16px; border: 1px solid #ccc; text-align: left; color: #7F8C8D!important; background-color: #ddd!important; padding: 5px 10px!important;">volitile-random</td> <td style="font-family: 微软雅黑; font-weight: bold; font-size: 16px; border: 1px solid #ccc; text-align: left; color: #7F8C8D!important; background-color: #ddd!important; padding: 5px 10px!important;">从已设置过期时间的 KV 集中随机选择数据淘汰</td> </tr> <tr style="border: 0; border-top: 1px solid #ccc; background-color: #F8F8F8; border-width: 1px!important; border-style: solid!important; border-color: #009688!important;"> <td style="font-family: 微软雅黑; font-weight: bold; font-size: 16px; border: 1px solid #ccc; text-align: left; color: #7F8C8D!important; background-color: #ddd!important; padding: 5px 10px!important;">allkeys-lru</td> <td style="font-family: 微软雅黑; font-weight: bold; font-size: 16px; border: 1px solid #ccc; text-align: left; color: #7F8C8D!important; background-color: #ddd!important; padding: 5px 10px!important;">从所有 KV 集中优先对最近最少使用(less recently used)的数据淘汰</td> </tr> <tr style="border: 0; border-top: 1px solid #ccc; background-color: white; border-width: 1px!important; border-style: solid!important; border-color: #009688!important;"> <td style="font-family: 微软雅黑; font-weight: bold; font-size: 16px; border: 1px solid #ccc; text-align: left; color: #7F8C8D!important; background-color: #ddd!important; padding: 5px 10px!important;">allKeys-random</td> <td style="font-family: 微软雅黑; font-weight: bold; font-size: 16px; border: 1px solid #ccc; text-align: left; color: #7F8C8D!important; background-color: #ddd!important; padding: 5px 10px!important;">从所有 KV 集中随机选择数据淘汰</td> </tr> <tr style="border: 0; border-top: 1px solid #ccc; background-color: #F8F8F8; border-width: 1px!important; border-style: solid!important; border-color: #009688!important;"> <td style="font-family: 微软雅黑; font-weight: bold; font-size: 16px; border: 1px solid #ccc; text-align: left; color: #7F8C8D!important; background-color: #ddd!important; padding: 5px 10px!important;">noeviction</td> <td style="font-family: 微软雅黑; font-weight: bold; font-size: 16px; border: 1px solid #ccc; text-align: left; color: #7F8C8D!important; background-color: #ddd!important; padding: 5px 10px!important;">不淘汰策略,若超过最大内存,返回错误信息</td> </tr> </tbody> </table> <h4 style="margin-top: 30px; margin-bottom: 15px; font-weight: bold; font-size: 1em; background-color: #009688; display: inline-block; margin: 20px 0 10px !important; padding: 1px 6px !important; color: #fff !important;" data-tool="mdnice编辑器" data-id="heading-85"><span style="display: none;" class="prefix"></span><span class="content">4.0 版本后增加以下两种</span><span style="display: none;" class="suffix"></span></h4> <ul style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">volatile-lfu:从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">allkeys-lfu:当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key</section></li></ul> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-86"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">Redis常见性能问题和解决方案?</span><span class="suffix"></span></h2> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Master 最好不要做任何持久化工作,包括内存快照和 AOF 日志文件,特别是不要启用内存快照做持久化。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">如果数据比较关键,某个 Slave 开启 AOF 备份数据,策略为每秒同步一次。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">为了主从复制的速度和连接的稳定性,Slave 和 Master 最好在同一个局域网内。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">尽量避免在压力较大的主库上增加从库。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Master 调用 BGREWRITEAOF 重写 AOF 文件,AOF 在重写的时候会占大量的 CPU 和内存资源,导致服务 load 过高,出现短暂服务暂停现象。</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">为了 Master 的稳定性,主从复制不要用图状结构,用单向链表结构更稳定,即主从关系为:Master&lt;–Slave1&lt;–Slave2&lt;–Slave3…,这样的结构也方便解决单点故障问题,实现 Slave 对 Master 的替换,也即,如果 Master 挂了,可以立马启用 Slave1 做 Master,其他不变。</section></li></ol> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-87"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如何将它们全部找出来?</span><span class="suffix"></span></h2> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">使用 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">keys</code> 指令可以扫出指定模式的 key 列表。但是要注意 keys 指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">scan</code> 指令,<code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">scan</code> 指令可以无阻塞的提取出指定模式的 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">key</code> 列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用 <code style="border-style: none; font-size: 14px; word-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0 2px; color: #1e6bb8; background-color: rgba(27,31,35,.05); font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; word-break: break-all;">keys</code> 指令长。</p> <h2 style="font-weight: bold; font-size: 1.4em; background-color: rgb(0, 150, 136); border-radius: 6px; margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; padding: 1px 6px !important; color: rgb(255, 255, 255) !important;" data-tool="mdnice编辑器" data-id="heading-88"><span style="margin-right: 6px;">■</span><span style="display: none;" class="prefix"></span><span class="content">More..</span><span class="suffix"></span></h2> <h1 style="font-weight: bold; font-size: 1.6em; background-color: rgb(0, 150, 136); margin: 20px 0 10px !important; margin-top: 20px !important; margin-bottom: 10px !important; color: rgb(255, 255, 255) !important; padding: 1px 8px !important;" data-tool="mdnice编辑器" data-id="heading-89"><span style="display: none;" class="prefix"></span><span class="content">参考资料</span><span class="suffix"></span></h1> <ol style="margin-top: 8px; margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: decimal;" data-tool="mdnice编辑器"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">3w字深度好文|Redis面试全攻略,读完这个就可以和面试官大战几个回合了 - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://mp.weixin.qq.com/s/f9N13fnyTtnu2D5sKZiu9w" target="_blank" rel="nofollow noopener noreferrer">mp.weixin.qq.com/s/f9N13fnyT…</a></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">大厂面试!我和面试官之间关于Redis的一场对弈! - [https://mp.weixin.qq.com/s/DHTPSfmWTZpdTmlytzLz1g](https://mp.weixin.qq.com/s/DHTPSfmWTZpdTmlytzLz1g</section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">Redis面试题(2020最新版) - <a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://blog.csdn.net/ThinkWon/article/details/103522351" target="_blank" rel="nofollow noopener noreferrer">blog.csdn.net/ThinkWon/ar…</a></section></li></ol> <blockquote style="display: block; font-size: 0.9em; overflow: auto; overflow-scrolling: touch; background: rgba(0, 0, 0, 0.05); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 10px; margin-bottom: 20px; margin-top: 20px; border-left: 3px solid #009688; quotes: none; font-style: normal; padding: 12px; position: relative; line-height: 1.8; text-indent: 0; border: none; color: #888;" data-tool="mdnice编辑器"><span style="display: inline; color: #555555; font-size: 4em; font-family: Arial, serif; line-height: 1em; font-weight: 700;">“</span> <ul style="margin-bottom: 8px; padding-left: 25px; color: black; list-style-type: disc; margin-top: -20px !important;"> <li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;">本文已收录至我的 Github 程序员成长系列 <strong style="font-weight: bold; color: #BF360C;">【More Than Java】,学习,不止 Code,欢迎 star:<a style="text-decoration: none; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8; color: #009688;" href="https://github.com/wmyskxz/MoreThanJava" target="_blank" rel="nofollow noopener noreferrer">github.com/wmyskxz/Mor…</a></strong></section></li><li><section style="margin-top: 5px; margin-bottom: 5px; line-height: 26px; text-align: left; color: rgb(1,1,1); font-weight: 500;"><strong style="font-weight: bold; color: #BF360C;">个人公众号</strong> :wmyskxz,<strong style="font-weight: bold; color: #BF360C;">个人独立域名博客</strong>:wmyskxz.com,坚持原创输出,下方扫码关注,2020,与您共同成长!</section></li></ul> </blockquote> <figure style="margin: 0; margin-top: 10px; margin-bottom: 10px;" data-tool="mdnice编辑器"><img style="width: auto; max-width: 100%; display: block; text-align: center; margin: 0 auto; border-radius: 5px;" alt="" class="lazyload inited loaded" data-src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff905fd414?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" data-width="344" data-height="344" src="https://user-gold-cdn.xitu.io/2020/3/25/171117ff905fd414?imageView2/0/w/1280/h/960/format/webp/ignore-error/1"></figure> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">非常感谢各位人才能 <strong style="font-weight: bold; color: #BF360C;">看到这里</strong>,如果觉得本篇文章写得不错,觉得 <strong style="font-weight: bold; color: #BF360C;">「我没有三颗心脏」有点东西</strong> 的话,<strong style="font-weight: bold; color: #BF360C;">求点赞,求关注,求分享,求留言!</strong></p> <p style="padding-top: 8px; padding-bottom: 8px; margin: 0; font-size: 1em; line-height: 28px; color: #595959; font-family: 微软雅黑;" data-tool="mdnice编辑器">创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!</p> </section></div></article><div data-v-7407bc26="" data-v-23c7d456="" class="tag-list-box"><div data-v-7407bc26="" data-v-23c7d456="" class="tag-list-title">关注下面的标签,发现更多相似文章</div><div data-v-7407bc26="" data-v-23c7d456="" st:block="tagList" class="tag-list"><a data-v-7407bc26="" href="/tag/Redis" target="_blank" rel="" st:name="tag" class="item" data-v-23c7d456=""><div data-v-292b3648="" data-v-4d895a49="" data-v-7407bc26="" data-src="https://lc-gold-cdn.xitu.io/4045af43b278afc7229b.png?imageView2/2/w/42/h/42/q/85/format/webp/interlace/1" class="lazy thumb tag-icon loaded" style="background-image: url(&quot;https://lc-gold-cdn.xitu.io/4045af43b278afc7229b.png?imageView2/2/w/42/h/42/q/85/format/webp/interlace/1&quot;); background-size: contain;"></div><div data-v-7407bc26="" class="tag-title">Redis</div></a></div></div><a data-v-7407bc26="" href="/user/5cfb61a36fb9a07ef819ef3a" target="_blank" rel="" data-v-23c7d456=""><div data-v-7407bc26="" class="footer-author-block"><div data-v-60bba1f2="" data-v-7407bc26="" itemscope="itemscope" itemtype="http://schema.org/Person" class="author"><meta itemprop="url" content="https://juejin.im/user/5cfb61a36fb9a07ef819ef3a"><meta itemprop="image" content="https://user-gold-cdn.xitu.io/2019/6/8/16b35f5985473ab9?w=638&amp;h=638&amp;f=png&amp;s=227542"><meta itemprop="name" content="我没有三颗心脏"><meta itemprop="jobTitle" content="后端开发"><!----><div data-v-60bba1f2="" class="author-info-block"><a data-v-60bba1f2="" href="/user/5cfb61a36fb9a07ef819ef3a" target="_blank" rel="" class="avatar-link"><div data-v-292b3648="" data-v-11331c20="" data-v-60bba1f2="" data-src="https://user-gold-cdn.xitu.io/2019/6/8/16b35f5985473ab9?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1" class="lazy avatar avatar loaded" style="background-image: url(&quot;https://user-gold-cdn.xitu.io/2019/6/8/16b35f5985473ab9?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1&quot;);"></div></a><div data-v-60bba1f2="" class="author-info-box"><div data-v-60bba1f2="" class="profile-box"><a data-v-44e95489="" data-v-60bba1f2="" href="/user/5cfb61a36fb9a07ef819ef3a" target="_blank" rel="" class="username username ellipsis">我没有三颗心脏<a data-v-00e1e43c="" data-v-44e95489="" href="/book/5c90640c5188252d7941f5bb/section/5c9065385188252da6320022" target="_blank" rel="" class="rank"><img data-v-00e1e43c="" src="https://b-gold-cdn.xitu.io/v3/static/img/lv-2.f597b88.svg" alt="lv-2"></a></a><span data-v-60bba1f2="" class="position ellipsis">后端开发</span></div><div data-v-60bba1f2="" class="meta-box"><a data-v-60bba1f2="" href="/user/5cfb61a36fb9a07ef819ef3a/posts" target="_blank" rel="" class="posts"><span data-v-60bba1f2="" class="count post-count">发布了 22 篇专栏 · </span></a><span data-v-60bba1f2="" class="count">获得点赞 118 · </span><span data-v-60bba1f2="" class="count">获得阅读 4,838</span></div></div><button data-v-fa88a374="" data-v-60bba1f2="" class="follow-button follow">关注</button></div></div></div></a><div data-v-7407bc26="" data-v-23c7d456="" st:block="banner" class="article-banner"><a data-v-7407bc26="" data-v-23c7d456="" st:name="link" st:state="https://juejin.im/extension/?utm_source=juejin.im&amp;utm_medium=post&amp;utm_campaign=extension_promotion" class="banner-title" href="https://juejin.im/extension/?utm_source=juejin.im&amp;utm_medium=post&amp;utm_campaign=extension_promotion" target="_blank">安装掘金浏览器插件</a><div data-v-7407bc26="" data-v-23c7d456="" class="banner-content">打开新标签页发现好内容,掘金、GitHub、Dribbble、ProductHunt 等站点内容轻松获取。快来安装掘金浏览器插件获取高质量内容吧!</div></div><!----><!----><div data-v-4b46f152="" data-v-7407bc26="" class="comment-list-box" id="comment-box" data-v-23c7d456="" manual="true"><div data-v-4b46f152="" class="title">评论</div><div data-v-5d62a384="" data-v-4b46f152="" class="comment-form comment-form"><div data-v-5d62a384="" class="avatar-box"><div data-v-292b3648="" data-v-11331c20="" data-v-5d62a384="" data-src="https://b-gold-cdn.xitu.io/v3/static/img/default-avatar.e30559a.svg" class="lazy avatar avatar loaded" style="background-image: url(&quot;https://b-gold-cdn.xitu.io/v3/static/img/default-avatar.e30559a.svg&quot;);"></div></div><div data-v-5d62a384="" class="form-box"><div data-v-5d62a384="" class="input-box"><div data-v-8f167968="" data-v-5d62a384="" class="auth-card"><!----><div data-v-5d62a384="" data-v-8f167968="" contenteditable="true" spellcheck="false" placeholder="输入评论..." class="rich-input empty"><br data-v-5d62a384="" data-v-8f167968=""></div></div><!----></div><!----></div><input data-v-5d62a384="" type="file" class="hidden"></div><div data-v-1d85495c="" data-v-4b46f152="" class="comment-list comment-list"><div data-v-5db6962e="" data-v-1d85495c="" class="image-viewer-box"><!----></div><div data-v-1d85495c="" class="item"><div data-v-c3a00e66="" data-v-1d85495c="" class="comment comment"><div data-v-0f4ef93c="" data-v-c3a00e66="" st:block="userPopover" st:state="57d8abfaa0bb9f00587a1108" class="user-popover-box popover"><!----><a data-v-c3a00e66="" href="/user/57d8abfaa0bb9f00587a1108" target="_blank" rel="" class="user-link" data-v-0f4ef93c=""><div data-v-292b3648="" data-v-11331c20="" data-v-c3a00e66="" data-src="https://user-gold-cdn.xitu.io/2018/8/12/1652ccb4c024b255?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1" class="lazy avatar avatar loaded" style="background-image: url(&quot;https://user-gold-cdn.xitu.io/2018/8/12/1652ccb4c024b255?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1&quot;);"></div></a></div><div data-v-c3a00e66="" class="content-box comment-divider-line"><div data-v-c3a00e66="" class="meta-box"><div data-v-0f4ef93c="" data-v-c3a00e66="" st:block="userPopover" st:state="57d8abfaa0bb9f00587a1108" class="user-popover-box"><!----><a data-v-44e95489="" data-v-c3a00e66="" href="/user/57d8abfaa0bb9f00587a1108" target="_blank" rel="" class="username username ellipsis" data-v-0f4ef93c="">MigrationUK<!----></a></div><div data-v-c3a00e66="" class="position">Gopher @ Forchange</div></div><div data-v-c3a00e66="" class="content">图还行</div><div data-v-c3a00e66="" class="limit-ctl-box"><!----><!----></div><!----><div data-v-c3a00e66="" class="reply-stat"><time data-v-c3a00e66="" datetime="2020-03-29T15:55:50.466Z" title="Sun Mar 29 2020 23:55:50 GMT+0800 (中国标准时间)" class="time">6天前</time><div data-v-c3a00e66="" class="delete"> &nbsp;·&nbsp;删除</div><div data-v-c3a00e66="" class="action-box"><div data-v-c3a00e66="" class="like-action action"><svg data-v-c3a00e66="" aria-hidden="true" width="16" height="16" viewBox="0 0 20 20" class="icon like-icon"><g data-v-c3a00e66="" fill="none" fill-rule="evenodd"><path data-v-c3a00e66="" d="M0 0h20v20H0z"></path> <path data-v-c3a00e66="" stroke="#8A93A0" stroke-linejoin="round" d="M4.58 8.25V17h-1.4C2.53 17 2 16.382 2 15.624V9.735c0-.79.552-1.485 1.18-1.485h1.4zM11.322 2c1.011.019 1.614.833 1.823 1.235.382.735.392 1.946.13 2.724-.236.704-.785 1.629-.785 1.629h4.11c.434 0 .838.206 1.107.563.273.365.363.84.24 1.272l-1.86 6.513A1.425 1.425 0 0 1 14.724 17H6.645V7.898C8.502 7.51 9.643 4.59 9.852 3.249A1.47 1.47 0 0 1 11.322 2z"></path></g></svg><!----></div><div data-v-c3a00e66="" class="comment-action action"><svg data-v-c3a00e66="" aria-hidden="true" width="16" height="16" viewBox="0 0 20 20" class="icon comment-icon"><g data-v-c3a00e66="" fill="none" fill-rule="evenodd"><path data-v-c3a00e66="" d="M0 0h20v20H0z"></path> <path data-v-c3a00e66="" stroke="#8A93A0" stroke-linejoin="round" d="M10 17c-4.142 0-7.5-2.91-7.5-6.5S5.858 4 10 4c4.142 0 7.5 2.91 7.5 6.5 0 1.416-.522 2.726-1.41 3.794-.129.156.41 3.206.41 3.206l-3.265-1.134c-.998.369-2.077.634-3.235.634z"></path></g></svg> <span data-v-c3a00e66="" class="action-title">回复</span></div></div></div><!----><div data-v-39f2ce6a="" data-v-c3a00e66="" class="sub-comment-list sub-comment-list"><!----></div></div><!----></div></div><div data-v-1d85495c="" class="item"><div data-v-c3a00e66="" data-v-1d85495c="" class="comment comment"><div data-v-0f4ef93c="" data-v-c3a00e66="" st:block="userPopover" st:state="5e5db8c0e51d452716050cdd" class="user-popover-box popover"><!----><a data-v-c3a00e66="" href="/user/5e5db8c0e51d452716050cdd" target="_blank" rel="" class="user-link" data-v-0f4ef93c=""><div data-v-292b3648="" data-v-11331c20="" data-v-c3a00e66="" data-src="https://b-gold-cdn.xitu.io/v3/static/img/default-avatar.e30559a.svg" class="lazy avatar avatar loaded" style="background-image: url(&quot;https://b-gold-cdn.xitu.io/v3/static/img/default-avatar.e30559a.svg&quot;);"></div></a></div><div data-v-c3a00e66="" class="content-box comment-divider-line"><div data-v-c3a00e66="" class="meta-box"><div data-v-0f4ef93c="" data-v-c3a00e66="" st:block="userPopover" st:state="5e5db8c0e51d452716050cdd" class="user-popover-box"><!----><a data-v-44e95489="" data-v-c3a00e66="" href="/user/5e5db8c0e51d452716050cdd" target="_blank" rel="" class="username username ellipsis" data-v-0f4ef93c="">黑豆君<!----></a></div><div data-v-c3a00e66="" class="position">Java</div></div><div data-v-c3a00e66="" class="content">Redis事物不能保证原子性</div><div data-v-c3a00e66="" class="limit-ctl-box"><!----><!----></div><!----><div data-v-c3a00e66="" class="reply-stat"><time data-v-c3a00e66="" datetime="2020-03-29T00:51:39.270Z" title="Sun Mar 29 2020 08:51:39 GMT+0800 (中国标准时间)" class="time">7天前</time><div data-v-c3a00e66="" class="delete"> &nbsp;·&nbsp;删除</div><div data-v-c3a00e66="" class="action-box"><div data-v-c3a00e66="" class="like-action action"><svg data-v-c3a00e66="" aria-hidden="true" width="16" height="16" viewBox="0 0 20 20" class="icon like-icon"><g data-v-c3a00e66="" fill="none" fill-rule="evenodd"><path data-v-c3a00e66="" d="M0 0h20v20H0z"></path> <path data-v-c3a00e66="" stroke="#8A93A0" stroke-linejoin="round" d="M4.58 8.25V17h-1.4C2.53 17 2 16.382 2 15.624V9.735c0-.79.552-1.485 1.18-1.485h1.4zM11.322 2c1.011.019 1.614.833 1.823 1.235.382.735.392 1.946.13 2.724-.236.704-.785 1.629-.785 1.629h4.11c.434 0 .838.206 1.107.563.273.365.363.84.24 1.272l-1.86 6.513A1.425 1.425 0 0 1 14.724 17H6.645V7.898C8.502 7.51 9.643 4.59 9.852 3.249A1.47 1.47 0 0 1 11.322 2z"></path></g></svg><!----></div><div data-v-c3a00e66="" class="comment-action action"><svg data-v-c3a00e66="" aria-hidden="true" width="16" height="16" viewBox="0 0 20 20" class="icon comment-icon"><g data-v-c3a00e66="" fill="none" fill-rule="evenodd"><path data-v-c3a00e66="" d="M0 0h20v20H0z"></path> <path data-v-c3a00e66="" stroke="#8A93A0" stroke-linejoin="round" d="M10 17c-4.142 0-7.5-2.91-7.5-6.5S5.858 4 10 4c4.142 0 7.5 2.91 7.5 6.5 0 1.416-.522 2.726-1.41 3.794-.129.156.41 3.206.41 3.206l-3.265-1.134c-.998.369-2.077.634-3.235.634z"></path></g></svg> <span data-v-c3a00e66="" class="action-title">回复</span></div></div></div><!----><div data-v-39f2ce6a="" data-v-c3a00e66="" class="sub-comment-list sub-comment-list"><!----></div></div><!----></div></div><div data-v-1d85495c="" class="item"><div data-v-c3a00e66="" data-v-1d85495c="" class="comment comment"><div data-v-0f4ef93c="" data-v-c3a00e66="" st:block="userPopover" st:state="5c3da3916fb9a04a06051fd9" class="user-popover-box popover"><!----><a data-v-c3a00e66="" href="/user/5c3da3916fb9a04a06051fd9" target="_blank" rel="" class="user-link" data-v-0f4ef93c=""><div data-v-292b3648="" data-v-11331c20="" data-v-c3a00e66="" data-src="https://mirror-gold-cdn.xitu.io/168e09badc9eb7ee2c2?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1" class="lazy avatar avatar loaded" style="background-image: url(&quot;https://mirror-gold-cdn.xitu.io/168e09badc9eb7ee2c2?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1&quot;);"></div></a></div><div data-v-c3a00e66="" class="content-box comment-divider-line"><div data-v-c3a00e66="" class="meta-box"><div data-v-0f4ef93c="" data-v-c3a00e66="" st:block="userPopover" st:state="5c3da3916fb9a04a06051fd9" class="user-popover-box"><!----><a data-v-44e95489="" data-v-c3a00e66="" href="/user/5c3da3916fb9a04a06051fd9" target="_blank" rel="" class="username username ellipsis" data-v-0f4ef93c="">Wyman的小站<!----></a></div><div data-v-c3a00e66="" class="position"></div></div><div data-v-c3a00e66="" class="content">真滴详细, 有空看完</div><div data-v-c3a00e66="" class="limit-ctl-box"><!----><!----></div><!----><div data-v-c3a00e66="" class="reply-stat"><time data-v-c3a00e66="" datetime="2020-03-27T09:15:13.591Z" title="Fri Mar 27 2020 17:15:13 GMT+0800 (中国标准时间)" class="time">9天前</time><div data-v-c3a00e66="" class="delete"> &nbsp;·&nbsp;删除</div><div data-v-c3a00e66="" class="action-box"><div data-v-c3a00e66="" class="like-action action"><svg data-v-c3a00e66="" aria-hidden="true" width="16" height="16" viewBox="0 0 20 20" class="icon like-icon"><g data-v-c3a00e66="" fill="none" fill-rule="evenodd"><path data-v-c3a00e66="" d="M0 0h20v20H0z"></path> <path data-v-c3a00e66="" stroke="#8A93A0" stroke-linejoin="round" d="M4.58 8.25V17h-1.4C2.53 17 2 16.382 2 15.624V9.735c0-.79.552-1.485 1.18-1.485h1.4zM11.322 2c1.011.019 1.614.833 1.823 1.235.382.735.392 1.946.13 2.724-.236.704-.785 1.629-.785 1.629h4.11c.434 0 .838.206 1.107.563.273.365.363.84.24 1.272l-1.86 6.513A1.425 1.425 0 0 1 14.724 17H6.645V7.898C8.502 7.51 9.643 4.59 9.852 3.249A1.47 1.47 0 0 1 11.322 2z"></path></g></svg><!----></div><div data-v-c3a00e66="" class="comment-action action"><svg data-v-c3a00e66="" aria-hidden="true" width="16" height="16" viewBox="0 0 20 20" class="icon comment-icon"><g data-v-c3a00e66="" fill="none" fill-rule="evenodd"><path data-v-c3a00e66="" d="M0 0h20v20H0z"></path> <path data-v-c3a00e66="" stroke="#8A93A0" stroke-linejoin="round" d="M10 17c-4.142 0-7.5-2.91-7.5-6.5S5.858 4 10 4c4.142 0 7.5 2.91 7.5 6.5 0 1.416-.522 2.726-1.41 3.794-.129.156.41 3.206.41 3.206l-3.265-1.134c-.998.369-2.077.634-3.235.634z"></path></g></svg> <span data-v-c3a00e66="" class="action-title">回复</span></div></div></div><!----><div data-v-39f2ce6a="" data-v-c3a00e66="" class="sub-comment-list sub-comment-list"><!----></div></div><!----></div></div><div data-v-1d85495c="" class="item"><div data-v-c3a00e66="" data-v-1d85495c="" class="comment comment"><div data-v-0f4ef93c="" data-v-c3a00e66="" st:block="userPopover" st:state="57da88bb128fe10064b68758" class="user-popover-box popover"><!----><a data-v-c3a00e66="" href="/user/57da88bb128fe10064b68758" target="_blank" rel="" class="user-link" data-v-0f4ef93c=""><div data-v-292b3648="" data-v-11331c20="" data-v-c3a00e66="" data-src="https://user-gold-cdn.xitu.io/2016/11/29/98c5e8d39e34c96ed03af62e8a41986f?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1" class="lazy avatar avatar loaded" style="background-image: url(&quot;https://user-gold-cdn.xitu.io/2016/11/29/98c5e8d39e34c96ed03af62e8a41986f?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1&quot;);"></div></a></div><div data-v-c3a00e66="" class="content-box comment-divider-line"><div data-v-c3a00e66="" class="meta-box"><div data-v-0f4ef93c="" data-v-c3a00e66="" st:block="userPopover" st:state="57da88bb128fe10064b68758" class="user-popover-box"><!----><a data-v-44e95489="" data-v-c3a00e66="" href="/user/57da88bb128fe10064b68758" target="_blank" rel="" class="username username ellipsis" data-v-0f4ef93c="">Seirios<!----></a></div><div data-v-c3a00e66="" class="position"></div></div><div data-v-c3a00e66="" class="content">大佬。这文章可以。很强。图画的有点好看的。+10086</div><div data-v-c3a00e66="" class="limit-ctl-box"><!----><!----></div><!----><div data-v-c3a00e66="" class="reply-stat"><time data-v-c3a00e66="" datetime="2020-03-27T05:56:51.688Z" title="Fri Mar 27 2020 13:56:51 GMT+0800 (中国标准时间)" class="time">9天前</time><div data-v-c3a00e66="" class="delete"> &nbsp;·&nbsp;删除</div><div data-v-c3a00e66="" class="action-box"><div data-v-c3a00e66="" class="like-action action"><svg data-v-c3a00e66="" aria-hidden="true" width="16" height="16" viewBox="0 0 20 20" class="icon like-icon"><g data-v-c3a00e66="" fill="none" fill-rule="evenodd"><path data-v-c3a00e66="" d="M0 0h20v20H0z"></path> <path data-v-c3a00e66="" stroke="#8A93A0" stroke-linejoin="round" d="M4.58 8.25V17h-1.4C2.53 17 2 16.382 2 15.624V9.735c0-.79.552-1.485 1.18-1.485h1.4zM11.322 2c1.011.019 1.614.833 1.823 1.235.382.735.392 1.946.13 2.724-.236.704-.785 1.629-.785 1.629h4.11c.434 0 .838.206 1.107.563.273.365.363.84.24 1.272l-1.86 6.513A1.425 1.425 0 0 1 14.724 17H6.645V7.898C8.502 7.51 9.643 4.59 9.852 3.249A1.47 1.47 0 0 1 11.322 2z"></path></g></svg><!----></div><div data-v-c3a00e66="" class="comment-action action"><svg data-v-c3a00e66="" aria-hidden="true" width="16" height="16" viewBox="0 0 20 20" class="icon comment-icon"><g data-v-c3a00e66="" fill="none" fill-rule="evenodd"><path data-v-c3a00e66="" d="M0 0h20v20H0z"></path> <path data-v-c3a00e66="" stroke="#8A93A0" stroke-linejoin="round" d="M10 17c-4.142 0-7.5-2.91-7.5-6.5S5.858 4 10 4c4.142 0 7.5 2.91 7.5 6.5 0 1.416-.522 2.726-1.41 3.794-.129.156.41 3.206.41 3.206l-3.265-1.134c-.998.369-2.077.634-3.235.634z"></path></g></svg> <span data-v-c3a00e66="" class="action-title">回复</span></div></div></div><!----><div data-v-39f2ce6a="" data-v-c3a00e66="" class="sub-comment-list sub-comment-list"><!----></div></div><!----></div></div><div data-v-1d85495c="" class="item"><div data-v-c3a00e66="" data-v-1d85495c="" class="comment comment"><div data-v-0f4ef93c="" data-v-c3a00e66="" st:block="userPopover" st:state="5dca46986fb9a04a6076bc65" class="user-popover-box popover"><!----><a data-v-c3a00e66="" href="/user/5dca46986fb9a04a6076bc65" target="_blank" rel="" class="user-link" data-v-0f4ef93c=""><div data-v-292b3648="" data-v-11331c20="" data-v-c3a00e66="" data-src="https://mirror-gold-cdn.xitu.io/16e5e23ccc514b6456a?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1" class="lazy avatar avatar loaded" style="background-image: url(&quot;https://mirror-gold-cdn.xitu.io/16e5e23ccc514b6456a?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1&quot;);"></div></a></div><div data-v-c3a00e66="" class="content-box comment-divider-line"><div data-v-c3a00e66="" class="meta-box"><div data-v-0f4ef93c="" data-v-c3a00e66="" st:block="userPopover" st:state="5dca46986fb9a04a6076bc65" class="user-popover-box"><!----><a data-v-44e95489="" data-v-c3a00e66="" href="/user/5dca46986fb9a04a6076bc65" target="_blank" rel="" class="username username ellipsis" data-v-0f4ef93c="">SuperGao110<!----></a></div><div data-v-c3a00e66="" class="position"></div></div><div data-v-c3a00e66="" class="content">牛逼<img class="emoji" draggable="false" alt="👍" src="https://gold-cdn.xitu.io/asset/twemoji/2.6.0/svg/1f44d.svg"></div><div data-v-c3a00e66="" class="limit-ctl-box"><!----><!----></div><!----><div data-v-c3a00e66="" class="reply-stat"><time data-v-c3a00e66="" datetime="2020-03-27T02:18:00.914Z" title="Fri Mar 27 2020 10:18:00 GMT+0800 (中国标准时间)" class="time">9天前</time><div data-v-c3a00e66="" class="delete"> &nbsp;·&nbsp;删除</div><div data-v-c3a00e66="" class="action-box"><div data-v-c3a00e66="" class="like-action action"><svg data-v-c3a00e66="" aria-hidden="true" width="16" height="16" viewBox="0 0 20 20" class="icon like-icon"><g data-v-c3a00e66="" fill="none" fill-rule="evenodd"><path data-v-c3a00e66="" d="M0 0h20v20H0z"></path> <path data-v-c3a00e66="" stroke="#8A93A0" stroke-linejoin="round" d="M4.58 8.25V17h-1.4C2.53 17 2 16.382 2 15.624V9.735c0-.79.552-1.485 1.18-1.485h1.4zM11.322 2c1.011.019 1.614.833 1.823 1.235.382.735.392 1.946.13 2.724-.236.704-.785 1.629-.785 1.629h4.11c.434 0 .838.206 1.107.563.273.365.363.84.24 1.272l-1.86 6.513A1.425 1.425 0 0 1 14.724 17H6.645V7.898C8.502 7.51 9.643 4.59 9.852 3.249A1.47 1.47 0 0 1 11.322 2z"></path></g></svg><!----></div><div data-v-c3a00e66="" class="comment-action action"><svg data-v-c3a00e66="" aria-hidden="true" width="16" height="16" viewBox="0 0 20 20" class="icon comment-icon"><g data-v-c3a00e66="" fill="none" fill-rule="evenodd"><path data-v-c3a00e66="" d="M0 0h20v20H0z"></path> <path data-v-c3a00e66="" stroke="#8A93A0" stroke-linejoin="round" d="M10 17c-4.142 0-7.5-2.91-7.5-6.5S5.858 4 10 4c4.142 0 7.5 2.91 7.5 6.5 0 1.416-.522 2.726-1.41 3.794-.129.156.41 3.206.41 3.206l-3.265-1.134c-.998.369-2.077.634-3.235.634z"></path></g></svg> <span data-v-c3a00e66="" class="action-title">回复</span></div></div></div><!----><div data-v-39f2ce6a="" data-v-c3a00e66="" class="sub-comment-list sub-comment-list"><!----></div></div><!----></div></div><div data-v-1d85495c="" class="item"><div data-v-c3a00e66="" data-v-1d85495c="" class="comment comment"><div data-v-0f4ef93c="" data-v-c3a00e66="" st:block="userPopover" st:state="595af13af265da6c3f70ac9a" class="user-popover-box popover"><!----><a data-v-c3a00e66="" href="/user/595af13af265da6c3f70ac9a" target="_blank" rel="" class="user-link" data-v-0f4ef93c=""><div data-v-292b3648="" data-v-11331c20="" data-v-c3a00e66="" data-src="https://user-gold-cdn.xitu.io/2017/10/31/5a261e6242827fbf75789601810a74e4?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1" class="lazy avatar avatar loaded" style="background-image: url(&quot;https://user-gold-cdn.xitu.io/2017/10/31/5a261e6242827fbf75789601810a74e4?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1&quot;);"></div></a></div><div data-v-c3a00e66="" class="content-box comment-divider-line"><div data-v-c3a00e66="" class="meta-box"><div data-v-0f4ef93c="" data-v-c3a00e66="" st:block="userPopover" st:state="595af13af265da6c3f70ac9a" class="user-popover-box"><!----><a data-v-44e95489="" data-v-c3a00e66="" href="/user/595af13af265da6c3f70ac9a" target="_blank" rel="" class="username username ellipsis" data-v-0f4ef93c="">DonFisher<a data-v-00e1e43c="" data-v-44e95489="" href="/book/5c90640c5188252d7941f5bb/section/5c9065385188252da6320022" target="_blank" rel="" class="rank"><img data-v-00e1e43c="" src="https://b-gold-cdn.xitu.io/v3/static/img/lv-1.636691c.svg" alt="lv-1"></a></a></div><div data-v-c3a00e66="" class="position">软件开发</div></div><div data-v-c3a00e66="" class="content">总结的很好<img class="emoji" draggable="false" alt="👋" src="https://gold-cdn.xitu.io/asset/twemoji/2.6.0/svg/1f44b.svg"></div><div data-v-c3a00e66="" class="limit-ctl-box"><!----><!----></div><!----><div data-v-c3a00e66="" class="reply-stat"><time data-v-c3a00e66="" datetime="2020-03-27T02:00:22.664Z" title="Fri Mar 27 2020 10:00:22 GMT+0800 (中国标准时间)" class="time">9天前</time><div data-v-c3a00e66="" class="delete"> &nbsp;·&nbsp;删除</div><div data-v-c3a00e66="" class="action-box"><div data-v-c3a00e66="" class="like-action action"><svg data-v-c3a00e66="" aria-hidden="true" width="16" height="16" viewBox="0 0 20 20" class="icon like-icon"><g data-v-c3a00e66="" fill="none" fill-rule="evenodd"><path data-v-c3a00e66="" d="M0 0h20v20H0z"></path> <path data-v-c3a00e66="" stroke="#8A93A0" stroke-linejoin="round" d="M4.58 8.25V17h-1.4C2.53 17 2 16.382 2 15.624V9.735c0-.79.552-1.485 1.18-1.485h1.4zM11.322 2c1.011.019 1.614.833 1.823 1.235.382.735.392 1.946.13 2.724-.236.704-.785 1.629-.785 1.629h4.11c.434 0 .838.206 1.107.563.273.365.363.84.24 1.272l-1.86 6.513A1.425 1.425 0 0 1 14.724 17H6.645V7.898C8.502 7.51 9.643 4.59 9.852 3.249A1.47 1.47 0 0 1 11.322 2z"></path></g></svg><!----></div><div data-v-c3a00e66="" class="comment-action action"><svg data-v-c3a00e66="" aria-hidden="true" width="16" height="16" viewBox="0 0 20 20" class="icon comment-icon"><g data-v-c3a00e66="" fill="none" fill-rule="evenodd"><path data-v-c3a00e66="" d="M0 0h20v20H0z"></path> <path data-v-c3a00e66="" stroke="#8A93A0" stroke-linejoin="round" d="M10 17c-4.142 0-7.5-2.91-7.5-6.5S5.858 4 10 4c4.142 0 7.5 2.91 7.5 6.5 0 1.416-.522 2.726-1.41 3.794-.129.156.41 3.206.41 3.206l-3.265-1.134c-.998.369-2.077.634-3.235.634z"></path></g></svg> <span data-v-c3a00e66="" class="action-title">回复</span></div></div></div><!----><div data-v-39f2ce6a="" data-v-c3a00e66="" class="sub-comment-list sub-comment-list"><!----></div></div><!----></div></div></div><div data-v-4b46f152="" class="fetch-more-comment">查看更多 &gt;</div></div></div><!----><div data-v-7407bc26="" data-v-23c7d456="" st:block="recommended" class="main-area recommended-area shadow"><div data-v-7407bc26="" data-v-23c7d456="" class="recommended-entry-list-title">相关推荐</div><!----><ul data-v-158dab7e="" data-v-7407bc26="" st:block="entryList" class="entry-list recommended-entry-list" data-v-23c7d456=""><!----><li data-v-158dab7e="" data-growing-container="true" data-growing-title="entryList" class="item"><div data-v-45a8407d="" data-v-158dab7e="" class="entry-box"><div data-v-2d360bea="" data-v-45a8407d="" st:block="entry" st:state="5e85aab6e51d45470652ed48|1" class="entry"><a data-v-2d360bea="" href="/post/5e85a933e51d45470245efaf" target="_blank" rel="" st:name="link" class="entry-link"><div data-v-2d360bea="" class="content-box"><div data-v-2d360bea="" class="info-box"><div data-v-2d360bea="" class="info-row meta-row"><ul data-v-2d360bea="" class="meta-list"><!----><!----><li data-v-2d360bea="" class="item post">专栏</li><li data-v-2d360bea="" class="item username clickable"><div data-v-0f4ef93c="" data-v-2d360bea="" st:block="userPopover" st:state="5d4bdc04f265da039519df90" class="user-popover-box"><!----><a data-v-2d360bea="" href="/user/5d4bdc04f265da039519df90" target="_blank" rel="" st:name="user" st:state="5d4bdc04f265da039519df90" data-v-0f4ef93c="">程序员追风</a></div></li><li data-v-2d360bea="" class="item">3天前</li><li data-v-2d360bea="" class="item tag"><a data-v-2d360bea="" href="/tag/Redis" target="_blank" rel="" st:name="tag" st:state="555e9ab1e4b00c57d99560b5" class="tag">Redis</a><a data-v-2d360bea="" href="/tag/Java" target="_blank" rel="" st:name="tag" st:state="559a7207e4b08a686d25703e" class="tag">Java</a></li><!----></ul></div><div data-v-2d360bea="" class="info-row title-row"><!----><!----><a data-v-2d360bea="" href="/post/5e85a933e51d45470245efaf" target="_blank" rel="" st:name="title" class="title">从阿里、腾讯的面试真题中总结了这11个Redis高频面试题</a></div><div data-v-2d360bea="" class="info-row action-row"><ul data-v-2d360bea="" class="action-list"><li data-v-2d360bea="" st:name="likeBtn" class="item like clickable"><a data-v-2d360bea="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-2d360bea="" class="count">119</span></a></li><li data-v-2d360bea="" st:name="commentBtn" class="item comment clickable"><a data-v-2d360bea="" href="/post/5e85a933e51d45470245efaf#comment" target="_blank" rel="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.4d5744f.svg" class="icon"><!----></a></li><li data-v-2d360bea="" st:name="shareBtn" title="分享" class="item share clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/share.1d55e69.svg" class="icon"><div data-v-2d360bea="" class="share-panel"><div data-v-2d360bea="" st:name="shareItem" st:state="weibo" class="share-item weibo"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/weibo.8e2f5d6.svg" class="icon">微博</div><div data-v-2d360bea="" st:name="shareItem" st:state="wechat" class="share-item wechat"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/wechat.844402c.svg" class="icon">微信扫一扫<div data-v-2d360bea="" class="qr-code-box"><img data-v-2d360bea="" src="" class="qr-code"></div></div></div></li><li data-v-2d360bea="" title="收藏" st:name="collectBtn" class="item collect clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/collect.02e2979.svg" class="icon"><!----></li><!----></ul></div></div><!----></div></a></div></div></li><li data-v-158dab7e="" data-growing-container="true" data-growing-title="entryList" class="item"><div data-v-45a8407d="" data-v-158dab7e="" class="entry-box"><div data-v-2d360bea="" data-v-45a8407d="" st:block="entry" st:state="5e82949351882573793e674e|2" class="entry"><a data-v-2d360bea="" href="/post/5e81fd1ff265da47e84e5e2c" target="_blank" rel="" st:name="link" class="entry-link"><div data-v-2d360bea="" class="content-box"><div data-v-2d360bea="" class="info-box"><div data-v-2d360bea="" class="info-row meta-row"><ul data-v-2d360bea="" class="meta-list"><!----><!----><li data-v-2d360bea="" class="item post">专栏</li><li data-v-2d360bea="" class="item username clickable"><div data-v-0f4ef93c="" data-v-2d360bea="" st:block="userPopover" st:state="5cf7c1d7f265da1bc07e28b7" class="user-popover-box"><!----><a data-v-2d360bea="" href="/user/5cf7c1d7f265da1bc07e28b7" target="_blank" rel="" st:name="user" st:state="5cf7c1d7f265da1bc07e28b7" data-v-0f4ef93c="">MacroZheng</a></div></li><li data-v-2d360bea="" class="item">5天前</li><li data-v-2d360bea="" class="item tag"><a data-v-2d360bea="" href="/tag/Redis" target="_blank" rel="" st:name="tag" st:state="555e9ab1e4b00c57d99560b5" class="tag">Redis</a><a data-v-2d360bea="" href="/tag/Java" target="_blank" rel="" st:name="tag" st:state="559a7207e4b08a686d25703e" class="tag">Java</a></li><!----></ul></div><div data-v-2d360bea="" class="info-row title-row"><!----><!----><a data-v-2d360bea="" href="/post/5e81fd1ff265da47e84e5e2c" target="_blank" rel="" st:name="title" class="title">Docker环境下秒建Redis集群,连SpringBoot也整上了!</a></div><div data-v-2d360bea="" class="info-row action-row"><ul data-v-2d360bea="" class="action-list"><li data-v-2d360bea="" st:name="likeBtn" class="item like clickable"><a data-v-2d360bea="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-2d360bea="" class="count">40</span></a></li><li data-v-2d360bea="" st:name="commentBtn" class="item comment clickable"><a data-v-2d360bea="" href="/post/5e81fd1ff265da47e84e5e2c#comment" target="_blank" rel="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.4d5744f.svg" class="icon"><span data-v-2d360bea="" class="count">3</span></a></li><li data-v-2d360bea="" st:name="shareBtn" title="分享" class="item share clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/share.1d55e69.svg" class="icon"><div data-v-2d360bea="" class="share-panel"><div data-v-2d360bea="" st:name="shareItem" st:state="weibo" class="share-item weibo"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/weibo.8e2f5d6.svg" class="icon">微博</div><div data-v-2d360bea="" st:name="shareItem" st:state="wechat" class="share-item wechat"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/wechat.844402c.svg" class="icon">微信扫一扫<div data-v-2d360bea="" class="qr-code-box"><img data-v-2d360bea="" src="" class="qr-code"></div></div></div></li><li data-v-2d360bea="" title="收藏" st:name="collectBtn" class="item collect clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/collect.02e2979.svg" class="icon"><!----></li><!----></ul></div></div><div data-v-292b3648="" data-v-4d895a49="" data-v-2d360bea="" data-src="https://user-gold-cdn.xitu.io/2020/3/30/1712bc5b6aa154ad?imageView2/1/w/120/h/120/q/85/format/webp/interlace/1" class="lazy thumb thumb loaded" style="background-image: url(&quot;https://user-gold-cdn.xitu.io/2020/3/30/1712bc5b6aa154ad?imageView2/1/w/120/h/120/q/85/format/webp/interlace/1&quot;); background-size: cover;"></div></div></a></div></div></li><li data-v-158dab7e="" data-growing-container="true" data-growing-title="entryList" class="item"><div data-v-45a8407d="" data-v-158dab7e="" class="entry-box"><div data-v-2d360bea="" data-v-45a8407d="" st:block="entry" st:state="5e7b43ab6fb9a07cde650099|3" class="entry"><a data-v-2d360bea="" href="/post/5e7b43945188255dda23d1e3" target="_blank" rel="" st:name="link" class="entry-link"><div data-v-2d360bea="" class="content-box"><div data-v-2d360bea="" class="info-box"><div data-v-2d360bea="" class="info-row meta-row"><ul data-v-2d360bea="" class="meta-list"><!----><!----><li data-v-2d360bea="" class="item post">专栏</li><li data-v-2d360bea="" class="item username clickable"><div data-v-0f4ef93c="" data-v-2d360bea="" st:block="userPopover" st:state="5cfb61a36fb9a07ef819ef3a" class="user-popover-box"><!----><a data-v-2d360bea="" href="/user/5cfb61a36fb9a07ef819ef3a" target="_blank" rel="" st:name="user" st:state="5cfb61a36fb9a07ef819ef3a" data-v-0f4ef93c="">我没有三颗心脏</a></div></li><li data-v-2d360bea="" class="item">10天前</li><li data-v-2d360bea="" class="item tag"><a data-v-2d360bea="" href="/tag/Redis" target="_blank" rel="" st:name="tag" st:state="555e9ab1e4b00c57d99560b5" class="tag">Redis</a></li><!----></ul></div><div data-v-2d360bea="" class="info-row title-row"><!----><!----><a data-v-2d360bea="" href="/post/5e7b43945188255dda23d1e3" target="_blank" rel="" st:name="title" class="title">妈妈再也不担心我面试被Redis问得脸都绿了</a></div><div data-v-2d360bea="" class="info-row action-row"><ul data-v-2d360bea="" class="action-list"><li data-v-2d360bea="" st:name="likeBtn" class="item like clickable"><a data-v-2d360bea="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-2d360bea="" class="count">54</span></a></li><li data-v-2d360bea="" st:name="commentBtn" class="item comment clickable"><a data-v-2d360bea="" href="/post/5e7b43945188255dda23d1e3#comment" target="_blank" rel="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.4d5744f.svg" class="icon"><span data-v-2d360bea="" class="count">8</span></a></li><li data-v-2d360bea="" st:name="shareBtn" title="分享" class="item share clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/share.1d55e69.svg" class="icon"><div data-v-2d360bea="" class="share-panel"><div data-v-2d360bea="" st:name="shareItem" st:state="weibo" class="share-item weibo"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/weibo.8e2f5d6.svg" class="icon">微博</div><div data-v-2d360bea="" st:name="shareItem" st:state="wechat" class="share-item wechat"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/wechat.844402c.svg" class="icon">微信扫一扫<div data-v-2d360bea="" class="qr-code-box"><img data-v-2d360bea="" src="" class="qr-code"></div></div></div></li><li data-v-2d360bea="" title="收藏" st:name="collectBtn" class="item collect clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/collect.02e2979.svg" class="icon"><!----></li><!----></ul></div></div><!----></div></a></div></div></li><!----><li data-v-158dab7e="" data-growing-container="true" data-growing-title="entryList" class="item"><div data-v-45a8407d="" data-v-158dab7e="" class="entry-box"><div data-v-2d360bea="" data-v-45a8407d="" st:block="entry" st:state="5e8849bbe51d4546f03d895b|4" class="entry"><a data-v-2d360bea="" href="/post/5e88314351882573b627e6a9" target="_blank" rel="" st:name="link" class="entry-link"><div data-v-2d360bea="" class="content-box"><div data-v-2d360bea="" class="info-box"><div data-v-2d360bea="" class="info-row meta-row"><ul data-v-2d360bea="" class="meta-list"><!----><!----><li data-v-2d360bea="" class="item post">专栏</li><li data-v-2d360bea="" class="item username clickable"><div data-v-0f4ef93c="" data-v-2d360bea="" st:block="userPopover" st:state="57f490a90e3dd900579e302c" class="user-popover-box"><!----><a data-v-2d360bea="" href="/user/57f490a90e3dd900579e302c" target="_blank" rel="" st:name="user" st:state="57f490a90e3dd900579e302c" data-v-0f4ef93c="">_天道酬勤_</a></div></li><li data-v-2d360bea="" class="item">1天前</li><li data-v-2d360bea="" class="item tag"><a data-v-2d360bea="" href="/tag/Redis" target="_blank" rel="" st:name="tag" st:state="555e9ab1e4b00c57d99560b5" class="tag">Redis</a></li><!----></ul></div><div data-v-2d360bea="" class="info-row title-row"><!----><!----><a data-v-2d360bea="" href="/post/5e88314351882573b627e6a9" target="_blank" rel="" st:name="title" class="title">Redis 地理空间(geospatial)介绍及应用</a></div><div data-v-2d360bea="" class="info-row action-row"><ul data-v-2d360bea="" class="action-list"><li data-v-2d360bea="" st:name="likeBtn" class="item like clickable"><a data-v-2d360bea="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-2d360bea="" class="count">2</span></a></li><li data-v-2d360bea="" st:name="commentBtn" class="item comment clickable"><a data-v-2d360bea="" href="/post/5e88314351882573b627e6a9#comment" target="_blank" rel="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.4d5744f.svg" class="icon"><!----></a></li><li data-v-2d360bea="" st:name="shareBtn" title="分享" class="item share clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/share.1d55e69.svg" class="icon"><div data-v-2d360bea="" class="share-panel"><div data-v-2d360bea="" st:name="shareItem" st:state="weibo" class="share-item weibo"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/weibo.8e2f5d6.svg" class="icon">微博</div><div data-v-2d360bea="" st:name="shareItem" st:state="wechat" class="share-item wechat"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/wechat.844402c.svg" class="icon">微信扫一扫<div data-v-2d360bea="" class="qr-code-box"><img data-v-2d360bea="" src="" class="qr-code"></div></div></div></li><li data-v-2d360bea="" title="收藏" st:name="collectBtn" class="item collect clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/collect.02e2979.svg" class="icon"><!----></li><!----></ul></div></div><!----></div></a></div></div></li><li data-v-158dab7e="" data-growing-container="true" data-growing-title="entryList" class="item"><div data-v-45a8407d="" data-v-158dab7e="" class="entry-box"><div data-v-2d360bea="" data-v-45a8407d="" st:block="entry" st:state="5e7970d7f265da570f5053ad|5" class="entry"><a data-v-2d360bea="" href="/post/5e79702af265da570c75580a" target="_blank" rel="" st:name="link" class="entry-link"><div data-v-2d360bea="" class="content-box"><div data-v-2d360bea="" class="info-box"><div data-v-2d360bea="" class="info-row meta-row"><ul data-v-2d360bea="" class="meta-list"><!----><!----><li data-v-2d360bea="" class="item post">专栏</li><li data-v-2d360bea="" class="item username clickable"><div data-v-0f4ef93c="" data-v-2d360bea="" st:block="userPopover" st:state="5a62ee8af265da3e290c4aa4" class="user-popover-box"><!----><a data-v-2d360bea="" href="/user/5a62ee8af265da3e290c4aa4" target="_blank" rel="" st:name="user" st:state="5a62ee8af265da3e290c4aa4" data-v-0f4ef93c="">老王_Java中文社群</a></div></li><li data-v-2d360bea="" class="item">12天前</li><li data-v-2d360bea="" class="item tag"><a data-v-2d360bea="" href="/tag/Redis" target="_blank" rel="" st:name="tag" st:state="555e9ab1e4b00c57d99560b5" class="tag">Redis</a><a data-v-2d360bea="" href="/tag/Java" target="_blank" rel="" st:name="tag" st:state="559a7207e4b08a686d25703e" class="tag">Java</a></li><!----></ul></div><div data-v-2d360bea="" class="info-row title-row"><!----><!----><a data-v-2d360bea="" href="/post/5e79702af265da570c75580a" target="_blank" rel="" st:name="title" class="title">《吐血整理》Redis 性能优化的 13 条军规!史上最全</a></div><div data-v-2d360bea="" class="info-row action-row"><ul data-v-2d360bea="" class="action-list"><li data-v-2d360bea="" st:name="likeBtn" class="item like clickable"><a data-v-2d360bea="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-2d360bea="" class="count">53</span></a></li><li data-v-2d360bea="" st:name="commentBtn" class="item comment clickable"><a data-v-2d360bea="" href="/post/5e79702af265da570c75580a#comment" target="_blank" rel="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.4d5744f.svg" class="icon"><span data-v-2d360bea="" class="count">3</span></a></li><li data-v-2d360bea="" st:name="shareBtn" title="分享" class="item share clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/share.1d55e69.svg" class="icon"><div data-v-2d360bea="" class="share-panel"><div data-v-2d360bea="" st:name="shareItem" st:state="weibo" class="share-item weibo"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/weibo.8e2f5d6.svg" class="icon">微博</div><div data-v-2d360bea="" st:name="shareItem" st:state="wechat" class="share-item wechat"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/wechat.844402c.svg" class="icon">微信扫一扫<div data-v-2d360bea="" class="qr-code-box"><img data-v-2d360bea="" src="" class="qr-code"></div></div></div></li><li data-v-2d360bea="" title="收藏" st:name="collectBtn" class="item collect clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/collect.02e2979.svg" class="icon"><!----></li><!----></ul></div></div><div data-v-292b3648="" data-v-4d895a49="" data-v-2d360bea="" data-src="https://user-gold-cdn.xitu.io/2020/3/24/1710a6c1e84190c7?imageView2/1/w/120/h/120/q/85/format/webp/interlace/1" class="lazy thumb thumb loaded" style="background-image: url(&quot;https://user-gold-cdn.xitu.io/2020/3/24/1710a6c1e84190c7?imageView2/1/w/120/h/120/q/85/format/webp/interlace/1&quot;); background-size: cover;"></div></div></a></div></div></li><!----><!----><li data-v-158dab7e="" data-growing-container="true" data-growing-title="entryList" class="item"><div data-v-45a8407d="" data-v-158dab7e="" class="entry-box"><div data-v-2d360bea="" data-v-45a8407d="" st:block="entry" st:state="5e84abff6fb9a03c8c04046c|4" class="entry"><a data-v-2d360bea="" href="/post/5e84abc66fb9a03c6422fb19" target="_blank" rel="" st:name="link" class="entry-link"><div data-v-2d360bea="" class="content-box"><div data-v-2d360bea="" class="info-box"><div data-v-2d360bea="" class="info-row meta-row"><ul data-v-2d360bea="" class="meta-list"><!----><!----><li data-v-2d360bea="" class="item post">专栏</li><li data-v-2d360bea="" class="item username clickable"><div data-v-0f4ef93c="" data-v-2d360bea="" st:block="userPopover" st:state="5b7a29afe51d453890058b7f" class="user-popover-box"><!----><a data-v-2d360bea="" href="/user/5b7a29afe51d453890058b7f" target="_blank" rel="" st:name="user" st:state="5b7a29afe51d453890058b7f" data-v-0f4ef93c="">面向Google编程</a></div></li><li data-v-2d360bea="" class="item">3天前</li><li data-v-2d360bea="" class="item tag"><a data-v-2d360bea="" href="/tag/Redis" target="_blank" rel="" st:name="tag" st:state="555e9ab1e4b00c57d99560b5" class="tag">Redis</a></li><!----></ul></div><div data-v-2d360bea="" class="info-row title-row"><!----><!----><a data-v-2d360bea="" href="/post/5e84abc66fb9a03c6422fb19" target="_blank" rel="" st:name="title" class="title">走近源码:Redis如何清除过期key</a></div><div data-v-2d360bea="" class="info-row action-row"><ul data-v-2d360bea="" class="action-list"><li data-v-2d360bea="" st:name="likeBtn" class="item like clickable"><a data-v-2d360bea="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-2d360bea="" class="count">3</span></a></li><li data-v-2d360bea="" st:name="commentBtn" class="item comment clickable"><a data-v-2d360bea="" href="/post/5e84abc66fb9a03c6422fb19#comment" target="_blank" rel="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.4d5744f.svg" class="icon"><!----></a></li><li data-v-2d360bea="" st:name="shareBtn" title="分享" class="item share clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/share.1d55e69.svg" class="icon"><div data-v-2d360bea="" class="share-panel"><div data-v-2d360bea="" st:name="shareItem" st:state="weibo" class="share-item weibo"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/weibo.8e2f5d6.svg" class="icon">微博</div><div data-v-2d360bea="" st:name="shareItem" st:state="wechat" class="share-item wechat"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/wechat.844402c.svg" class="icon">微信扫一扫<div data-v-2d360bea="" class="qr-code-box"><img data-v-2d360bea="" src="" class="qr-code"></div></div></div></li><li data-v-2d360bea="" title="收藏" st:name="collectBtn" class="item collect clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/collect.02e2979.svg" class="icon"><!----></li><!----></ul></div></div><div data-v-292b3648="" data-v-4d895a49="" data-v-2d360bea="" data-src="https://user-gold-cdn.xitu.io/2020/4/1/171363f839f32748?imageView2/1/w/120/h/120/q/85/format/webp/interlace/1" class="lazy thumb thumb loaded" style="background-image: url(&quot;https://user-gold-cdn.xitu.io/2020/4/1/171363f839f32748?imageView2/1/w/120/h/120/q/85/format/webp/interlace/1&quot;); background-size: cover;"></div></div></a></div></div></li><li data-v-158dab7e="" data-growing-container="true" data-growing-title="entryList" class="item"><div data-v-45a8407d="" data-v-158dab7e="" class="entry-box"><div data-v-2d360bea="" data-v-45a8407d="" st:block="entry" st:state="5e7aeb72f265da57213f28a3|5" class="entry"><a data-v-2d360bea="" href="/post/5e7ae9635188255dd461f066" target="_blank" rel="" st:name="link" class="entry-link"><div data-v-2d360bea="" class="content-box"><div data-v-2d360bea="" class="info-box"><div data-v-2d360bea="" class="info-row meta-row"><ul data-v-2d360bea="" class="meta-list"><!----><!----><li data-v-2d360bea="" class="item post">专栏</li><li data-v-2d360bea="" class="item username clickable"><div data-v-0f4ef93c="" data-v-2d360bea="" st:block="userPopover" st:state="595210b85188250d9745f7a8" class="user-popover-box"><!----><a data-v-2d360bea="" href="/user/595210b85188250d9745f7a8" target="_blank" rel="" st:name="user" st:state="595210b85188250d9745f7a8" data-v-0f4ef93c="">程序员内点事</a></div></li><li data-v-2d360bea="" class="item">11天前</li><li data-v-2d360bea="" class="item tag"><a data-v-2d360bea="" href="/tag/Redis" target="_blank" rel="" st:name="tag" st:state="555e9ab1e4b00c57d99560b5" class="tag">Redis</a></li><!----></ul></div><div data-v-2d360bea="" class="info-row title-row"><!----><!----><a data-v-2d360bea="" href="/post/5e7ae9635188255dd461f066" target="_blank" rel="" st:name="title" class="title">Redis数据结构及对应使用场景,看一次就整明白得了</a></div><div data-v-2d360bea="" class="info-row action-row"><ul data-v-2d360bea="" class="action-list"><li data-v-2d360bea="" st:name="likeBtn" class="item like clickable"><a data-v-2d360bea="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-2d360bea="" class="count">40</span></a></li><li data-v-2d360bea="" st:name="commentBtn" class="item comment clickable"><a data-v-2d360bea="" href="/post/5e7ae9635188255dd461f066#comment" target="_blank" rel="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.4d5744f.svg" class="icon"><span data-v-2d360bea="" class="count">1</span></a></li><li data-v-2d360bea="" st:name="shareBtn" title="分享" class="item share clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/share.1d55e69.svg" class="icon"><div data-v-2d360bea="" class="share-panel"><div data-v-2d360bea="" st:name="shareItem" st:state="weibo" class="share-item weibo"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/weibo.8e2f5d6.svg" class="icon">微博</div><div data-v-2d360bea="" st:name="shareItem" st:state="wechat" class="share-item wechat"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/wechat.844402c.svg" class="icon">微信扫一扫<div data-v-2d360bea="" class="qr-code-box"><img data-v-2d360bea="" src="" class="qr-code"></div></div></div></li><li data-v-2d360bea="" title="收藏" st:name="collectBtn" class="item collect clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/collect.02e2979.svg" class="icon"><!----></li><!----></ul></div></div><div data-v-292b3648="" data-v-4d895a49="" data-v-2d360bea="" data-src="https://user-gold-cdn.xitu.io/2020/3/25/1711029d1785998e?imageView2/1/w/120/h/120/q/85/format/webp/interlace/1" class="lazy thumb thumb loaded" style="background-image: url(&quot;https://user-gold-cdn.xitu.io/2020/3/25/1711029d1785998e?imageView2/1/w/120/h/120/q/85/format/webp/interlace/1&quot;); background-size: cover;"></div></div></a></div></div></li><li data-v-158dab7e="" data-growing-container="true" data-growing-title="entryList" class="item"><div data-v-45a8407d="" data-v-158dab7e="" class="entry-box"><div data-v-2d360bea="" data-v-45a8407d="" st:block="entry" st:state="5e7f526ae51d4546b90d057f|6" class="entry"><a data-v-2d360bea="" href="/post/5e7f3b13f265da7978136a31" target="_blank" rel="" st:name="link" class="entry-link"><div data-v-2d360bea="" class="content-box"><div data-v-2d360bea="" class="info-box"><div data-v-2d360bea="" class="info-row meta-row"><ul data-v-2d360bea="" class="meta-list"><!----><!----><li data-v-2d360bea="" class="item post">专栏</li><li data-v-2d360bea="" class="item username clickable"><div data-v-0f4ef93c="" data-v-2d360bea="" st:block="userPopover" st:state="5ddb26966fb9a07adf28ca7e" class="user-popover-box"><!----><a data-v-2d360bea="" href="/user/5ddb26966fb9a07adf28ca7e" target="_blank" rel="" st:name="user" st:state="5ddb26966fb9a07adf28ca7e" data-v-0f4ef93c="">南橘ryc</a></div></li><li data-v-2d360bea="" class="item">7天前</li><li data-v-2d360bea="" class="item tag"><a data-v-2d360bea="" href="/tag/Redis" target="_blank" rel="" st:name="tag" st:state="555e9ab1e4b00c57d99560b5" class="tag">Redis</a></li><!----></ul></div><div data-v-2d360bea="" class="info-row title-row"><!----><!----><a data-v-2d360bea="" href="/post/5e7f3b13f265da7978136a31" target="_blank" rel="" st:name="title" class="title">【进阶之路】Redis基础知识两篇就满足(二)</a></div><div data-v-2d360bea="" class="info-row action-row"><ul data-v-2d360bea="" class="action-list"><li data-v-2d360bea="" st:name="likeBtn" class="item like clickable"><a data-v-2d360bea="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-2d360bea="" class="count">20</span></a></li><li data-v-2d360bea="" st:name="commentBtn" class="item comment clickable"><a data-v-2d360bea="" href="/post/5e7f3b13f265da7978136a31#comment" target="_blank" rel="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.4d5744f.svg" class="icon"><span data-v-2d360bea="" class="count">6</span></a></li><li data-v-2d360bea="" st:name="shareBtn" title="分享" class="item share clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/share.1d55e69.svg" class="icon"><div data-v-2d360bea="" class="share-panel"><div data-v-2d360bea="" st:name="shareItem" st:state="weibo" class="share-item weibo"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/weibo.8e2f5d6.svg" class="icon">微博</div><div data-v-2d360bea="" st:name="shareItem" st:state="wechat" class="share-item wechat"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/wechat.844402c.svg" class="icon">微信扫一扫<div data-v-2d360bea="" class="qr-code-box"><img data-v-2d360bea="" src="" class="qr-code"></div></div></div></li><li data-v-2d360bea="" title="收藏" st:name="collectBtn" class="item collect clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/collect.02e2979.svg" class="icon"><!----></li><!----></ul></div></div><!----></div></a></div></div></li><li data-v-158dab7e="" data-growing-container="true" data-growing-title="entryList" class="item"><div data-v-45a8407d="" data-v-158dab7e="" class="entry-box"><div data-v-2d360bea="" data-v-45a8407d="" st:block="entry" st:state="5e7c0ee6f265da42f4494bbe|7" class="entry"><a data-v-2d360bea="" href="/post/5e7c0e79f265da42b71a039c" target="_blank" rel="" st:name="link" class="entry-link"><div data-v-2d360bea="" class="content-box"><div data-v-2d360bea="" class="info-box"><div data-v-2d360bea="" class="info-row meta-row"><ul data-v-2d360bea="" class="meta-list"><!----><!----><li data-v-2d360bea="" class="item post">专栏</li><li data-v-2d360bea="" class="item username clickable"><div data-v-0f4ef93c="" data-v-2d360bea="" st:block="userPopover" st:state="5a62ee8af265da3e290c4aa4" class="user-popover-box"><!----><a data-v-2d360bea="" href="/user/5a62ee8af265da3e290c4aa4" target="_blank" rel="" st:name="user" st:state="5a62ee8af265da3e290c4aa4" data-v-0f4ef93c="">老王_Java中文社群</a></div></li><li data-v-2d360bea="" class="item">10天前</li><li data-v-2d360bea="" class="item tag"><a data-v-2d360bea="" href="/tag/Redis" target="_blank" rel="" st:name="tag" st:state="555e9ab1e4b00c57d99560b5" class="tag">Redis</a><a data-v-2d360bea="" href="/tag/Java" target="_blank" rel="" st:name="tag" st:state="559a7207e4b08a686d25703e" class="tag">Java</a></li><!----></ul></div><div data-v-2d360bea="" class="info-row title-row"><!----><!----><a data-v-2d360bea="" href="/post/5e7c0e79f265da42b71a039c" target="_blank" rel="" st:name="title" class="title">惊呆了,竟然可以用这种方式秒建Redis集群?</a></div><div data-v-2d360bea="" class="info-row action-row"><ul data-v-2d360bea="" class="action-list"><li data-v-2d360bea="" st:name="likeBtn" class="item like clickable"><a data-v-2d360bea="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-2d360bea="" class="count">19</span></a></li><li data-v-2d360bea="" st:name="commentBtn" class="item comment clickable"><a data-v-2d360bea="" href="/post/5e7c0e79f265da42b71a039c#comment" target="_blank" rel="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.4d5744f.svg" class="icon"><span data-v-2d360bea="" class="count">3</span></a></li><li data-v-2d360bea="" st:name="shareBtn" title="分享" class="item share clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/share.1d55e69.svg" class="icon"><div data-v-2d360bea="" class="share-panel"><div data-v-2d360bea="" st:name="shareItem" st:state="weibo" class="share-item weibo"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/weibo.8e2f5d6.svg" class="icon">微博</div><div data-v-2d360bea="" st:name="shareItem" st:state="wechat" class="share-item wechat"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/wechat.844402c.svg" class="icon">微信扫一扫<div data-v-2d360bea="" class="qr-code-box"><img data-v-2d360bea="" src="" class="qr-code"></div></div></div></li><li data-v-2d360bea="" title="收藏" st:name="collectBtn" class="item collect clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/collect.02e2979.svg" class="icon"><!----></li><!----></ul></div></div><div data-v-292b3648="" data-v-4d895a49="" data-v-2d360bea="" data-src="https://user-gold-cdn.xitu.io/2020/3/26/17114997530ae789?imageView2/1/w/120/h/120/q/85/format/webp/interlace/1" class="lazy thumb thumb" style="background-image: none; background-size: cover;"></div></div></a></div></div></li><li data-v-158dab7e="" data-growing-container="true" data-growing-title="entryList" class="item"><div data-v-45a8407d="" data-v-158dab7e="" class="entry-box"><div data-v-2d360bea="" data-v-45a8407d="" st:block="entry" st:state="5e82f809f265da47f1449ee2|8" class="entry"><a data-v-2d360bea="" href="/post/5e82f77151882573793e683e" target="_blank" rel="" st:name="link" class="entry-link"><div data-v-2d360bea="" class="content-box"><div data-v-2d360bea="" class="info-box"><div data-v-2d360bea="" class="info-row meta-row"><ul data-v-2d360bea="" class="meta-list"><!----><!----><li data-v-2d360bea="" class="item post">专栏</li><li data-v-2d360bea="" class="item username clickable"><div data-v-0f4ef93c="" data-v-2d360bea="" st:block="userPopover" st:state="5e005a87f265da33c24ff9ce" class="user-popover-box"><!----><a data-v-2d360bea="" href="/user/5e005a87f265da33c24ff9ce" target="_blank" rel="" st:name="user" st:state="5e005a87f265da33c24ff9ce" data-v-0f4ef93c="">Java2B</a></div></li><li data-v-2d360bea="" class="item">5天前</li><li data-v-2d360bea="" class="item tag"><a data-v-2d360bea="" href="/tag/Redis" target="_blank" rel="" st:name="tag" st:state="555e9ab1e4b00c57d99560b5" class="tag">Redis</a></li><!----></ul></div><div data-v-2d360bea="" class="info-row title-row"><!----><!----><a data-v-2d360bea="" href="/post/5e82f77151882573793e683e" target="_blank" rel="" st:name="title" class="title">Redis面试题和答案整理</a></div><div data-v-2d360bea="" class="info-row action-row"><ul data-v-2d360bea="" class="action-list"><li data-v-2d360bea="" st:name="likeBtn" class="item like clickable"><a data-v-2d360bea="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-2d360bea="" class="count">8</span></a></li><li data-v-2d360bea="" st:name="commentBtn" class="item comment clickable"><a data-v-2d360bea="" href="/post/5e82f77151882573793e683e#comment" target="_blank" rel="" class="title-box"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.4d5744f.svg" class="icon"><!----></a></li><li data-v-2d360bea="" st:name="shareBtn" title="分享" class="item share clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/share.1d55e69.svg" class="icon"><div data-v-2d360bea="" class="share-panel"><div data-v-2d360bea="" st:name="shareItem" st:state="weibo" class="share-item weibo"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/weibo.8e2f5d6.svg" class="icon">微博</div><div data-v-2d360bea="" st:name="shareItem" st:state="wechat" class="share-item wechat"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/wechat.844402c.svg" class="icon">微信扫一扫<div data-v-2d360bea="" class="qr-code-box"><img data-v-2d360bea="" src="" class="qr-code"></div></div></div></li><li data-v-2d360bea="" title="收藏" st:name="collectBtn" class="item collect clickable hover"><img data-v-2d360bea="" src="https://b-gold-cdn.xitu.io/v3/static/img/collect.02e2979.svg" class="icon"><!----></li><!----></ul></div></div><!----></div></a></div></div></li><li data-v-158dab7e="" class="item"><!----></li><!----></ul></div><div data-v-7286dda2="" data-v-7407bc26="" st:block="sidebar" class="sidebar sidebar sticky" data-v-23c7d456=""><div data-v-200fbf1c="" data-v-625baef0="" data-v-7286dda2="" class="sidebar-block author-block shadow"><div data-v-200fbf1c="" class="block-title">关于作者</div><div data-v-200fbf1c="" class="block-body"><a data-v-625baef0="" href="/user/5cfb61a36fb9a07ef819ef3a" target="_blank" rel="" class="user-item item" data-v-200fbf1c=""><div data-v-292b3648="" data-v-11331c20="" data-v-625baef0="" data-src="https://user-gold-cdn.xitu.io/2019/6/8/16b35f5985473ab9?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1" class="lazy avatar avatar loaded" style="background-image: url(&quot;https://user-gold-cdn.xitu.io/2019/6/8/16b35f5985473ab9?imageView2/1/w/100/h/100/q/85/format/webp/interlace/1&quot;);"></div><div data-v-625baef0="" class="info-box"><a data-v-44e95489="" data-v-625baef0="" href="/user/5cfb61a36fb9a07ef819ef3a" target="_blank" rel="" class="username">我没有三颗心脏<a data-v-00e1e43c="" data-v-44e95489="" href="/book/5c90640c5188252d7941f5bb/section/5c9065385188252da6320022" target="_blank" rel="" class="rank"><img data-v-00e1e43c="" src="https://b-gold-cdn.xitu.io/v3/static/img/lv-2.f597b88.svg" alt="lv-2"></a></a><div data-v-625baef0="" title="后端开发" class="position">后端开发</div></div></a><div data-v-625baef0="" data-v-200fbf1c="" class="stat-item item"><svg data-v-625baef0="" data-v-200fbf1c="" xmlns="http://www.w3.org/2000/svg" width="25" height="26" viewBox="0 0 25 26" class="zan"><g data-v-625baef0="" data-v-200fbf1c="" fill="none" fill-rule="evenodd" transform="translate(0 .57)"><ellipse data-v-625baef0="" data-v-200fbf1c="" cx="12.5" cy="12.57" fill="#E1EFFF" rx="12.5" ry="12.57"></ellipse> <path data-v-625baef0="" data-v-200fbf1c="" fill="#7BB9FF" d="M8.596 11.238V19H7.033C6.463 19 6 18.465 6 17.807v-5.282c0-.685.483-1.287 1.033-1.287h1.563zm4.275-4.156A1.284 1.284 0 0 1 14.156 6c.885.016 1.412.722 1.595 1.07.334.638.343 1.687.114 2.361-.207.61-.687 1.412-.687 1.412h3.596c.38 0 .733.178.969.488.239.317.318.728.21 1.102l-1.628 5.645a1.245 1.245 0 0 1-1.192.922h-7.068v-7.889c1.624-.336 2.623-2.866 2.806-4.029z"></path></g></svg> <span data-v-625baef0="" data-v-200fbf1c="" class="content">获得点赞<span data-v-625baef0="" data-v-200fbf1c="" class="count">118</span></span></div><div data-v-625baef0="" data-v-200fbf1c="" class="stat-item item"><svg data-v-625baef0="" data-v-200fbf1c="" width="25" height="25" viewBox="0 0 25 25" class="icon stat-view-icon"><g data-v-625baef0="" data-v-200fbf1c="" fill="none" fill-rule="evenodd"><circle data-v-625baef0="" data-v-200fbf1c="" cx="12.5" cy="12.5" r="12.5" fill="#E1EFFF"></circle> <path data-v-625baef0="" data-v-200fbf1c="" fill="#7BB9FF" d="M4 12.5S6.917 7 12.75 7s8.75 5.5 8.75 5.5-2.917 5.5-8.75 5.5S4 12.5 4 12.5zm8.75 2.292c1.208 0 2.188-1.026 2.188-2.292 0-1.266-.98-2.292-2.188-2.292-1.208 0-2.188 1.026-2.188 2.292 0 1.266.98 2.292 2.188 2.292z"></path></g></svg> <span data-v-625baef0="" data-v-200fbf1c="" class="content">文章被阅读<span data-v-625baef0="" data-v-200fbf1c="" class="count">4,838</span></span></div><!----></div></div><ul data-v-7286dda2="" class="sidebar-bd-entry"><li data-v-7286dda2=""><a data-v-6e16b16c="" data-v-7286dda2="" href="https://juejin.im/e/aliyun" target="_blank" class="sidebar-entry shadow" style="background-image: url(&quot;https://user-gold-cdn.xitu.io/15849480575180830481212c4c99405eba9295942348c.jpg&quot;);"></a></li><li data-v-7286dda2=""><a data-v-6e16b16c="" data-v-7286dda2="" href="http://www.huodongxing.com/go/tl4" target="_blank" class="sidebar-entry shadow" style="background-image: url(&quot;https://user-gold-cdn.xitu.io/158529256559264b488419aa2dbcf69b2848dba5d021f.jpg&quot;);"></a></li></ul><div data-v-0582ae5d="" data-v-548ff166="" data-v-7286dda2="" class="index-book-collect" place="post" category="5562b419e4b00c57d9b94ae2"><div data-v-0582ae5d="" class="header"><div data-v-0582ae5d="" class="title">掘金小册</div><div data-v-0582ae5d="" class="controllers"><div data-v-0582ae5d="" class="arrow icon ion-chevron-left"></div><div data-v-0582ae5d="" class="arrow icon ion-chevron-right"></div></div></div><div data-v-0582ae5d="" class="slide-book transition--next"><div data-v-11979726="" data-v-0582ae5d="" class="slide-book-list item"><a data-v-11979726="" href="/book/5d8ae0c2f265da5bb065c6f4" class="item"><div data-v-11979726="" class="poster"><div data-v-292b3648="" data-v-4d895a49="" data-v-11979726="" data-src="https://user-gold-cdn.xitu.io/2020/3/15/170dcdbe69f8bd21?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1" class="lazy thumb poster-img loaded" style="background-image: url(&quot;https://user-gold-cdn.xitu.io/2020/3/15/170dcdbe69f8bd21?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1&quot;); background-size: cover;"></div></div><div data-v-11979726="" class="content-text"><div data-v-11979726="" class="title">React SSR 服务端渲染原理解析与同构实践</div><div data-v-11979726="" class="price"><div data-v-11979726="" class="new">新人价 ¥9.95</div><div data-v-11979726="" class="delete">¥19.9</div></div></div></a><a data-v-11979726="" href="/book/5da91710f265da5ba674c009" class="item"><div data-v-11979726="" class="poster"><div data-v-292b3648="" data-v-4d895a49="" data-v-11979726="" data-src="https://user-gold-cdn.xitu.io/2020/3/24/1710a9b9b1971a6a?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1" class="lazy thumb poster-img loaded" style="background-image: url(&quot;https://user-gold-cdn.xitu.io/2020/3/24/1710a9b9b1971a6a?imageView2/1/w/104/h/144/q/95/format/webp/interlace/1&quot;); background-size: cover;"></div></div><div data-v-11979726="" class="content-text"><div data-v-11979726="" class="title">深入浅出 PWA</div><div data-v-11979726="" class="price"><div data-v-11979726="" class="new">新人价 ¥9.95</div><div data-v-11979726="" class="delete">¥19.9</div></div></div></a></div></div><div data-v-0582ae5d="" class="book-newuser"><div data-v-0582ae5d="" class="newuser-title"><span data-v-0582ae5d="">新人专享好礼</span></div><div data-v-0582ae5d="" class="giftbag"><img data-v-0582ae5d="" src="https://b-gold-cdn.xitu.io/v3/static/img/45.b99ea03.svg"><div data-v-0582ae5d="" class="content-text"><div data-v-0582ae5d="" class="title">送你<span data-v-0582ae5d="" class="highlight">45元</span>买小册</div><div data-v-0582ae5d="" class="btn-box"><div data-v-0582ae5d="" class="btn-giftbag">立即领取</div></div></div></div></div></div><!----><!----><div data-v-200fbf1c="" data-v-64a8a8ac="" data-v-7286dda2="" class="sidebar-block related-entry-sidebar-block shadow" st:block="relatedEntrySidebarBlock"><div data-v-200fbf1c="" class="block-title">相关文章</div><div data-v-200fbf1c="" class="block-body"><div data-v-64a8a8ac="" data-v-200fbf1c="" class="entry-list"><a data-v-64a8a8ac="" href="/post/5e7b43945188255dda23d1e3" target="_blank" rel="" st:name="link" class="item" data-v-200fbf1c=""><div data-v-64a8a8ac="" class="entry-title">妈妈再也不担心我面试被Redis问得脸都绿了</div><div data-v-64a8a8ac="" class="entry-meta-box"><div data-v-64a8a8ac="" class="entry-meta"><img data-v-64a8a8ac="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-64a8a8ac="" class="count">54</span></div><div data-v-64a8a8ac="" class="entry-meta"><img data-v-64a8a8ac="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.a7c8341.svg" class="icon"><span data-v-64a8a8ac="" class="count">8</span></div></div></a><a data-v-64a8a8ac="" href="/post/5e8192b0e51d4546ba6615fe" target="_blank" rel="" st:name="link" class="item" data-v-200fbf1c=""><div data-v-64a8a8ac="" class="entry-title">懂一点前端—Vue快速入门</div><div data-v-64a8a8ac="" class="entry-meta-box"><div data-v-64a8a8ac="" class="entry-meta"><img data-v-64a8a8ac="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-64a8a8ac="" class="count">6</span></div><div data-v-64a8a8ac="" class="entry-meta"><img data-v-64a8a8ac="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.a7c8341.svg" class="icon"><span data-v-64a8a8ac="" class="count">0</span></div></div></a><a data-v-64a8a8ac="" href="/post/5e780f8ae51d4526f829d813" target="_blank" rel="" st:name="link" class="item" data-v-200fbf1c=""><div data-v-64a8a8ac="" class="entry-title">懂一点Python系列——快速入门</div><div data-v-64a8a8ac="" class="entry-meta-box"><div data-v-64a8a8ac="" class="entry-meta"><img data-v-64a8a8ac="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-64a8a8ac="" class="count">9</span></div><div data-v-64a8a8ac="" class="entry-meta"><img data-v-64a8a8ac="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.a7c8341.svg" class="icon"><span data-v-64a8a8ac="" class="count">0</span></div></div></a><a data-v-64a8a8ac="" href="/post/5e5cc59af265da57621338df" target="_blank" rel="" st:name="link" class="item" data-v-200fbf1c=""><div data-v-64a8a8ac="" class="entry-title">Reids(4)——神奇的HyperLoglog解决统计问题</div><div data-v-64a8a8ac="" class="entry-meta-box"><div data-v-64a8a8ac="" class="entry-meta"><img data-v-64a8a8ac="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-64a8a8ac="" class="count">8</span></div><div data-v-64a8a8ac="" class="entry-meta"><img data-v-64a8a8ac="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.a7c8341.svg" class="icon"><span data-v-64a8a8ac="" class="count">0</span></div></div></a><a data-v-64a8a8ac="" href="/post/5e5b506ff265da57671bc6c7" target="_blank" rel="" st:name="link" class="item" data-v-200fbf1c=""><div data-v-64a8a8ac="" class="entry-title">Redis(3)——分布式锁深入探究</div><div data-v-64a8a8ac="" class="entry-meta-box"><div data-v-64a8a8ac="" class="entry-meta"><img data-v-64a8a8ac="" src="https://b-gold-cdn.xitu.io/v3/static/img/zan.e9d7698.svg" class="icon"><span data-v-64a8a8ac="" class="count">4</span></div><div data-v-64a8a8ac="" class="entry-meta"><img data-v-64a8a8ac="" src="https://b-gold-cdn.xitu.io/v3/static/img/comment.a7c8341.svg" class="icon"><span data-v-64a8a8ac="" class="count">0</span></div></div></a></div></div></div><div data-v-7286dda2="" class="sticky-block-box"><div data-v-200fbf1c="" data-v-26763b8a="" data-v-7286dda2="" class="sidebar-block catalog-block pure"><nav data-v-311d93ec="" data-v-26763b8a="" class="article-catalog" data-v-200fbf1c="" style=""><div data-v-311d93ec="" class="catalog-title">目录</div><div data-v-311d93ec="" class="catalog-body"><ul data-v-311d93ec="" class="catalog-list" style="margin-top: -1901.6px;"><li data-v-311d93ec="" class="item d1"><a href="#heading-0" title="前言">前言</a><!----></li><li data-v-311d93ec="" class="item d1"><a href="#heading-1" title="一、基础篇">一、基础篇</a><ul class="sub-list"><li class="item d2"><a href="#heading-2" title="■什么是 Redis ?">■什么是 Redis ?</a><ul class="sub-list"><li class="item d3"><a href="#heading-3" title="先解释 Redis 基本概念">先解释 Redis 基本概念</a><!----></li><li class="item d3"><a href="#heading-4" title="简单提一下 Redis 数据结构">简单提一下 Redis 数据结构</a><!----></li><li class="item d3"><a href="#heading-5" title="Redis 小总结">Redis 小总结</a><!----></li></ul></li><li class="item d2"><a href="#heading-6" title="■Redis 优缺点">■Redis 优缺点</a><ul class="sub-list"><li class="item d3"><a href="#heading-7" title="优点">优点</a><!----></li><li class="item d3"><a href="#heading-8" title="缺点">缺点</a><!----></li></ul></li><li class="item d2"><a href="#heading-9" title="■为什么要用缓存?为什么使用 Redis?">■为什么要用缓存?为什么使用 Redis?</a><ul class="sub-list"><li class="item d3"><a href="#heading-10" title="提一下现在 Web 应用的现状">提一下现在 Web 应用的现状</a><!----></li><li class="item d3"><a href="#heading-11" title="使用 Redis or 使用缓存带来的优势">使用 Redis or 使用缓存带来的优势</a><!----></li><li class="item d3"><a href="#heading-12" title="也要提一下使用缓存的考虑">也要提一下使用缓存的考虑</a><!----></li></ul></li><li class="item d2"><a href="#heading-13" title="■使用缓存会出现什么问题?">■使用缓存会出现什么问题?</a><ul class="sub-list"><li class="item d3"><a href="#heading-14" title="缓存雪崩问题">缓存雪崩问题</a><!----></li><li class="item d3"><a href="#heading-15" title="缓存穿透问题">缓存穿透问题</a><!----></li><li class="item d3"><a href="#heading-16" title="缓存与数据库双写一致问题">缓存与数据库双写一致问题</a><!----></li></ul></li><li class="item d2"><a href="#heading-17" title="■Redis 为什么早期版本选择单线程?">■Redis 为什么早期版本选择单线程?</a><ul class="sub-list"><li class="item d3"><a href="#heading-18" title="官方解释">官方解释</a><!----></li><li class="item d3"><a href="#heading-19" title="简单总结一下">简单总结一下</a><!----></li></ul></li><li class="item d2"><a href="#heading-20" title="■Redis 为什么这么快?">■Redis 为什么这么快?</a><!----></li></ul></li><li data-v-311d93ec="" class="item d1"><a href="#heading-21" title="二、数据结构篇">二、数据结构篇</a><ul class="sub-list"><li class="item d2"><a href="#heading-22" title="■简述一下 Redis 常用数据结构及实现?">■简述一下 Redis 常用数据结构及实现?</a><!----></li><li class="item d2"><a href="#heading-23" title="■Redis 的 SDS 和 C 中字符串相比有什么优势?">■Redis 的 SDS 和 C 中字符串相比有什么优势?</a><ul class="sub-list"><li class="item d3"><a href="#heading-24" title="先简单总结一下">先简单总结一下</a><!----></li><li class="item d3"><a href="#heading-25" title="再来说 C 语言字符串的问题">再来说 C 语言字符串的问题</a><!----></li><li class="item d3"><a href="#heading-26" title="Redis 如何解决的 | SDS 的优势">Redis 如何解决的 | SDS 的优势</a><!----></li></ul></li><li class="item d2"><a href="#heading-27" title="■字典是如何实现的?Rehash 了解吗?">■字典是如何实现的?Rehash 了解吗?</a><ul class="sub-list"><li class="item d3"><a href="#heading-28" title="先总体聊一下 Redis 中的字典">先总体聊一下 Redis 中的字典</a><!----></li><li class="item d3"><a href="#heading-29" title="说明字典内部结构和 rehash">说明字典内部结构和 rehash</a><!----></li><li class="item d3"><a href="#heading-30" title="扩缩容的条件">扩缩容的条件</a><!----></li></ul></li><li class="item d2"><a href="#heading-31" title="■跳跃表是如何实现的?原理?">■跳跃表是如何实现的?原理?</a><!----></li><li class="item d2"><a href="#heading-32" title="■HyperLogLog 有了解吗?">■HyperLogLog 有了解吗?</a><!----></li><li class="item d2"><a href="#heading-33" title="■布隆过滤器有了解吗?">■布隆过滤器有了解吗?</a><!----></li><li class="item d2"><a href="#heading-34" title="■GeoHash 了解吗?">■GeoHash 了解吗?</a><!----></li><li class="item d2"><a href="#heading-35" title="■压缩列表了解吗?">■压缩列表了解吗?</a><!----></li><li class="item d2"><a href="#heading-36" title="■快速列表 quicklist 了解吗?">■快速列表 quicklist 了解吗?</a><!----></li><li class="item d2"><a href="#heading-37" title="■Stream 结构有了解吗?">■Stream 结构有了解吗?</a><ul class="sub-list"><li class="item d3"><a href="#heading-38" title="Stream 消息太多怎么办?">Stream 消息太多怎么办?</a><!----></li><li class="item d3"><a href="#heading-39" title="PEL 是如何避免消息丢失的?">PEL 是如何避免消息丢失的?</a><!----></li><li class="item d3"><a href="#heading-40" title="和 Kafka 对比起来呢?">和 Kafka 对比起来呢?</a><!----></li></ul></li></ul></li><li data-v-311d93ec="" class="item d1"><a href="#heading-41" title="三、持久化篇">三、持久化篇</a><ul class="sub-list"><li class="item d2"><a href="#heading-42" title="■什么是持久化?">■什么是持久化?</a><ul class="sub-list"><li class="item d3"><a href="#heading-43" title="先简单谈一谈是什么">先简单谈一谈是什么</a><!----></li><li class="item d3"><a href="#heading-44" title="解释一下持久化发生了什么">解释一下持久化发生了什么</a><!----></li><li class="item d3"><a href="#heading-45" title="分析如何保证持久化安全">分析如何保证持久化安全</a><!----></li></ul></li><li class="item d2"><a href="#heading-46" title="■Redis 中的两种持久化方式?">■Redis 中的两种持久化方式?</a><ul class="sub-list"><li class="item d3"><a href="#heading-47" title="方式一:快照">方式一:快照</a><!----></li><li class="item d3"><a href="#heading-48" title="方式二:AOF">方式二:AOF</a><!----></li><li class="item d3"><a href="#heading-49" title="Redis 4.0 的混合持久化">Redis 4.0 的混合持久化</a><!----></li></ul></li><li class="item d2"><a href="#heading-50" title="■RDB 和 AOF 各自有什么优缺点?">■RDB 和 AOF 各自有什么优缺点?</a><ul class="sub-list"><li class="item d3"><a href="#heading-51" title="RDB | 优点">RDB | 优点</a><!----></li><li class="item d3"><a href="#heading-52" title="RDB | 缺点">RDB | 缺点</a><!----></li><li class="item d3"><a href="#heading-53" title="AOF | 优点">AOF | 优点</a><!----></li><li class="item d3"><a href="#heading-54" title="AOF | 缺点">AOF | 缺点</a><!----></li></ul></li><li class="item d2"><a href="#heading-55" title="■两种方式如何选择?">■两种方式如何选择?</a><!----></li><li class="item d2"><a href="#heading-56" title="■Redis 的数据恢复">■Redis 的数据恢复</a><!----></li></ul></li><li data-v-311d93ec="" class="item d1"><a href="#heading-57" title="四、集群篇">四、集群篇</a><ul class="sub-list"><li class="item d2"><a href="#heading-58" title="■主从同步了解吗?">■主从同步了解吗?</a><ul class="sub-list"><li class="item d3"><a href="#heading-59" title="主从复制主要的作用">主从复制主要的作用</a><!----></li><li class="item d3"><a href="#heading-60" title="实现原理">实现原理</a><!----></li></ul></li><li class="item d2"><a href="#heading-61" title="■哨兵模式了解吗?">■哨兵模式了解吗?</a><ul class="sub-list"><li class="item d3"><a href="#heading-62" title="新的主服务器是怎样被挑选出来的?">新的主服务器是怎样被挑选出来的?</a><!----></li></ul></li><li class="item d2"><a href="#heading-63" title="■Redis 集群使用过吗?原理?">■Redis 集群使用过吗?原理?</a><ul class="sub-list"><li class="item d3"><a href="#heading-64" title="基本原理">基本原理</a><!----></li><li class="item d3"><a href="#heading-65" title="集群的主要作用">集群的主要作用</a><!----></li></ul></li><li class="item d2"><a href="#heading-66" title="■集群中数据如何分区?">■集群中数据如何分区?</a><ul class="sub-list"><li class="item d3"><a href="#heading-67" title="方案一:哈希值 % 节点数">方案一:哈希值 % 节点数</a><!----></li><li class="item d3"><a href="#heading-68" title="方案二:一致性哈希分区">方案二:一致性哈希分区</a><!----></li><li class="item d3"><a href="#heading-69" title="方案三:带有虚拟节点的一致性哈希分区">方案三:带有虚拟节点的一致性哈希分区</a><!----></li></ul></li><li class="item d2"><a href="#heading-70" title="■节点之间的通信机制了解吗?">■节点之间的通信机制了解吗?</a><ul class="sub-list"><li class="item d3"><a href="#heading-71" title="两个端口">两个端口</a><!----></li><li class="item d3"><a href="#heading-72" title="Gossip 协议">Gossip 协议</a><!----></li><li class="item d3"><a href="#heading-73" title="消息类型">消息类型</a><!----></li></ul></li><li class="item d2"><a href="#heading-74" title="■集群数据如何存储的有了解吗?">■集群数据如何存储的有了解吗?</a><ul class="sub-list"><li class="item d3"><a href="#heading-75" title="clusterNode 结构">clusterNode 结构</a><!----></li><li class="item d3"><a href="#heading-76" title="clusterState 结构">clusterState 结构</a><!----></li></ul></li></ul></li><li data-v-311d93ec="" class="item d1"><a href="#heading-77" title="五、其他问题">五、其他问题</a><ul class="sub-list"><li class="item d2"><a href="#heading-78" title="■Redis 如何实现分布式锁?">■Redis 如何实现分布式锁?</a><!----></li><li class="item d2"><a href="#heading-79" title="■Redis 过期键的删除策略?">■Redis 过期键的删除策略?</a><ul class="sub-list"><li class="item d3"><a href="#heading-80" title="简单描述">简单描述</a><!----></li><li class="item d3 active"><a href="#heading-81" title="三种策略都有各自的优缺点">三种策略都有各自的优缺点</a><!----></li><li class="item d3"><a href="#heading-82" title="Redis 中的实现">Redis 中的实现</a><!----></li></ul></li><li class="item d2"><a href="#heading-83" title="■Redis 的淘汰策略有哪些?">■Redis 的淘汰策略有哪些?</a><ul class="sub-list"><li class="item d3"><a href="#heading-84" title="Redis 有六种淘汰策略">Redis 有六种淘汰策略</a><!----></li><li class="item d3"><a href="#heading-85" title="4.0 版本后增加以下两种">4.0 版本后增加以下两种</a><!----></li></ul></li><li class="item d2"><a href="#heading-86" title="■Redis常见性能问题和解决方案?">■Redis常见性能问题和解决方案?</a><!----></li><li class="item d2"><a href="#heading-87" title="■假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如何将它们全部找出来?">■假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如何将它们全部找出来?</a><!----></li><li class="item d2"><a href="#heading-88" title="■More..">■More..</a><!----></li></ul></li><li data-v-311d93ec="" class="item d1"><a href="#heading-89" title="参考资料">参考资料</a><!----></li></ul></div></nav></div></div></div><div data-v-18c05c07="" data-v-7407bc26="" class="article-suspended-panel article-suspended-panel" data-v-23c7d456=""><div data-v-18c05c07="" badge="54" class="like-btn panel-btn like-adjust with-badge"></div><div data-v-18c05c07="" badge="8" class="comment-btn panel-btn comment-adjust with-badge"></div><div data-v-18c05c07="" class="collect-btn panel-btn"><!----></div><div data-v-18c05c07="" class="share-title">分享</div><div data-v-18c05c07="" class="weibo-btn share-btn panel-btn"></div><div data-v-18c05c07="" class="qq-btn share-btn panel-btn"></div><div data-v-18c05c07="" class="wechat-btn share-btn panel-btn"><img data-v-18c05c07="" src="" class="wechat-qr-code-img shadow" style="display: none;"></div></div><div data-v-5db6962e="" data-v-7407bc26="" class="image-viewer-box" data-v-23c7d456=""><!----></div><!----></div></main></div><!----></div>
  <script type="text/javascript" src="https://b-gold-cdn.xitu.io/v3/static/js/runtime.cc2b750c14e4e98c0e3a.js"></script><script type="text/javascript" src="https://b-gold-cdn.xitu.io/v3/static/js/0.38bbdc24de2d86d47ad6.js"></script><script type="text/javascript" src="https://b-gold-cdn.xitu.io/v3/static/js/1.b6186216ae7d3a6e6750.js"></script>
</body>
posted @ 2020-04-05 18:40  216119  阅读(246)  评论(0)    收藏  举报