Welcome to mirror list, hosted at ThFree Co, Russian Federation.

index.html « sentinel « 11 « 2019 - github.com/xiaoheiAh/hugo-theme-pure.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 0a9865401d5c6405a25b2432e7981758939774e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <title>
        Redis HA - 哨兵模式 - 赵小黑的博客
      </title>
    <head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport"
    content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui">
  <meta name="renderer" content="webkit">
  <meta http-equiv="Cache-Control" content="no-transform" />
  <meta http-equiv="Cache-Control" content="no-siteapp" />
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta name="format-detection" content="telephone=no,email=no,adress=no">
  
  <meta name="theme-color" content="#000000" />
  
  <meta http-equiv="window-target" content="_top" />
  
  
  <meta name="description" content="Redis 官方高可用(HA)方案之一: 哨兵模式
" />
  <meta name="generator" content="Hugo 0.58.0 with theme pure" />
  <title>Redis HA - 哨兵模式 - 赵小黑的博客</title>
  

  <link rel="stylesheet" href="https://xiaohei.im/hugo-theme-pure/css/style.css">
  <link rel="stylesheet" href="https://cdn.staticfile.org/highlight.js/9.15.10/styles/github.min.css"> 
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.css">
  <meta property="og:title" content="Redis HA - 哨兵模式" />
<meta property="og:description" content="Redis 官方高可用(HA)方案之一: 哨兵模式" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://xiaohei.im/hugo-theme-pure/2019/11/sentinel/" />
<meta property="article:published_time" content="2019-11-23T17:56:15+08:00" />
<meta property="article:modified_time" content="2019-11-23T17:56:15+08:00" />
<meta itemprop="name" content="Redis HA - 哨兵模式">
<meta itemprop="description" content="Redis 官方高可用(HA)方案之一: 哨兵模式">


<meta itemprop="datePublished" content="2019-11-23T17:56:15&#43;08:00" />
<meta itemprop="dateModified" content="2019-11-23T17:56:15&#43;08:00" />
<meta itemprop="wordCount" content="3828">



<meta itemprop="keywords" content="redis," />
<meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="Redis HA - 哨兵模式"/>
<meta name="twitter:description" content="Redis 官方高可用(HA)方案之一: 哨兵模式"/>

  <!--[if lte IE 9]>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/classlist/1.1.20170427/classList.min.js"></script>
    <![endif]-->

  <!--[if lt IE 9]>
      <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
    <![endif]-->

</head>
  </head>
  

  <body class="main-center theme-black" itemscope itemtype="http://schema.org/WebPage"><header class="header" itemscope itemtype="http://schema.org/WPHeader">
    <div class="slimContent">
      <div class="navbar-header">
        <div class="profile-block text-center">
          <a id="avatar" href="https://github.com/xiaoheiAh" target="_blank">
            <img class="img-circle img-rotate" src="https://xiaohei.im/hugo-theme-pure/avatar.png" width="200" height="200">
          </a>
          <h2 id="name" class="hidden-xs hidden-sm">赵小黑</h2>
          <h3 id="title" class="hidden-xs hidden-sm hidden-md">Java Developer</h3>
          <small id="location" class="text-muted hidden-xs hidden-sm"><i class="icon icon-map-marker"></i>Shanghai, China</small>
        </div><div class="search" id="search-form-wrap">
    <form class="search-form sidebar-form">
        <div class="input-group">
            <input type="text" class="search-form-input form-control" placeholder="搜索" />
            <span class="input-group-btn">
                <button type="submit" class="search-form-submit btn btn-flat" onclick="return false;"><i
                        class="icon icon-search"></i></button>
            </span>
        </div>
        <div class="ins-search">
            <div class="ins-search-mask"></div>
            <div class="ins-search-container">
                <div class="ins-input-wrapper">
                    <input type="text" class="ins-search-input" placeholder="想要查找什么..."
                        x-webkit-speech />
                    <button type="button" class="close ins-close ins-selectable" data-dismiss="modal"
                        aria-label="Close"><span aria-hidden="true">×</span></button>
                </div>
                <div class="ins-section-wrapper">
                    <div class="ins-section-container"></div>
                </div>
            </div>
        </div>
    </form>
</div>
        <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#main-navbar" aria-controls="main-navbar" aria-expanded="false">
          <span class="sr-only">Toggle navigation</span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
      </div>
      <nav id="main-navbar" class="collapse navbar-collapse" itemscope itemtype="http://schema.org/SiteNavigationElement" role="navigation">
        <ul class="nav navbar-nav main-nav  menu-highlight">
            <li class="menu-item menu-item-home">
                <a href="/hugo-theme-pure/">
                    <i class="icon icon-home-fill"></i>
                  <span class="menu-title">主页</span>
                </a>
            </li>
            <li class="menu-item menu-item-archives">
                <a href="/hugo-theme-pure/posts">
                    <i class="icon icon-archives-fill"></i>
                  <span class="menu-title">归档</span>
                </a>
            </li>
            <li class="menu-item menu-item-categories">
                <a href="/hugo-theme-pure/categories">
                    <i class="icon icon-folder"></i>
                  <span class="menu-title">分类</span>
                </a>
            </li>
            <li class="menu-item menu-item-tags">
                <a href="/hugo-theme-pure/tags">
                    <i class="icon icon-tags"></i>
                  <span class="menu-title">标签</span>
                </a>
            </li>
            <li class="menu-item menu-item-about">
                <a href="/hugo-theme-pure/about">
                    <i class="icon icon-cup-fill"></i>
                  <span class="menu-title">关于</span>
                </a>
            </li>
        </ul>
      </nav>
    </div>
  </header>
  <aside class="sidebar" itemscope itemtype="http://schema.org/WPSideBar">
  <div class="slimContent">
    
      <div class="widget">
    <h3 class="widget-title">公告</h3>
    <div class="widget-body">
        <div id="board">
            <div class="content"><p>自用科学上网节点推荐(便宜又好用)<a href="https://tianlinzhao.com/aff.php?aff=4969" target="_blank" style="background-color:#FFFF00">点这里跳转</a>
            </div>
        </div>
    </div>
</div>

      <div class="widget">
    <h3 class="widget-title"> 分类</h3>
    <div class="widget-body">
        <ul class="category-list">
            <li class="category-list-item"><a href="https://xiaohei.im/hugo-theme-pure/categories/corejava/" class="category-list-link">corejava</a><span class="category-list-count">7</span></li>
            <li class="category-list-item"><a href="https://xiaohei.im/hugo-theme-pure/categories/hystrix/" class="category-list-link">hystrix</a><span class="category-list-count">2</span></li>
            <li class="category-list-item"><a href="https://xiaohei.im/hugo-theme-pure/categories/leetcode/" class="category-list-link">leetcode</a><span class="category-list-count">3</span></li>
            <li class="category-list-item"><a href="https://xiaohei.im/hugo-theme-pure/categories/redis/" class="category-list-link">redis</a><span class="category-list-count">10</span></li>
            <li class="category-list-item"><a href="https://xiaohei.im/hugo-theme-pure/categories/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/" class="category-list-link">学习笔记</a><span class="category-list-count">1</span></li>
            <li class="category-list-item"><a href="https://xiaohei.im/hugo-theme-pure/categories/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/" class="category-list-link">消息队列</a><span class="category-list-count">4</span></li>
        </ul>
    </div>
</div>
      <div class="widget">
    <h3 class="widget-title"> 标签</h3>
    <div class="widget-body">
        <ul class="tag-list">
            
            
            <li class="tag-list-item"><a href="https://xiaohei.im/hugo-theme-pure/tags/collections/" class="tag-list-link">collections</a><span
                    class="tag-list-count">7</span></li>
            
            
            <li class="tag-list-item"><a href="https://xiaohei.im/hugo-theme-pure/tags/hugo/" class="tag-list-link">hugo</a><span
                    class="tag-list-count">1</span></li>
            
            
            <li class="tag-list-item"><a href="https://xiaohei.im/hugo-theme-pure/tags/hystrix/" class="tag-list-link">hystrix</a><span
                    class="tag-list-count">1</span></li>
            
            
            <li class="tag-list-item"><a href="https://xiaohei.im/hugo-theme-pure/tags/leetcode/" class="tag-list-link">leetcode</a><span
                    class="tag-list-count">3</span></li>
            
            
            <li class="tag-list-item"><a href="https://xiaohei.im/hugo-theme-pure/tags/netty/" class="tag-list-link">netty</a><span
                    class="tag-list-count">1</span></li>
            
            
            <li class="tag-list-item"><a href="https://xiaohei.im/hugo-theme-pure/tags/rabbitmq/" class="tag-list-link">rabbitmq</a><span
                    class="tag-list-count">4</span></li>
            
            
            <li class="tag-list-item"><a href="https://xiaohei.im/hugo-theme-pure/tags/redis/" class="tag-list-link">redis</a><span
                    class="tag-list-count">10</span></li>
            
            
            <li class="tag-list-item"><a href="https://xiaohei.im/hugo-theme-pure/tags/rust/" class="tag-list-link">rust</a><span
                    class="tag-list-count">3</span></li>
            
            
            <li class="tag-list-item"><a href="https://xiaohei.im/hugo-theme-pure/tags/rxjava/" class="tag-list-link">rxjava</a><span
                    class="tag-list-count">2</span></li>
            
            
            <li class="tag-list-item"><a href="https://xiaohei.im/hugo-theme-pure/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/" class="tag-list-link">分布式锁</a><span
                    class="tag-list-count">1</span></li>
            
            
            <li class="tag-list-item"><a href="https://xiaohei.im/hugo-theme-pure/tags/%E5%93%8D%E5%BA%94%E5%BC%8F%E7%BC%96%E7%A8%8B/" class="tag-list-link">响应式编程</a><span
                    class="tag-list-count">1</span></li>
            
            
            <li class="tag-list-item"><a href="https://xiaohei.im/hugo-theme-pure/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/" class="tag-list-link">数据结构</a><span
                    class="tag-list-count">1</span></li>
            
        </ul>

    </div>
</div>
      
<div class="widget">
    <h3 class="widget-title">最新文章</h3>
    <div class="widget-body">
        <ul class="recent-post-list list-unstyled no-thumbnail">
            <li>
                <div class="item-inner">
                    <p class="item-title">
                        <a href="https://xiaohei.im/hugo-theme-pure/2019/11/netty/" class="title">[学习笔记] Netty</a>
                    </p>
                    <p class="item-date">
                        <time datetime="2019-11-29 18:40:27 &#43;0800 CST" itemprop="datePublished">2019-11-29</time>
                    </p>
                </div>
            </li>
            <li>
                <div class="item-inner">
                    <p class="item-title">
                        <a href="https://xiaohei.im/hugo-theme-pure/2019/11/cluster/" class="title">Redis HA - Cluster</a>
                    </p>
                    <p class="item-date">
                        <time datetime="2019-11-24 11:48:17 &#43;0800 CST" itemprop="datePublished">2019-11-24</time>
                    </p>
                </div>
            </li>
            <li>
                <div class="item-inner">
                    <p class="item-title">
                        <a href="https://xiaohei.im/hugo-theme-pure/2019/11/sentinel/" class="title">Redis HA - 哨兵模式</a>
                    </p>
                    <p class="item-date">
                        <time datetime="2019-11-23 17:56:15 &#43;0800 CST" itemprop="datePublished">2019-11-23</time>
                    </p>
                </div>
            </li>
            <li>
                <div class="item-inner">
                    <p class="item-title">
                        <a href="https://xiaohei.im/hugo-theme-pure/2019/11/replication/" class="title">Redis-复制功能探索</a>
                    </p>
                    <p class="item-date">
                        <time datetime="2019-11-16 14:24:40 &#43;0800 CST" itemprop="datePublished">2019-11-16</time>
                    </p>
                </div>
            </li>
            <li>
                <div class="item-inner">
                    <p class="item-title">
                        <a href="https://xiaohei.im/hugo-theme-pure/2019/11/event/" class="title">Redis-事件</a>
                    </p>
                    <p class="item-date">
                        <time datetime="2019-11-14 15:01:45 &#43;0800 CST" itemprop="datePublished">2019-11-14</time>
                    </p>
                </div>
            </li>
        </ul>
    </div>
</div>
  </div>
</aside>

    
    
<aside class="sidebar sidebar-toc collapse" id="collapseToc" itemscope itemtype="http://schema.org/WPSideBar">
  <div class="slimContent">
    <h4 class="toc-title">文章目录</h4>
    <nav id="toc" class="js-toc toc">

    </nav>
  </div>
</aside>
<main class="main" role="main"><div class="content">
  <article id="-" class="article article-type-" itemscope
    itemtype="http://schema.org/BlogPosting">
    
    <div class="article-header">
      <h1 itemprop="name">
  <a
    class="article-title"
    href="/hugo-theme-pure/2019/11/sentinel/"
    >Redis HA - 哨兵模式</a
  >
</h1>

      <div class="article-meta">
        <span class="article-date">
  <i class="icon icon-calendar-check"></i>
<a href="https://xiaohei.im/hugo-theme-pure/2019/11/sentinel/" class="article-date">
  <time datetime="2019-11-23 17:56:15 &#43;0800 CST" itemprop="datePublished">2019-11-23</time>
</a>
</span><span class="article-category">
  <i class="icon icon-folder"></i>
  <a class="article-category-link" href="/hugo-theme-pure/categories/redis/"> redis </a>
</span>  
  <span class="article-tag">
    <i class="icon icon-tags"></i>
    <a class="article-tag-link" href="/hugo-theme-pure/tags/redis/"> redis </a>
  </span>

	<span class="article-read hidden-xs">
	    <i class="icon icon-eye-fill" aria-hidden="true"></i>
	    <span id="busuanzi_container_page_pv">
			<span id="busuanzi_value_page_pv">0</span>
		</span>
	</span>
        <span class="post-comment"><i class="icon icon-comment"></i> <a href="/hugo-theme-pure/2019/11/sentinel/#comments"
            class="article-comment-link">评论</a></span>
		<span class="post-wordcount hidden-xs" itemprop="wordCount">字数统计:3828字</span>
		<span class="post-readcount hidden-xs" itemprop="timeRequired">阅读时长:8分 </span>
      </div>
    </div>
    <div class="article-entry marked-body js-toc-content" itemprop="articleBody">
      <p>Redis 官方高可用(HA)方案之一: <strong>哨兵模式</strong></p>

<p>这篇文章已经介绍的很全面了:<a href="https://juejin.im/post/5b7d226a6fb9a01a1e01ff64">https://juejin.im/post/5b7d226a6fb9a01a1e01ff64</a> 自己就总结一些问题:</p>

<h2 id="sentinel-如何保证集群高可用">sentinel 如何保证集群高可用?</h2>

<ol>
<li>时刻与监控的节点保持心跳(PING),订阅 <code>__sentinel__:hello</code> 频道实时更新配置并持久化到磁盘</li>
<li>自动发现监听节点的其他 <code>sentinel</code> 保持通信</li>
<li>节点不可达时询问其他节点确认是否不可达,是否需要执行故障转移(半数投票)</li>
<li>故障转移后广播配置,帮助其他从节点切换到新的主节点,以 <code>epoch</code> 最大的配置为准</li>
</ol>

<h2 id="sentinel-如何判定节点下线">sentinel 如何判定节点下线?</h2>

<p><a href="#主观下线/客观下线">主观下线/客观下线</a></p>

<h2 id="sentinel-的局限性">sentinel 的局限性?</h2>

<p><code>Redis Sentinel</code> 仅仅解决了 <strong>高可用</strong> 的问题,对于 <strong>主节点</strong> 单点写入和单节点无法扩容等问题,还需要引入 <code>Redis Cluster</code> <strong>集群模式</strong> 予以解决。</p>

<h2 id="官方文档介绍">官方文档介绍</h2>

<blockquote>
<p><a href="https://redis.io/topics/sentinel">https://redis.io/topics/sentinel</a></p>

<p>使用 <code>sentinel</code> 的原因: 做到无人工介入的自动容错 <code>redis</code> 集群.</p>
</blockquote>

<p><code>sentinel</code> 宏观概览:</p>

<ul>
<li><strong>监控 Monitoring:</strong> 持续监控主从节点的运行状态</li>
<li><strong>通知 Notification:</strong> 节点异常时,通过暴露的 <code>API</code> 可以及时报警</li>
<li><strong>自动故障转移 Automatic Failover:</strong> 主节点宕机后,可以自动晋升从节点为新主节点,其他节点会重新连接到新主节点,应用也会被通知相应的节点变化</li>
<li><strong>提供配置 Configuration Provider:</strong> <code>sentinel</code> 维护着主从的节点信息,客户端会连接<code>sentinel</code> 获取主节点信息.</li>
</ul>

<p><code>sentinel</code> <strong>天生分布式,</strong>多节点协同的好处在于:</p>

<ul>
<li>多数节点都同意主节点不可用时才执行故障检测.有效避免错判.</li>
<li>多节点可以提升系统鲁棒性(<code>system robust</code>),避免单点故障</li>
</ul>

<h3 id="使用须知">使用须知</h3>

<ol>
<li>至少 3 个 <code>sentinel</code> 保证系统鲁棒性</li>
<li>节点最好放在不同的主机或虚拟机,降低级联故障(一下全GG)</li>
<li>由于 <code>redis</code> 采用的是异步复制,<code>sentinel</code> + <code>redis</code> 不能保证故障期间确认的写入(主从可能无法通信,确认复制进度).<code>sentinel</code> 可以在发布时控制一定时间内数据不丢失,但也不是万全之策.</li>
<li>客户端需要支持 <code>sentinel</code> (常用 <code>Java</code> 客户端基本都支持)</li>
<li>高可用并不是百分之百有效,即时你时时刻刻都在测试,产线环境也在跑,保不准凌晨就 GG,也没办法不是.</li>
<li><code>Sentinel</code>,<code>Docker</code>,或者其他形式的网络地址交换或端口映射需要加倍小心:Docker执行端口重新映射,破坏<code>Sentinel</code>自动发现其他的哨兵进程和主节点的 <code>replicas</code> 列表。</li>
</ol>

<h3 id="sentinel-设置">Sentinel 设置</h3>

<p><code>redis</code> 安装目录下有一个 <code>sentinel.conf</code> 模板配置可以参考.最小化配置如下:</p>

<pre><code class="language-plain">sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5
</code></pre>

<p>不需要配置 <code>replicas</code> , <code>sentinel</code> 可以自动从主节点中获取 <code>INFO</code> 信息.同时该配置也会实时重写的: 新的 <code>sentinel</code> 节点加入或者故障转移 <code>replica</code> 晋升时.</p>

<h4 id="sentinel-monitor-master-group-name-ip-port-quorum"><code>sentinel monitor &lt;master-group-name&gt; &lt;ip&gt; &lt;port&gt; &lt;quorum&gt;</code></h4>

<p>从命令就可以看出来一些名堂: 监控地址为 <code>ip:port,name</code> 为 <code>master-group-name</code> 的主节点.</p>

<p><strong>quorum:</strong> 判断节点确实已经下线的支持票数(由 <code>Sentinel</code> 节点进行投票),票数超过一定范围后就可以让节点下线并作故障转移.但 <code>quorum</code> 只是针对于下线判断,执行故障转移需要在 <code>sentinel</code> 集群选举(投票)出一个 <code>leader</code> 来执行故障转移.</p>

<p>e.g. <code>quorum</code> = 2, <code>sentinel</code> 节点数 = 5</p>

<ul>
<li>如果有两个 <code>sentinel</code> 节点认为主节点下线了,那么这两个节点中的一个会尝试开始执行故障转移.</li>
<li>如果有超过半数 <code>sentinel</code> 节点存在(当前情况下即活着 3 个 <code>sentinel</code> 节点),故障转移就会被授权真正开始执行.</li>
</ul>

<p><strong>核心概念:</strong> <code>sentinel</code> 节点半数不可达就不允许执行 <strong>故障转移</strong>.</p>

<h4 id="sentinel-option-name-master-name-option-value"><code>sentinel &lt;option_name&gt; &lt;master_name&gt; &lt;option_value&gt;</code></h4>

<p><code>sentinel</code> 其它的配置基本都是这个格式.</p>

<ul>
<li><code>down-after-milliseconds</code> 节点宕机超过该毫秒时间后 <code>sentinel</code> 节点才能认为其不可达.</li>
<li><code>parallel-syncs</code> 在发生failover主从切换时,这个选项指定了最多可以有多少个 <code>replica</code> 同时对新的<code>master</code> 进行同步,这个数字越小,完成主从故障转移所需的时间就越长,但是如果这个数字越大,就意味着越多的slave因为主从同步而不可用。可以通过将这个值设为1来保证每次只有一个 <code>replica</code> 处于不能处理命令请求的状态。</li>
</ul>

<p><strong>所有配置都可以通过 <code>SENTINEL SET</code> 热更新.</strong></p>

<h4 id="添加-删除-sentinel-节点">添加/删除 sentinel 节点</h4>

<p><strong>添加</strong>: 启动一个新的 <code>sentinel</code> 即可.10s就可以获得其他 <code>sentinel</code> 节点以及主节点的 <code>replicas</code> 信息了.</p>

<p><strong>多节点添加</strong>:建议 <code>one by one</code>,等到当前节点添加进集群后,再添加下一个.添加节点过程中可能会出故障.</p>

<p><strong>删除节点:</strong> <code>sentinel</code> 节点不会丢失见过 <code>sentinel</code> 节点信息,即使这些节点已经挂了.所以需要在没有网络分区的情况下做以下几步:</p>

<ol>
<li>终止你想要关掉的 <code>sentinel</code> 节点进程</li>
<li>发送一条命令 <code>SENTINEL RESET *</code> 给所有 <code>sentinel</code> 节点.如果只想对单一 <code>master</code> 处理,把 <code>*</code> 换成主节点名称.等一会儿~</li>
<li>通过 <code>SENTINEL MASTER</code> 命令查看节点是否已删除</li>
</ol>

<h4 id="主观下线-客观下线">主观下线/客观下线</h4>

<p><code>sentinel</code> 中有两种下线状态.</p>

<ul>
<li><strong>主观下线(Subjectively Down)</strong> aka. SDOWN</li>
</ul>

<p>当前 <code>sentinel</code> 认为自己监控的节点下线了,即主观下线.<code>SDOWN</code> 判定的条件为: <code>sentinel</code> 节点向监控节点发送 <code>PING</code> 命令在设置的 <code>is-master-down-after-milliseconds</code> 毫秒后没有收到有效回复则判定为 <code>SDOWN</code></p>

<ul>
<li><strong>客观下线(Objectively Down)</strong> aka. ODOWN</li>
</ul>

<p>有 <code>quorum</code> 数量的 <code>sentinel</code> 节点认为监控的节点 <code>SDOWN</code>.当一个 <code>sentinel</code> 节点认为监控的节点 <code>SDOWN</code> 后,会向其它节点发送 <code>SENTINEL is-master-down-by-addr</code> 命令来判断其它节点对该节点的监控状态.如果回执为 <strong>已下线</strong> 的节点数+自身大于 <code>quorum</code> 数量,则判定为 <strong>客观下线</strong></p>

<p><code>PING</code> 命令的有效回复有什么?</p>

<ul>
<li>+PONG</li>
<li>-LOADING error</li>
<li>-MASTERDOWN error</li>
</ul>

<p>其它回复都是无效的.需要注意的是: 只要收到有效回复就不会认为其 <code>SDOWN</code> 了.</p>

<p><code>SDOWN</code> 并不能触发故障转移,只能判定节点不可用.要触发故障转移,<strong>必须</strong>达到 <code>ODOWN</code> 状态.</p>

<h4 id="sdown-odwn">SDOWN -&gt; ODWN?</h4>

<p><code>sentinel</code> 没有使用强一致性的算法来保证 <code>SDOWN</code> -&gt; <code>ODOWN</code> 的转换,而是使用的<a href="https://zhuanlan.zhihu.com/p/41228196">Gossip协议</a>来保证最终一致性.在给定的时间范围内,给定的 <code>sentinel</code> 节点收到了足够多(<code>quorum</code>)的其它 <code>sentinel</code> 节点的 <code>SDOWN</code> 确认,就会从 <code>SDOWN</code> 切换到 <code>ODOWN</code> 了.</p>

<p>真正执行故障转移时会有比较严格的授权,但是前提也得是 <code>ODOWN</code> 状态才行.<code>ODOWN</code> 只针对 <code>master</code> 节点,<code>replicas</code> 和 <code>sentinels</code> 只会有 <code>SDOWN</code> 状态.如果 <code>replica</code> 变为 <code>SDOWN</code> 了,在故障转移的时候就不会被晋升.</p>

<h4 id="自动发现-auto-discovery">自动发现 auto discovery</h4>

<p><code>sentinel</code> 节点之间会保持连接来互相检查是否可用,交换信息,但是并不需要在启动的时候配置一长串其他 <code>sentinel</code> 节点的地址. <code>sentinel</code> 会利用 <code>redis</code> 的 <code>Pub/Sub</code> 能力来发现监控了相同 <code>master/replicas</code> 的 <code>sentinel</code> 节点.<code>replicas</code> 自动发现是一样的原理.</p>

<h5 id="如何实现的">如何实现的?</h5>

<p>向一个叫 <code>__sentinel__:hello</code> 的 <code>channel</code> 发送 hello 消息.</p>

<ul>
<li>每个 <code>sentinel</code> 节点都会向每一个它监控的 <code>master</code> 和 <code>replica</code> 的叫做 <code>__sentinel__:hello</code> 的Pub/Sub channel 广播自己的 <code>ip</code>,<code>port</code>,<code>runid</code>.2s 一次.</li>
<li>每个订阅了 <code>master</code> 和 <code>replica</code> 的 <code>sentinel</code> 都会收到消息,并会去判断有新的 <code>sentinel</code> 节点就会被添加进来.</li>
<li>这个 <code>hello</code> 消息同样包含着最新的 <code>master</code> 全量配置,每个收到消息的 <code>sentinel</code> 会进行比对更新.</li>
<li>添加新的 <code>sentinel</code> 节点时会提前判断该节点信息是否已经存在.</li>
</ul>

<h4 id="sentinel-强制更新配置">sentinel 强制更新配置</h4>

<p><strong>sentinel 是一个总会尝试将当前最新的配置强制更新到所有监控节点的系统</strong>.</p>

<blockquote>
<p>这可能也是一种 tradeoff 吧.比如 replica 如果连错 master 了,那 sentinel 就必须把它矫正过来,重连正确的master.</p>
</blockquote>

<h4 id="副本选举">副本选举</h4>

<p><code>sentinel</code> 可以执行故障转移时,需要选择一个合适的 <code>replica</code> 晋升.</p>

<h5 id="评估条件">评估条件</h5>

<ul>
<li>与 <code>master</code> 的断连时间</li>
<li><code>replica</code> 优先级-&gt;可以设置</li>
<li>复制进度 <code>offset</code></li>
<li>Run ID</li>
</ul>

<h5 id="判定需要跳过的节点">判定需要跳过的节点</h5>

<pre><code class="language-bash">(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state
</code></pre>

<p>如果一个 <code>replica</code> 的断连时间超过上面这个表达式,那就认为该节点不可靠,不考虑. <code>down-after-milliseconds</code> 是通过设置的,<code>milliseconds_since_master_is_in_SDOWN_state</code> 指在执行故障转移时 <code>master</code> 仍不可用的时间.</p>

<h5 id="选举过程">选举过程</h5>

<p>符合上述条件后才会对其按照条件进行排序.顺序如下:</p>

<ul>
<li>首先根据 <code>replica-priority</code> 排序(<code>redis.conf</code> 进行设置),值越小越优先</li>
<li><code>priority</code> 相同时,比较 <code>offset</code>,值越大越优先(同步最完整)</li>
<li>如果 <code>priority</code>,<code>offset</code> 都相同,就会判断 <code>run ID</code> 的字典序.越小的 <code>run ID</code> 并不是说有什么优势,但是比起重排序随机选一个 <code>replica</code>,字典序选举方式更有确定性更有用(大白话).</li>
</ul>

<p>建议所有节点都设置 <code>replica-priority</code>.如果  <code>replica-priority</code> 设置为 0, 表示永远不会被选为 <code>master</code> .但是在故障转移后 <code>sentinel</code> 会重置通过这种方式设置的配置,以便可以与新的 <code>master</code> 连接,唯一的区别就是该节点不会是主节点.</p>

<h3 id="深入算法内部">深入算法内部</h3>

<h4 id="quorum">Quorum</h4>

<p><code>quorum</code> 参数会被 <code>sentinel</code> 集群用来判断是否有这个数量的 <code>sentinel</code> 节点认为 <code>master</code> 已经 <code>SDOWN</code> 了,需不需要转为 <code>ODOWN</code> 触发故障转移 <code>failover</code>.</p>

<p>但是,触发故障转移后,至少需要有<strong>半数</strong>的 <code>sentinel</code> 节点(如果 <code>quorum</code> 值比半数还多,那其实需要有<code>quorum</code>个节点)授权给一个 <code>sentinel</code> 节点才能真正执行.小于半数节点不允许执行.</p>

<blockquote>
<p>e.g. 5 instances <code>quorum</code> = 2</p>

<p>当有2个节点认为 <code>master</code> 不可达时,就会触发 failover.但是需要有至少3个节点授权给这2个节点之一才能真正执行failover.</p>

<p>如果 <code>quorum</code> = 5,那就需要所有节点都认为 <code>master</code> 不可达,才能触发failover,并且所有节点都要授权.</p>
</blockquote>

<h4 id="纪元-configuration-epochs">纪元 Configuration Epochs</h4>

<p>为什么需要获取半数以上的授权执行 <code>failover</code>?</p>

<p>当一个 <code>sentinel</code> 节点被授权后,会获得一个可以用于故障转移节点的唯一的纪元(<code>configuration epoch</code>)标志.这是一个在故障转移完成后针对新配置的版本号 number.因为是多数同意将指定的版本分配给指定授权的 <code>sentinel</code> ,所以不会有其他节点使用这个版本号.也就意味着每一次故障转移时生成的新配置都有唯一的版本号标识.</p>

<p><code>sentinel</code> 集群有一条规则: 如果 sentinel A 投票给 sentinel B 去执行故障转移,A 会等待一段时间后对同一个主节点再次进行故障转移.这个时间可以通过 <code>sentinel.conf</code> 的 <code>failover-timeout</code> 进行配置.这就意味着不会有节点在同一时间对同一个主节点进行故障转移,被授权的节点回先执行,失败了后面会有其他的节点进行重试.</p>

<p><code>sentinel</code> 保证 <a href="https://en.wikipedia.org/wiki/Liveness">liveness</a> 特性(我的理解就是不会宕机一直存活):如果有多个节点可用,只会选择一个节点去执行故障转移.</p>

<p><code>sentinel</code> 同样保证 <a href="https://en.wikipedia.org/wiki/Safety#System_safety_and_reliability_engineering">safety</a> 特性:每一个节点都会尝试使用不同的 <code>configuration epoch</code> 对相同的节点进行故障转移.</p>

<h4 id="配置传递-configuration-propagation">配置传递  Configuration propagation</h4>

<p>故障转移完成后,<code>sentinel</code> 会广播新的配置给其他 <code>sentinel</code> 节点更新这个新的主节点信息.执行故障转移的主节点还需要对新的主节点执行 <code>SLAVE NO ONE</code>,稍后在 <code>INFO</code> 命令中就可以看到这个主节点了.</p>

<p>所有 <code>sentinel</code> 节点都会广播配置信息,通过 <code>__sentinel__:hello</code> channel 广播出去.配置信息都带有 <code>epoch</code> ,值越大越会被当做最新的配置.</p>

<h4 id="网络分区后的一致性问题">网络分区后的一致性问题</h4>

<p>Redis + Sentinel 架构是<strong>保证最终一致性</strong>的系统,在发生网络分区恢复时,不可避免的会丢失数据.</p>

<p>如果把 redis 当做缓存来用,数据丢了也没事,可以再去库里查嘛.</p>

<p>如果把 redis 当做存储来用,那最好配上下面两个配置降低损失.</p>

<pre><code class="language-bash">min-replicas-to-write 1
min-replicas-max-lag 10
</code></pre>

<h4 id="sentinel-状态持久化">Sentinel 状态持久化</h4>

<p>Sentinel 状态持久化在 <code>sentinel.conf</code> 中,每次手挡新配置,或者创建配置,都会带着<code>configuration epoch</code> 一起持久化到硬盘,重启时就没有问题了.</p>
    </div>
    <div class="article-footer">
<blockquote class="mt-2x">
  <ul class="post-copyright list-unstyled">
    <li class="post-copyright-link hidden-xs">
      <strong>本文链接: </strong>
      <a href="https://xiaohei.im/hugo-theme-pure/2019/11/sentinel/" title="Redis HA - 哨兵模式" target="_blank" rel="external">https://xiaohei.im/hugo-theme-pure/2019/11/sentinel/</a>
    </li>
    <li class="post-copyright-license">
      <strong>License:</strong><a href="http://creativecommons.org/licenses/by/4.0/deed.zh" target="_blank" rel="external">CC BY 4.0 CN</a>
    </li>
  </ul>
</blockquote>

<div class="panel panel-default panel-badger">
  <div class="panel-body">
    <figure class="media">
      <div class="media-left">
        <a href="https://github.com/xiaoheiAh" target="_blank" class="img-burn thumb-sm visible-lg">
          <img src="https://xiaohei.im/hugo-theme-pure/avatar.png" class="img-rounded w-full" alt="">
        </a>
      </div>
      <div class="media-body">
        <h3 class="media-heading"><a href="https://github.com/xiaoheiAh" target="_blank"><span class="text-dark">赵小黑</span><small class="ml-1x">Java Developer</small></a></h3>
        <div>好好学习~天天向上~</div>
      </div>
    </figure>
  </div>
</div>
    </div>
  </article>
<section id="comments">
</section>

</div><nav class="bar bar-footer clearfix" data-stick-bottom>
    <div class="bar-inner">
        <ul class="pager pull-left">
            <li class="prev">
                <a href="https://xiaohei.im/hugo-theme-pure/2019/11/replication/" title="Redis-复制功能探索"><i
                        class="icon icon-angle-left"
                        aria-hidden="true"></i><span>&nbsp;&nbsp;下一篇</span></a>
            </li>
            <li class="next">
                <a href="https://xiaohei.im/hugo-theme-pure/2019/11/cluster/"
                    title="Redis HA - Cluster"><span>上一篇&nbsp;&nbsp;</span><i
                        class="icon icon-angle-right" aria-hidden="true"></i></a>
            </li>
            
            <li class="toggle-toc">
                <a class="toggle-btn collapsed" data-toggle="collapse" href="#collapseToc" aria-expanded="false"
                    title="文章目录" role="button">
                    <span>[&nbsp;</span><span>文章目录</span>
                    <i class="text-collapsed icon icon-anchor"></i>
                    <i class="text-in icon icon-close"></i>
                    <span>]</span>
                </a>
            </li>
        </ul>
        
        <button type="button" class="btn btn-fancy btn-donate pop-onhover bg-gradient-warning" data-toggle="modal"
            data-target="#donateModal"><span>赏</span></button>
        
        <div class="bar-right">
            <div class="share-component" data-sites="weibo,qq,wechat,facebook,twitter"
                data-mobile-sites="weibo,qq,qzone"></div>
        </div>
    </div>
</nav>


<div class="modal modal-center modal-small modal-xs-full fade" id="donateModal" tabindex="-1" role="dialog">
    <div class="modal-dialog" role="document">
        <div class="modal-content donate">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
                    aria-hidden="true">&times;</span></button>
            <div class="modal-body">
                <div class="donate-box">
                    <div class="donate-head">
                        <p>感谢您的支持,我会继续努力的!</p>
                    </div>
                    <div class="tab-content">
                        <div role="tabpanel" class="tab-pane fade active in" id="alipay">
                            <div class="donate-payimg">
                                <img src="https://xiaohei.im/hugo-theme-pure/donate/alipayimg.png"
                                    alt="扫码支持" title="扫一扫" />
                            </div>
                            <p class="text-muted mv">扫码打赏, 多少你说了算~</p>
                            <p class="text-grey">打开支付宝扫一扫,即可进行扫码打赏哦~</p>
                        </div>
                        <div role="tabpanel" class="tab-pane fade" id="wechatpay">
                            <div class="donate-payimg">
                                <img src="https://xiaohei.im/hugo-theme-pure/donate/wechatpayimg.png"
                                    alt="扫码支持" title="扫一扫" />
                            </div>
                            <p class="text-muted mv">扫码打赏, 多少你说了算~</p>
                            <p class="text-grey">打开微信扫一扫,即可进行扫码打赏哦</p>
                        </div>
                    </div>
                    <div class="donate-footer">
                        <ul class="nav nav-tabs nav-justified" role="tablist">
                            <li role="presentation" class="active">
                                <a href="#alipay" id="alipay-tab" role="tab" data-toggle="tab" aria-controls="alipay"
                                    aria-expanded="true"><i class="icon icon-alipay"></i> 支付宝</a>
                            </li>
                            <li role="presentation" class="">
                                <a href="#wechatpay" role="tab" id="wechatpay-tab" data-toggle="tab"
                                    aria-controls="wechatpay" aria-expanded="false"><i class="icon icon-wepay"></i>
                                    微信支付</a>
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
</main><footer class="footer" itemscope itemtype="http://schema.org/WPFooter">
<ul class="social-links">
    <li><a href="https://github.com/xiaoheiAh" target="_blank" title="github" data-toggle=tooltip data-placement=top >
            <i class="icon icon-github"></i></a></li>
    <li><a href="https://xiaohei.im/index.xml" target="_blank" title="rss" data-toggle=tooltip data-placement=top >
            <i class="icon icon-rss"></i></a></li>
</ul>
  <div class="copyright">
    &copy;2017  -
    2019
    <div class="publishby">
        Theme by <a href="https://github.com/xiaoheiAh" target="_blank"> xiaoheiAh </a>base on<a href="https://github.com/xiaoheiAh/hugo-theme-pure" target="_blank"> pure</a>.
    </div>
  </div>
</footer>

<script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.min.js"></script>
<script>
    window.jQuery || document.write('<script src="js/jquery.min.js"><\/script>')
</script>
<script type="text/javascript" src="https://cdn.staticfile.org/highlight.js/9.15.10/highlight.min.js"></script>
<script type="text/javascript" src="https://cdn.staticfile.org/highlight.js/9.15.10/languages/rust.min.js"></script>
<script type="text/javascript"
    src="https://cdn.staticfile.org/highlight.js/9.15.10/languages/dockerfile.min.js"></script>
<script>
    hljs.configure({
        tabReplace: '    ', 
        classPrefix: ''     
        
    })
    hljs.initHighlightingOnLoad();
</script>
<script type="text/javascript" src="https://xiaohei.im/hugo-theme-pure/js/application.js"></script>
<script type="text/javascript" src="https://xiaohei.im/hugo-theme-pure/js/plugin.js"></script>
<script>
    (function (window) {
        var INSIGHT_CONFIG = {
            TRANSLATION: {
                POSTS: '文章',
                PAGES: '页面',
                CATEGORIES: '分类',
                TAGS: '标签',
                UNTITLED: '(未命名)',
            },
            ROOT_URL: 'https:\/\/xiaohei.im\/hugo-theme-pure',
            CONTENT_URL: 'https:\/\/xiaohei.im\/hugo-theme-pure\/searchindex.json ',
        };
        window.INSIGHT_CONFIG = INSIGHT_CONFIG;
    })(window);
</script>
<script type="text/javascript" src="https://xiaohei.im/hugo-theme-pure/js/insight.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.min.js"></script>
<script>
    tocbot.init({
        
        tocSelector: '.js-toc',
        
        contentSelector: '.js-toc-content',
        
        headingSelector: 'h1, h2, h3',
        
        hasInnerContainers: true,
    });
</script>

<script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

<script src="https://cdn.jsdelivr.net/npm/gitalk@1.4.0/dist/gitalk.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/blueimp-md5@2.10.0/js/md5.min.js"></script>
<script type="text/javascript">
    var gitalk = new Gitalk({
        clientID: 'e38fc798c72a7e4e1386',
        clientSecret: 'e151aa3b7b98d3cfaa1f096b88fdd7897e2c8007',
        repo: 'xiaoheiAh.github.io',
        owner: 'xiaoheiAh',
        admin: ['xiaoheiAh'],
        id: md5(location.pathname),
        distractionFreeMode: true
    });
    gitalk.render('comments');
</script>
<script type="application/javascript">
var doNotTrack = false;
if (!doNotTrack) {
	window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
	ga('create', 'UA-98254666-1', 'auto');
	
	ga('send', 'pageview');
}
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>

  </body>
</html>