-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path6a07ad6.html
More file actions
644 lines (534 loc) · 71 KB
/
6a07ad6.html
File metadata and controls
644 lines (534 loc) · 71 KB
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
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 6.3.0">
<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon.png">
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon.png">
<link rel="mask-icon" href="/images/logo.svg" color="#222">
<link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha256-HtsXJanqjKTc8vVQjO4YMhiqFoXkfBsjBWcX91T1jr8=" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">
<script class="next-config" data-name="main" type="application/json">{"hostname":"tallate.github.io","root":"/","images":"/images","scheme":"Gemini","darkmode":false,"version":"8.18.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":false,"style":null},"fold":{"enable":false,"height":500},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"menu_item":"fadeInDown","post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果:${query}","hits_time":"找到 ${hits} 个搜索结果(用时 ${time} 毫秒)","hits":"找到 ${hits} 个搜索结果"}}</script><script src="/js/config.js"></script>
<meta name="description" content="记录下Redis的一些优化点,以后可能随时会有用到。">
<meta property="og:type" content="article">
<meta property="og:title" content="Redis 性能调优">
<meta property="og:url" content="https://tallate.github.io/6a07ad6.html">
<meta property="og:site_name" content="Tallate">
<meta property="og:description" content="记录下Redis的一些优化点,以后可能随时会有用到。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://tallate.github.io/imgs/Redis/Redis%E4%B8%BB%E7%BA%BF%E7%A8%8B%E5%92%8CIO%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%BA%A4%E4%BA%92.jpg">
<meta property="og:image" content="https://tallate.github.io/imgs/Redis/Redis%E4%B8%BB%E7%BA%BF%E7%A8%8B%E5%92%8CIO%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%BA%A4%E4%BA%922.jpg">
<meta property="article:published_time" content="2020-11-10T04:21:48.000Z">
<meta property="article:modified_time" content="2025-07-06T17:56:20.902Z">
<meta property="article:author" content="tallate">
<meta property="article:tag" content="Redis">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://tallate.github.io/imgs/Redis/Redis%E4%B8%BB%E7%BA%BF%E7%A8%8B%E5%92%8CIO%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%BA%A4%E4%BA%92.jpg">
<link rel="canonical" href="https://tallate.github.io/6a07ad6.html">
<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"https://tallate.github.io/6a07ad6.html","path":"/6a07ad6.html","title":"Redis 性能调优"}</script>
<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>Redis 性能调优 | Tallate</title>
<noscript>
<link rel="stylesheet" href="/css/noscript.css">
</noscript>
</head>
<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
<div class="headband"></div>
<main class="main">
<div class="column">
<header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="site-brand-container">
<div class="site-nav-toggle">
<div class="toggle" aria-label="切换导航栏" role="button">
<span class="toggle-line"></span>
<span class="toggle-line"></span>
<span class="toggle-line"></span>
</div>
</div>
<div class="site-meta">
<a href="/" class="brand" rel="start">
<i class="logo-line"></i>
<p class="site-title">Tallate</p>
<i class="logo-line"></i>
</a>
<p class="site-subtitle" itemprop="description">该吃吃该喝喝 啥事别往心里搁</p>
</div>
<div class="site-nav-right">
<div class="toggle popup-trigger" aria-label="搜索" role="button">
<i class="fa fa-search fa-fw fa-lg"></i>
</div>
</div>
</div>
<nav class="site-nav">
<ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="home fa-fw"></i>首页</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="user fa-fw"></i>关于</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="tags fa-fw"></i>标签<span class="badge">84</span></a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="th fa-fw"></i>分类<span class="badge">25</span></a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="archive fa-fw"></i>归档<span class="badge">192</span></a></li>
<li class="menu-item menu-item-search">
<a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
</a>
</li>
</ul>
</nav>
<div class="search-pop-overlay">
<div class="popup search-popup"><div class="search-header">
<span class="search-icon">
<i class="fa fa-search"></i>
</span>
<div class="search-input-container">
<input autocomplete="off" autocapitalize="off" maxlength="80"
placeholder="搜索..." spellcheck="false"
type="search" class="search-input">
</div>
<span class="popup-btn-close" role="button">
<i class="fa fa-times-circle"></i>
</span>
</div>
<div class="search-result-container no-result">
<div class="search-result-icon">
<i class="fa fa-spinner fa-pulse fa-5x"></i>
</div>
</div>
</div>
</div>
</header>
<aside class="sidebar">
<div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
<ul class="sidebar-nav">
<li class="sidebar-nav-toc">
文章目录
</li>
<li class="sidebar-nav-overview">
站点概览
</li>
</ul>
<div class="sidebar-panel-container">
<!--noindex-->
<div class="post-toc-wrap sidebar-panel">
<div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#Redis-%E7%9B%91%E6%8E%A7"><span class="nav-number">1.</span> <span class="nav-text">Redis 监控</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#redis-cli"><span class="nav-number">1.1.</span> <span class="nav-text">redis-cli</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#redis-stat"><span class="nav-number">1.2.</span> <span class="nav-text">redis-stat</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#slowlog"><span class="nav-number">1.3.</span> <span class="nav-text">slowlog</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#redis-benchmark"><span class="nav-number">1.4.</span> <span class="nav-text">redis-benchmark</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#RDB-%E6%96%87%E4%BB%B6%E5%88%86%E6%9E%90"><span class="nav-number">1.5.</span> <span class="nav-text">RDB 文件分析</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Redis%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5"><span class="nav-number">2.</span> <span class="nav-text">Redis性能问题排查</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%93%AA%E4%BA%9B%E5%9C%BA%E6%99%AF%E4%BC%9A%E5%AF%BC%E8%87%B4Redis%E9%98%BB%E5%A1%9E%EF%BC%9F"><span class="nav-number">2.1.</span> <span class="nav-text">哪些场景会导致Redis阻塞?</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A6%82%E6%9E%9CRedis%E5%8F%98%E6%85%A2%EF%BC%8C%E5%8F%AF%E8%83%BD%E6%98%AF%E4%BB%80%E4%B9%88%E5%AF%BC%E8%87%B4%E7%9A%84%EF%BC%9F"><span class="nav-number">2.2.</span> <span class="nav-text">如果Redis变慢,可能是什么导致的?</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A6%82%E4%BD%95%E6%A3%80%E6%B5%8BRedis%E6%98%AF%E5%90%A6%E5%8F%98%E6%85%A2%EF%BC%9F"><span class="nav-number">2.3.</span> <span class="nav-text">如何检测Redis是否变慢?</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Redis%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96"><span class="nav-number">3.</span> <span class="nav-text">Redis性能优化</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%86%85%E5%AD%98%E4%BC%98%E5%8C%96"><span class="nav-number">3.1.</span> <span class="nav-text">内存优化</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%85%A2%E6%9F%A5%E8%AF%A2%E5%91%BD%E4%BB%A4"><span class="nav-number">3.2.</span> <span class="nav-text">慢查询命令</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%BF%87%E6%9C%9Fkey%E6%93%8D%E4%BD%9C"><span class="nav-number">3.3.</span> <span class="nav-text">过期key操作</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%89%B9%E9%87%8F%E8%AF%B7%E6%B1%82%E4%BC%98%E5%8C%96"><span class="nav-number">3.4.</span> <span class="nav-text">批量请求优化</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A4%A7%E9%87%8F%E6%95%B0%E6%8D%AE%E6%8F%92%E5%85%A5"><span class="nav-number">3.5.</span> <span class="nav-text">大量数据插入</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A4%A7-Key-%E9%97%AE%E9%A2%98"><span class="nav-number">3.6.</span> <span class="nav-text">大 Key 问题</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Redis%E4%B8%8ECPU%E7%9A%84%E5%85%B3%E7%B3%BB"><span class="nav-number">3.7.</span> <span class="nav-text">Redis与CPU的关系</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%86%85%E5%AD%98%E7%A2%8E%E7%89%87"><span class="nav-number">3.8.</span> <span class="nav-text">内存碎片</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9F%A5%E7%9C%8B%E5%86%85%E5%AD%98%E7%A2%8E%E7%89%87"><span class="nav-number">3.8.1.</span> <span class="nav-text">查看内存碎片</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%A4%84%E7%90%86%E5%86%85%E5%AD%98%E7%A2%8E%E7%89%87"><span class="nav-number">3.8.2.</span> <span class="nav-text">处理内存碎片</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A4%9A%E7%BA%BF%E7%A8%8B"><span class="nav-number">3.9.</span> <span class="nav-text">多线程</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%BC%95%E5%85%A5%E5%A4%9AIO%E7%BA%BF%E7%A8%8B%E7%89%B9%E6%80%A7%E7%9A%84%E7%90%86%E7%94%B1"><span class="nav-number">3.9.1.</span> <span class="nav-text">引入多IO线程特性的理由</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#IO%E7%BA%BF%E7%A8%8B%E5%92%8C%E4%B8%BB%E7%BA%BF%E7%A8%8B%E4%B9%8B%E9%97%B4%E7%9A%84%E4%BA%A4%E4%BA%92"><span class="nav-number">3.9.2.</span> <span class="nav-text">IO线程和主线程之间的交互</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%85%8D%E7%BD%AE%E5%BC%80%E5%90%AF%E5%A4%9A%E7%BA%BF%E7%A8%8B"><span class="nav-number">3.9.3.</span> <span class="nav-text">配置开启多线程</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%BC%93%E5%AD%98"><span class="nav-number">3.10.</span> <span class="nav-text">客户端缓存</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#NVM"><span class="nav-number">3.11.</span> <span class="nav-text">NVM</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#NVM%E7%9A%84%E4%B8%89%E4%B8%AA%E7%89%B9%E7%82%B9"><span class="nav-number">3.11.1.</span> <span class="nav-text">NVM的三个特点</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%85%B6%E4%BB%96%E4%BC%98%E5%8C%96%E7%82%B9"><span class="nav-number">3.12.</span> <span class="nav-text">其他优化点</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Redis%E9%85%8D%E7%BD%AE"><span class="nav-number">4.</span> <span class="nav-text">Redis配置</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%86%85%E5%AD%98"><span class="nav-number">4.1.</span> <span class="nav-text">内存</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BF%AE%E6%94%B9%E6%95%B0%E6%8D%AE%E5%BA%93%E9%85%8D%E7%BD%AE"><span class="nav-number">4.2.</span> <span class="nav-text">修改数据库配置</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%BF%87%E6%9C%9F%E6%97%B6%E9%97%B4%E7%9A%84%E8%AE%BE%E7%BD%AE"><span class="nav-number">4.3.</span> <span class="nav-text">过期时间的设置</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%BF%9E%E6%8E%A5%E8%AE%BE%E7%BD%AE"><span class="nav-number">4.4.</span> <span class="nav-text">连接设置</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#Redis%E8%BF%9E%E6%8E%A5%E9%85%8D%E7%BD%AE"><span class="nav-number">4.4.1.</span> <span class="nav-text">Redis连接配置</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BF%AE%E6%94%B9%E6%9C%80%E5%A4%A7TCP%E8%BF%9E%E6%8E%A5"><span class="nav-number">4.4.2.</span> <span class="nav-text">修改最大TCP连接</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BF%AE%E6%94%B9TCP%E8%BF%9E%E6%8E%A5%E7%AD%89%E5%BE%85%E9%98%9F%E5%88%97%E9%95%BF%E5%BA%A6"><span class="nav-number">4.4.3.</span> <span class="nav-text">修改TCP连接等待队列长度</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%8C%81%E4%B9%85%E5%8C%96"><span class="nav-number">4.5.</span> <span class="nav-text">持久化</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%B8%BB%E4%BB%8E%E9%85%8D%E7%BD%AE"><span class="nav-number">4.6.</span> <span class="nav-text">主从配置</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Redis-%E4%BD%BF%E7%94%A8%E8%A7%84%E8%8C%83"><span class="nav-number">5.</span> <span class="nav-text">Redis 使用规范</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%B8%9A%E5%8A%A1%E5%B1%82%E9%9D%A2"><span class="nav-number">5.1.</span> <span class="nav-text">业务层面</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%BF%90%E7%BB%B4%E5%B1%82%E9%9D%A2"><span class="nav-number">5.2.</span> <span class="nav-text">运维层面</span></a></li></ol></li></ol></div>
</div>
<!--/noindex-->
<div class="site-overview-wrap sidebar-panel">
<div class="site-author animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
<p class="site-author-name" itemprop="name">tallate</p>
<div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap animated">
<nav class="site-state">
<div class="site-state-item site-state-posts">
<a href="/archives/">
<span class="site-state-item-count">192</span>
<span class="site-state-item-name">日志</span>
</a>
</div>
<div class="site-state-item site-state-categories">
<a href="/categories/">
<span class="site-state-item-count">25</span>
<span class="site-state-item-name">分类</span></a>
</div>
<div class="site-state-item site-state-tags">
<a href="/tags/">
<span class="site-state-item-count">84</span>
<span class="site-state-item-name">标签</span></a>
</div>
</nav>
</div>
</div>
</div>
</div>
</aside>
</div>
<div class="main-inner post posts-expand">
<div class="post-block">
<article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
<link itemprop="mainEntityOfPage" href="https://tallate.github.io/6a07ad6.html">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/avatar.gif">
<meta itemprop="name" content="tallate">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Tallate">
<meta itemprop="description" content="">
</span>
<span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
<meta itemprop="name" content="Redis 性能调优 | Tallate">
<meta itemprop="description" content="">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
Redis 性能调优
</h1>
<div class="post-meta-container">
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2020-11-10 12:21:48" itemprop="dateCreated datePublished" datetime="2020-11-10T12:21:48+08:00">2020-11-10</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-calendar-check"></i>
</span>
<span class="post-meta-item-text">更新于</span>
<time title="修改时间:2025-07-07 01:56:20" itemprop="dateModified" datetime="2025-07-07T01:56:20+08:00">2025-07-07</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="far fa-folder"></i>
</span>
<span class="post-meta-item-text">分类于</span>
<span itemprop="about" itemscope itemtype="http://schema.org/Thing">
<a href="/categories/%E7%BC%93%E5%AD%98/" itemprop="url" rel="index"><span itemprop="name">缓存</span></a>
</span>
</span>
</div>
</div>
</header>
<div class="post-body" itemprop="articleBody"><p>记录下Redis的一些优化点,以后可能随时会有用到。</p>
<span id="more"></span>
<h1 id="Redis-监控"><a href="#Redis-监控" class="headerlink" title="Redis 监控"></a>Redis 监控</h1><p>这里把一些常见的监控命令总结一下,时不时都会用到。</p>
<h2 id="redis-cli"><a href="#redis-cli" class="headerlink" title="redis-cli"></a>redis-cli</h2><p>命令行客户端。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 创建连接,可以用PING-PONG来检查连接是否OK</span><br><span class="line">redis-cli -h localhost -p 6379</span><br><span class="line"># 监控Redis的连接和读写操作</span><br><span class="line">redis-cli -h localhost -p 6379 monitor</span><br><span class="line"># Redis服务器的统计信息</span><br><span class="line">redis-cli -h localhost -p 6379 info</span><br></pre></td></tr></table></figure>
<ul>
<li>内存使用<br><code>Memory</code>下可以查看 Redis 内存使用情况。如果 Redis 使用的内存超出了可用的物理内存大小,那么 Redis 很可能系统会被杀掉。针对这一点,你可以通过 info 命令对 used_memory 和 used_memory_peak 进行监控,为使用内存量设定阀值,并设定相应的报警机制。当然,报警只是手段,重要的是你得预先计划好,当内存使用量过大后,你应该做些什么,是清除一些没用的冷数据,还是把 Redis 迁移到更强大的机器上去。</li>
<li>持久化<br><code>Persistence</code>下可以查看 RDB 和 AOF 的备份情况。如果因为你的机器或 Redis 本身的问题导致 Redis 崩溃了,那么你唯一的救命稻草可能就是 dump 出来的 rdb 文件了,所以,对 Redis dump 文件进行监控也是很重要的。可以通过对 rdb_last_save_time 进行监控,了解最近一次 dump 数据操作的时间,还可以通过对 rdb_changes_since_last_save 进行监控来获得如果这时候出现故障,会丢失(即已改变)多少数据。</li>
<li>Keys<br>通过获取 Keyspace 中的结果得到各个数据库中 key 的数量</li>
<li>QPS<br>即每分钟执行的命令个数,即:(total_commands_processed2-total_commands_processed1)/span,为了实时得到 QPS,可以设定脚本在后台运行,记录过去几分钟的 total_commands_processed。在计算 QPS 时,利用过去的信息和当前的信息得出 QPS 的估计值。</li>
</ul>
<h2 id="redis-stat"><a href="#redis-stat" class="headerlink" title="redis-stat"></a>redis-stat</h2><p>Redis 服务器的<strong>实时</strong>信息。<br>这个命令不是 Redis 官方提供的,而是一个三方用 ruby 写的监控程序,安装起来有点麻烦,这里就不说明了。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"># usage:redis-stat [HOST[:PORT] ...] [INTERVAL [COUNT]]</span><br><span class="line"># 每1s收集一次</span><br><span class="line">redis-stat 1</span><br><span class="line"># 指定主机和服务器端口,间隔为1s,收集10次</span><br><span class="line">redis-stat localhost:6379 1 10</span><br><span class="line"># 启动一个redis-stat服务进程,提供一个Dashboard来查看Redis服务器的状态,按如下启动,可以访问 `localhost:8080` 查看</span><br><span class="line">redis-stat localhost:6379 --server=8080 5 --daemon</span><br></pre></td></tr></table></figure>
<p>-a, –auth=PASSWORD 密码<br>-v, –verbose 展示更多信息<br>–style=STYLE 输出样式:unicode|ascii<br>–no-color 去掉颜色<br>–csv[=CSV_FILE] 打印或将结果保存到 CSV 文件内<br>–es=ELASTICSEARCH_URL 将结果发送到 ElasticSearch:[http://]HOST[:PORT][/INDEX]<br>–server[=PORT] 启动 redis-stat 服务器(默认端口是 63790)<br>–daemon 启动 redis-stat 作为守护进程,必须和 –server 选项一起使用<br>–version 版本<br>–help 帮助信息</p>
<h2 id="slowlog"><a href="#slowlog" class="headerlink" title="slowlog"></a>slowlog</h2><p>慢查询日志。<br>可以在 redis.conf 中配置:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 记录执行时间超过5秒的查询</span><br><span class="line">config set slowlog-log-slower-than 5000</span><br><span class="line"># 最多保存25条日志</span><br><span class="line">config set slowlog-max-len 25</span><br></pre></td></tr></table></figure>
<p>使用 redis-cli 登录查看慢查询日志:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 获取10条日志</span><br><span class="line">slowlog get 10</span><br></pre></td></tr></table></figure>
<h2 id="redis-benchmark"><a href="#redis-benchmark" class="headerlink" title="redis-benchmark"></a>redis-benchmark</h2><p>redis-benchmark 是 Redis 官方提供的 Redis 服务器性能基准测试工具:<br>-t 选择你想测试的命令,比如 redis-benchmark -t set<br>-p 指定 port redis-benchmark -p 6379<br>-l 一直循环<br>-c 指定客户端数量<br>-n 指定 request 数量<br>-q Quiet,不显示额外信息(多少时间内完成了多少条之类的),只显示 query/sec 的值</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># 测试并发连接性能,100个并发连接,总共发100000个请求</span><br><span class="line">redis-benchmark -h localhost -p 6379 -c 100 -n 100000</span><br><span class="line"># 测试大数据包读写性能</span><br><span class="line">redis-benchmark -h localhost -p 6379 -q -d 100</span><br><span class="line"># 只测试某些操作的性能</span><br><span class="line">redis-benchmark -h localhost -p 6379 -t set,lpush -n 100000 -q</span><br><span class="line"># 只测试某些数值存取的性能</span><br><span class="line">redis-benchmark -h localhost -p 6379 -q script load "redis.call('set', 'foo', 'bar')"</span><br></pre></td></tr></table></figure>
<h2 id="RDB-文件分析"><a href="#RDB-文件分析" class="headerlink" title="RDB 文件分析"></a>RDB 文件分析</h2><p>Redis 内存比较大的时候不容易查出是哪些 key 比较占空间,这时可以使用 <a target="_blank" rel="noopener" href="https://github.com/sripathikrishnan/redis-rdb-tools">redis-rdb-tools</a> 这种工具来查看报告。</p>
<h1 id="Redis性能问题排查"><a href="#Redis性能问题排查" class="headerlink" title="Redis性能问题排查"></a>Redis性能问题排查</h1><h2 id="哪些场景会导致Redis阻塞?"><a href="#哪些场景会导致Redis阻塞?" class="headerlink" title="哪些场景会导致Redis阻塞?"></a>哪些场景会导致Redis阻塞?</h2><p>Redis实例运行期间会和多种对象进行交互:</p>
<ul>
<li>客户端:网络 IO,键值对增删改查操作,数据库操作;</li>
<li>磁盘:生成 RDB 快照,记录 AOF 日志,AOF 日志重写;</li>
<li>主从节点:主库生成、传输 RDB 文件,从库接收 RDB 文件、清空数据库、加载 RDB 文件;</li>
<li>切片集群实例:向其他实例传输哈希槽信息,数据迁移。</li>
</ul>
<h2 id="如果Redis变慢,可能是什么导致的?"><a href="#如果Redis变慢,可能是什么导致的?" class="headerlink" title="如果Redis变慢,可能是什么导致的?"></a>如果Redis变慢,可能是什么导致的?</h2><ol>
<li>Redis是单线程模型,如果前面有请求执行比较慢,后面的都要排队等着;<br>耗时的操作包括:<ul>
<li>集合全量查询和聚合操作:比如HGETALL、SMEMBERS</li>
<li>操作bigkey:写入一个bigkey在分配内存时需要消耗更多的时间,同样,删除bigkey释放内存同样会产生耗时;<br> 特别是删除大key时需要释放内存,操作系统需要将释放掉的内存块插入到一个空闲内存块的链表,以便后续进行管理和再分配(指malloc/free)。</li>
<li>使用复杂度过高的命令:例如SORT/SUNION/ZUNIONSTORE,或者O(N)命令,但是N很大,例如lrange key 0 -1一次查询全量数据;</li>
<li>大量key集中过期:Redis的过期机制也是在主线程中执行的,大量key集中过期会导致处理一个请求时,耗时都在删除过期key,耗时变长;</li>
<li>淘汰策略:淘汰策略也是在主线程执行的,当内存超过Redis内存上限后,每次写入都需要淘汰一些key,也会造成耗时变长;</li>
<li>AOF刷盘开启always机制:每次写入都需要把这个操作刷到磁盘,写磁盘的速度远比写内存慢,会拖慢Redis的性能;</li>
<li>主从全量同步生成RDB:虽然采用fork子进程生成数据快照,但fork这一瞬间也是会阻塞整个线程的,实例越大,阻塞时间越久;<br>对此,需要业务人员主动规避上述可能导致超时的情况;</li>
</ul>
</li>
<li>并发非常大,单线程读写客户端IO数据存在性能瓶颈,虽然采用IO多路复用机制,但是读写客户端数据依旧是同步IO,只能单线程依次读取客户端的数据,无法利用到CPU多核。<br>对此,Redis6.0推出了多线程,可以在高并发场景下利用CPU多核多线程读写客户端数据。</li>
</ol>
<h2 id="如何检测Redis是否变慢?"><a href="#如何检测Redis是否变慢?" class="headerlink" title="如何检测Redis是否变慢?"></a>如何检测Redis是否变慢?</h2><p>如何排查Redis是否真的变慢,一个直接的方法是查看Redis的<strong>响应延迟</strong>,但是响应延迟多长算慢呢?不同硬件性能不同,这个值的判断也是不同的,并没有绝对的标准。<br>另一种方法是测算当前环境下的 Redis <strong>基线性能</strong>,也就是一个系统在低压力、无干扰下的基本性能,这个性能只由当前的软硬件配置决定。<br>从 2.8.7 版本开始,<code>redis-cli</code> 命令提供了<code>–intrinsic-latency</code> 选项,可以用来监测和统计测试期间内的最大延迟,这个延迟可以作为 Redis 的基线性能。<br>一般我们可以把Redis基线性能和响应延迟结合起来判断Redis是否变慢了,如果观察到Redis延迟是其基线性能的2倍以上,就可以认定Redis变慢了。</p>
<h1 id="Redis性能优化"><a href="#Redis性能优化" class="headerlink" title="Redis性能优化"></a>Redis性能优化</h1><h2 id="内存优化"><a href="#内存优化" class="headerlink" title="内存优化"></a>内存优化</h2><ol>
<li>压缩的类型<br>在数据量比较少时,Redis会使用占用内存更少的数据类型,包括hash、list、set、zset均为如此,占用的内存大小甚至可以达到普通类型的1/5。<br>hash-max-ziplist-entries 512<br>hash-max-ziplist-value 64<br>zset-max-ziplist-entries 128<br>zset-max-ziplist-value 64<br>set-max-intset-entries 512<br>压缩的类型是“拿时间换空间”,因此效率肯定是比不上普通类型的,只是数据量比较小的情况下二者是差不多的,试想:虽然一个压缩类型对象并不能省多少空间,但是如果很多很多对象都经过压缩,那么最终总体上就能省很多空间了。<br>当对象占用内存超过配置的最大值,Redis会自动将其转换为普通类型。</li>
<li>尽量使用散列表<br>小散列表占用的内存非常小</li>
</ol>
<h2 id="慢查询命令"><a href="#慢查询命令" class="headerlink" title="慢查询命令"></a>慢查询命令</h2><p>使用Redis前必须先了解各种指令的复杂度,比如get、set是O(1)的,set的smembers是O(N)的。<br>当发现性能变慢时,可以通过:</p>
<ol>
<li>Redis日志查询变慢的请求;</li>
<li>latency monitor工具查询变慢请求;</li>
</ol>
<p>如果确实有大量满查询命令,可以:</p>
<ol>
<li>用其他高效命令代替;</li>
<li>sort、sunion、sinter这些复杂操作可以将逻辑转移到客户端完成。<br>如果业务逻辑就是得用慢查询命令完成,那可以考虑采用性能更好的CPU,从而更快地完成查询命令。</li>
</ol>
<h2 id="过期key操作"><a href="#过期key操作" class="headerlink" title="过期key操作"></a>过期key操作</h2><p>Redis4.0之前,淘汰key的机制中,删除操作是阻塞的,而淘汰机制会不断抽样,直到过期的key只占不到25%的比例,因此淘汰很有可能会影响主线程;在Redis4.0之后采用异步线程机制来减少阻塞影响)。<br>比如同一时间有很多key设置了相同的过期时间,就会导致这种情况。</p>
<h2 id="批量请求优化"><a href="#批量请求优化" class="headerlink" title="批量请求优化"></a>批量请求优化</h2><p>使用管道Pipelineing:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ (printf "PING\r\nPING\r\nPING\r\n"; sleep 1) | nc localhost 6379</span><br></pre></td></tr></table></figure>
<p>优点:</p>
<ol>
<li>一次连接就可以执行多次请求;</li>
</ol>
<p>缺点:</p>
<ol>
<li>使用管道发送命令时,服务器将被迫回复一个队列答复,占用很多内存。所以,如果你需要发送大量的命令,最好是把他们按照合理数量分批次的处理,例如10K的命令,读回复,然后再发送另一个10k的命令,等等。这样速度几乎是相同的,但是在回复这10k命令队列需要非常大量的内存用来组织返回数据内容。</li>
</ol>
<h2 id="大量数据插入"><a href="#大量数据插入" class="headerlink" title="大量数据插入"></a>大量数据插入</h2><p>大量数据插入时会面临以下问题:</p>
<ol>
<li>一个一个插入的话会有很多时间浪费在请求的往返上,因此需要批量执行<br>批量执行可以是:管道、lua脚本</li>
<li>批量插入的过程怎么保证所有key都能插入成功<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">SET Key0 Value0</span><br><span class="line">SET Key1 Value1</span><br><span class="line">...</span><br><span class="line">SET KeyN ValueN</span><br></pre></td></tr></table></figure>
如果是如下的pipeline,其实并不可靠,因为执行过程中不能检查错误。<br><code>(cat data.txt; sleep 10) | nc localhost 6379 > /dev/null</code><br>一种更好的方式是使用redis-cli中的<strong>pipe mode</strong>,期间会把错误输出到终端:<br><code>cat data.txt | redis-cli --pipe</code></li>
</ol>
<h2 id="大-Key-问题"><a href="#大-Key-问题" class="headerlink" title="大 Key 问题"></a>大 Key 问题</h2><blockquote>
<p>大key大的是value。</p>
</blockquote>
<p>大 Key 有两种状况:</p>
<ol>
<li>Redis 中单个简单的 Key 存储的 value 很大</li>
<li>hash、set、zset、list 中存储的元素过多(以万为单位)。</li>
</ol>
<p>由于 Redis 的单线程模型,读写大 Key 时服务器的耗时可能会比较长、甚至阻塞。</p>
<p>分析大key可以通过<code>--bigkeys</code>进行:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">hgc@hgc-X555LD:~$ redis-cli -h 127.0.0.1 -p 6379 -n 0 --bigkeys</span><br><span class="line"></span><br><span class="line"># Scanning the entire keyspace to find biggest keys as well as</span><br><span class="line"># average sizes per key type. You can use -i 0.1 to sleep 0.1 sec</span><br><span class="line"># per 100 SCAN commands (not usually needed).</span><br><span class="line"></span><br><span class="line">[00.00%] Biggest string found so far '143' with 35 bytes</span><br><span class="line">[00.00%] Biggest string found so far 'a' with 184 bytes</span><br><span class="line">[73.33%] Biggest hash found so far 'b' with 1 fields</span><br><span class="line"></span><br><span class="line">-------- summary -------</span><br><span class="line"></span><br><span class="line">Sampled 15 keys in the keyspace!</span><br><span class="line">Total key length in bytes is 41 (avg len 2.73)</span><br><span class="line"></span><br><span class="line">Biggest hash found 'b' has 1 fields</span><br><span class="line">Biggest string found 'a' has 184 bytes</span><br><span class="line"></span><br><span class="line">0 lists with 0 items (00.00% of keys, avg size 0.00)</span><br><span class="line">1 hashs with 1 fields (06.67% of keys, avg size 1.00)</span><br><span class="line">14 strings with 639 bytes (93.33% of keys, avg size 45.64)</span><br><span class="line">0 streams with 0 entries (00.00% of keys, avg size 0.00)</span><br><span class="line">0 sets with 0 members (00.00% of keys, avg size 0.00)</span><br><span class="line">0 zsets with 0 members (00.00% of keys, avg size 0.00)</span><br></pre></td></tr></table></figure>
<p><code>bigkeys</code>是通过scan指令来实现的,所以并不会造成服务器长时间的阻塞,当然这种数据库全扫命令最好还是少用。</p>
<p>解决方案一般是能拆则拆,对于单个大 Key 的情况:<br>1.1 将大 Key 进行分割,拆成几个小的 key-value,使用 multiGet 获取值。<br>这样分拆的意义是将单次操作的压力分摊到多个 Redis 实例上,降低对单个 Redis 的 IO 影响,而且大 Key 拆分之后每次只查询一部分,减小了 IO 阻塞的风险。<br>为了均匀分割,可以对 field 进行 hash 并通过质数 N 取余,将余数加到 key 上面。<br>1.2 将大 Key 拆分成多个 key-value,并将这些存储在一个 hash 中,每个 field 代表一个具体的属性,使用 hget、hmget 来获取部分的 value,使用 hset、hmset 来更新部分属性</p>
<p>对于 hash、set、zset、list 中存储的元素过多的情况,可以控制将 field 分散到多个集合内。<br>比如以下代码将属于一个大 hash 内的 field 分散到 10000 个拆分后的小 hash 内:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">newHashKey = hashKey + (hash(field) % 10000)</span><br><span class="line">hset(newHashKey, field, value)</span><br><span class="line">hget(newHashKey, field)</span><br></pre></td></tr></table></figure>
<p>对于一些需要考虑顺序的场景,比如 lpop、zrange,需要在 hash 函数上做些文章,比如按照时间来拆分。</p>
<h2 id="Redis与CPU的关系"><a href="#Redis与CPU的关系" class="headerlink" title="Redis与CPU的关系"></a>Redis与CPU的关系</h2><p>在现代CPU架构中,每个物理核心都会有一个私有的L1 cache和L2 cache,不同核之间共用一个L3缓存,尽可能避免访问主存。<br>应用程序会被分配到一个CPU上执行,但是进程调度机制可能会将Redis进程调度到另一个核心上,导致之前加载的缓存都白费了。<br>可以通过taskset命令将Redis进程绑定在一个核上运行:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># -c 用于设置要绑定的核编号</span><br><span class="line">taskset -c 0 ./redis-server</span><br></pre></td></tr></table></figure>
<h2 id="内存碎片"><a href="#内存碎片" class="headerlink" title="内存碎片"></a>内存碎片</h2><p>Redis底层分配内存函数是jmalloc,它分配的内存大小总是2的幂倍数,如果分配的内存大小比实际使用的要多一些,就会产生内存碎片,内存碎片多了后就会有很多内存的浪费情况,特别是<strong>分配键值对的大小不一的情况下,内存碎片会尤其严重</strong>。</p>
<h3 id="查看内存碎片"><a href="#查看内存碎片" class="headerlink" title="查看内存碎片"></a>查看内存碎片</h3><p>查看内存碎片情况很容易,可以直接使用<code>info</code>命令:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">10.32.140.14:6211> info memory</span><br><span class="line"># Memory</span><br><span class="line">used_memory:1441123632</span><br><span class="line">used_memory_human:1.34G</span><br><span class="line">used_memory_rss:1853603840</span><br><span class="line">used_memory_rss_human:1.73G</span><br><span class="line">...</span><br><span class="line">mem_fragmentation_ratio:1.29</span><br></pre></td></tr></table></figure>
<p>其中<code>mem_fragmentation_ratio</code>这个指标就是Redis当前的内存碎片率,它的值其实就是<code>used_memory_rss</code>和<code>used_memory</code>相除的结果(<code>used_memory_rss/used_memory</code>),前者是OS分配给Redis的内存空间,包含碎片,后者不包含碎片。</p>
<ul>
<li><code>mem_fragmentation_ratio</code>在<code>[1,1.5]</code>范围内是合理的,因为内存碎片无法完全避免</li>
<li><code>mem_fragmentation_ratio</code>大于1.5则需要采取一些措施来减小内存碎片率。</li>
</ul>
<h3 id="处理内存碎片"><a href="#处理内存碎片" class="headerlink" title="处理内存碎片"></a>处理内存碎片</h3><ul>
<li>重启Redis实例。这是最简单的方法,但是重启后Redis内存中的数据会全部丢失,除非进行了持久化,但恢复也是需要不少时间的。</li>
<li>从Redis4.0-RC3后,Redis自身提供了内存碎片清理的功能,也即将内存数据拷贝到一块新的内存位置,可以设置参数控制碎片清理的开始、结束时机、占用的内存比例等:<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"># 开启内存碎片清理功能</span><br><span class="line">config set activedefrag yes</span><br><span class="line"># 表示内存碎片达到100MB时开始清理</span><br><span class="line">active-defrag-ignore-bytes 100mb</span><br><span class="line"># 表示内存碎片空间占Redis总空间大小的10%时</span><br><span class="line">tive-defrag-threshold-lower 10</span><br><span class="line"># 控制清理过程占用CPU时间比例不低于25%,保证清理能正常</span><br><span class="line">adtive-defrag-cycle-min 25</span><br><span class="line"># 控制清理过程占用CPU时间比例不高于75%,尽量不要影响主线程</span><br><span class="line">active-defrag-cycle-max 75</span><br></pre></td></tr></table></figure></li>
</ul>
<h2 id="多线程"><a href="#多线程" class="headerlink" title="多线程"></a>多线程</h2><p>Redis 6.0引入的多线程特性是多IO线程,而不是命令线程。</p>
<h3 id="引入多IO线程特性的理由"><a href="#引入多IO线程特性的理由" class="headerlink" title="引入多IO线程特性的理由"></a>引入多IO线程特性的理由</h3><p>随着网络硬件的性能提升,Redis 的性能瓶颈有时会出现在网络 IO 的处理上,也就是说,<strong>单个主线程处理网络请求的速度跟不上底层网络硬件的速度</strong>。<br>为了应对这个问题,一般有两种解决办法:</p>
<ol>
<li>用用户态网络协议栈(例如 DPDK)取代内核网络协议栈,让网络请求的处理不用在内核里执行,直接在用户态完成处理就行。<br>这种方案在Redis中改动会比较大,因此Redis6.0没有采用这个方案。</li>
<li>采用多个 IO 线程来处理网络请求,提高网络请求处理的并行度。</li>
</ol>
<h3 id="IO线程和主线程之间的交互"><a href="#IO线程和主线程之间的交互" class="headerlink" title="IO线程和主线程之间的交互"></a>IO线程和主线程之间的交互</h3><ol>
<li>服务端和客户端建立 Socket 连接,并分配处理线程首先,主线程负责接收建立连接请求。当有客户端请求和实例建立 Socket 连接时,主线程会创建和客户端的连接,并把 Socket 放入全局等待队列中。紧接着,主线程通过轮询方法把 Socket 连接分配给 IO 线程。</li>
<li>IO 线程读取并解析请求主线程一旦把 Socket 分配给 IO 线程,就会进入阻塞状态,等待 IO 线程完成客户端请求读取和解析。因为有多个 IO 线程在并行处理,所以,这个过程很快就可以完成。</li>
<li>主线程执行请求操作等到 IO 线程解析完请求,主线程还是会以单线程的方式执行这些命令操作。<br><img src="/imgs/Redis/Redis%E4%B8%BB%E7%BA%BF%E7%A8%8B%E5%92%8CIO%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%BA%A4%E4%BA%92.jpg" alt="Redis主线程和IO线程的交互" title="Redis主线程和IO线程的交互"><br>当主线程执行完请求操作后,会把需要返回的结果写入缓冲区,然后,主线程会阻塞等待 IO 线程把这些结果回写到 Socket 中,并返回给客户端。<br>和 IO 线程读取和解析请求一样,IO 线程回写 Socket 时,也是有多个线程在并发执行,所以回写 Socket 的速度也很快。等到 IO 线程回写 Socket 完毕,主线程会清空全局队列,等待客户端的后续请求。<br><img src="/imgs/Redis/Redis%E4%B8%BB%E7%BA%BF%E7%A8%8B%E5%92%8CIO%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%BA%A4%E4%BA%922.jpg" alt="Redis主线程和IO线程的交互2" title="Redis主线程和IO线程的交互2"></li>
</ol>
<h3 id="配置开启多线程"><a href="#配置开启多线程" class="headerlink" title="配置开启多线程"></a>配置开启多线程</h3><p>如果在实际应用Redis的过程中,发现Redis实例的CPU开销不大,吞吐量却没有提升,可以考虑使用Redis6.0的多线程机制来加速网络处理,进而提升实例的吞吐量。</p>
<ol>
<li>设置 io-thread-do-reads 配置项为 yes,表示启用多线程。<br><code>io-threads-do-reads yes</code></li>
<li>设置线程个数。一般来说,<strong>线程个数要小于 Redis 实例所在机器的 CPU 核个数</strong>,例如,对于一个 8 核的机器来说,Redis 官方建议配置 6 个 IO 线程<br><code>io-threads 6</code></li>
</ol>
<h2 id="客户端缓存"><a href="#客户端缓存" class="headerlink" title="客户端缓存"></a>客户端缓存</h2><p>Redis6.0后新增了一个服务端协助的客户端缓存功能,也被称为跟踪(Tracking)功能。<br>本地缓存的主要问题是:怎么和服务端数据保持一致?<br>Tracking功能提供两种模式来解决这个问题:</p>
<ol>
<li>普通模式<br>实例会在服务端记录客户端读取过的 key,并监测 key 是否有修改。一旦 key 的值发生变化,服务端会给客户端发送 invalidate 消息,通知客户端缓存失效了。<br>打开或关闭普通模式下的Tracking功能:<code>CLIENT TRACKING ON|OFF</code></li>
<li>广播模式<br>服务端会给客户端广播所有 key 的失效情况,不过,这样做了之后,如果 key 被频繁修改,服务端会发送大量的失效广播消息,这就会消耗大量的网络带宽资源。</li>
</ol>
<h2 id="NVM"><a href="#NVM" class="headerlink" title="NVM"></a>NVM</h2><p>Redis是基于内存的键值对数据库,因此数据具有易失性,虽然有持久化和主从复制机制,但是由于持久化是异步的,因此也无法完全避免数据丢失问题。<br>近年来的一个趋势是将NVM(新型非易失性存储,Non-Volatile Memory)作为Redis的存储介质,NVM具有容量大、性能快、能持久化保存数据的特性,可以替代内存来使用。</p>
<h3 id="NVM的三个特点"><a href="#NVM的三个特点" class="headerlink" title="NVM的三个特点"></a>NVM的三个特点</h3><ol>
<li>NVM 内存最大的优势是可以直接持久化保存数据<br>DRAM是掉电后数据会丢失,而NVM不会。<br>如果使用NVM来实现持久化,甚至连RDB和AOF也不再需要了(现在的主从复制仍是基于RDB+AOF的,尚不清楚以后是否会有别的特性来支持直接内存的复制)。</li>
<li>NVM 内存的访问速度接近 DRAM 的速度<br>根据一些测试报告,NVM内存的访问速度:读延迟大约是 200<del>300ns,而写延迟大约是 100ns。在读写带宽方面,单根 NVM 内存条的写带宽大约是 1</del>2GB/s,而读带宽约是 5~6GB/s。<br>但我没有条件进行测试。</li>
<li>NVM内存的容量很大<br>NVM 器件的密度大,单个 NVM 的存储单元可以保存更多数据。<br>例如,单根 NVM 内存条就能达到 128GB 的容量,最大可以达到 512GB,而单根 DRAM 内存条通常是 16GB 或 32GB。</li>
</ol>
<h2 id="其他优化点"><a href="#其他优化点" class="headerlink" title="其他优化点"></a>其他优化点</h2><ul>
<li>单进程单线程,无法充分发挥服务器多核 cpu 的性能;大流量下造成 IO 阻塞,同样是由于单进程单线程, cpu 在处理业务逻辑的时候,网络 IO 被阻塞住, 造成无法处理更多的请求.<br>多线程 master + N<em>work 工作模式.master 线程负责监听网络事件, 在接收到一个新的连接后, master 会把新的 fd 注册到 worker 的 epoll 事件中, 交由 worker 处理这个 fd 的所有读写事件, 这样 master 线程就可以完全被释放出来接收更多的连接, 同时又不妨碍 worker 处理业务逻辑和 IO 读写.<br>采用这种 master + N</em>worker 的网络层事件模型,可以实现 redis 性能的平行扩展. 真正的让 redis 在面临高并发请求时可以丛容面对.</li>
<li>维护成本高, 如果想要充分发挥服务器的所有资源包括 cpu, 网络 io 等, 就必须建立多个 instance, 但此时不可避免会增加维护成本. 拿 24 核服务器举例来讲, 如果部署 24 个单机版的 instance,理论上可以实现 10w*24core= 240wQPS 的总体性能.但是每个 instance 有各自独立的数据,占用资源如内存也会同比上升,反过来制约一台服务器又未必能支持这么多的 instance. 如果部署 24 个 Instance 来构成单机集群, 虽然可以共享数据,但是因为节点增加, redis 的状态通讯更加频繁和费时,性能也下会降很多. 并且两种方式都意味着要维护 24 个 Instance,运维成本都会成倍增加. </li>
<li>持久化:redis 提供了两种 save 方式 1)save 触发. 2)bgsave. 当然也可以使用 3)aof 来实现持久化, 但是这 3 点都有弊端.<ul>
<li>save: 由于是单进程单线程, redis 会阻塞住所有请求, 来遍历所有 redisDB, 把 key-val 写入 dump.rdb. 如果内存数据量过大, 会造成短时间几秒到几十秒甚至更长的时间停止服务, 这种方案对于 twitter, taobao 等大流量的网站, 显然是不可取的.</li>
<li>bgsave: 在触发 bgsave 时, redis 会 fork 自身, child 进程会进入 1)的处理方式,这意味着服务器内存要有一半的冗余才可以, 如今内存已变得越来越廉价, 但是对于存储海量数据的情况,内存以及服务器的成本还是不容忽视的.</li>
<li>aof: 说到持久化, redis 提供的 aof 算是最完美的方案了, 但是有得必有失, 严重影响性能! 因为 redis 每接收到一条请求, 就要把命令内容完整的写到磁盘文件, 且不说频繁读写会影响磁盘寿命,写磁盘的时间足以拖垮 redis 整体性能 . 当然熟悉 redis 的开发者会想到用 appendfsync 等参数来调整, 但都不是完美.即使使用 SSD,性能也只是略有提升,并且性价比不高。</li>
</ul>
</li>
<li>优化 jemalloc, 采用大内存页. Redis 在使用内存方面可谓苛刻至极, 压缩, string 转 number 等, 能省就省, 但是在实际生产环境中, 为了追求性能, 对于内存的使用可以适度(不至于如 bgsave 般浪费)通融处理, 因此 AliRedis 对 jemalloc 做了微调, 通过调整 pagesize 来让一次 je_malloc 分配更多 run 空间来储备更多的用户态可用内存, 同时可以减轻换页表的负载, 降低 user sys 的切换频率, 来提高申请内存的性能, 对 jemalloc 有兴趣的开发者可以参考 jemalloc 源码中的 bin, run, chunk 数据结构进行分析.</li>
</ul>
<h1 id="Redis配置"><a href="#Redis配置" class="headerlink" title="Redis配置"></a>Redis配置</h1><h2 id="内存"><a href="#内存" class="headerlink" title="内存"></a>内存</h2><p>因为系统的内存大小有限,所以我们在使用 Redis 的时候可以配置 Redis 能使用的最大的内存大小。<br>redis.conf:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># Redis最大占用内存大小</span><br><span class="line">maxmemory 100mb</span><br></pre></td></tr></table></figure>
<p>通过命令修改</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">127.0.0.1:6379> config set maxmemory 100mb</span><br><span class="line">127.0.0.1:6379> config get maxmemory</span><br></pre></td></tr></table></figure>
<p>如果不设置最大内存大小或设置最大内存大小为 0,在 64 位操作系统下不限制内存大小,在 32 位操作系统下最大使用 3GB 内存。</p>
<h2 id="修改数据库配置"><a href="#修改数据库配置" class="headerlink" title="修改数据库配置"></a>修改数据库配置</h2><p>redis 默认创建 16 个数据库(类似一个数组),默认值对应在 redis.conf 配置文件中 database 的值。<br>默认使用 0 号库,可以使用 select 命令来选择其他库。</p>
<h2 id="过期时间的设置"><a href="#过期时间的设置" class="headerlink" title="过期时间的设置"></a>过期时间的设置</h2><p>如果大量的 key 过期时间设置的过于集中,到过期的那个时间点,redis 可能会出现短暂的卡顿现象。一般需要在时间上加一个随机值,使得过期时间分散一些。</p>
<h2 id="连接设置"><a href="#连接设置" class="headerlink" title="连接设置"></a>连接设置</h2><h3 id="Redis连接配置"><a href="#Redis连接配置" class="headerlink" title="Redis连接配置"></a>Redis连接配置</h3><table>
<thead>
<tr>
<th>参数</th>
<th>含义</th>
<th>建议</th>
</tr>
</thead>
<tbody><tr>
<td>port 16371</td>
<td>指定Redis监听端口,默认端口为6379</td>
<td></td>
</tr>
<tr>
<td>bind 10.56.50.164</td>
<td>绑定的主机地址</td>
<td></td>
</tr>
<tr>
<td>timeout 2000</td>
<td>当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能</td>
<td>在压测时需要修改</td>
</tr>
<tr>
<td>tcp-keepalive 0</td>
<td>redis服务端主动向空闲的客户端发起ack请求,以判断连接是否有效,0表示未启用。定时向client发送tcp_ack包来探测client是否存活的。默认不探测,官方建议值为60秒</td>
<td>建议开启,避免连接意外中断后,服务端不能释放</td>
</tr>
<tr>
<td>maxclients 30000</td>
<td>设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息</td>
<td></td>
</tr>
</tbody></table>
<h3 id="修改最大TCP连接"><a href="#修改最大TCP连接" class="headerlink" title="修改最大TCP连接"></a>修改最大TCP连接</h3><p>1、编辑文件 sudo vim /etc/security/limits.conf ,添加如下内容</p>
<ul>
<li>soft nproc 60240</li>
<li>hard nproc 60240</li>
<li>soft nofile 65535</li>
<li>hard nofile 65535<br>2、编辑文件 vi /etc/pam.d/login,在末尾添加如下内容<br>session required /usr/lib64/security/pam_limits.so<br>3、编辑文件 /etc/pam.d/system-auth ,添加如下内容<br>session required /lib/security/$ISA/pam_limits.so<br>4、重启虚机</li>
</ul>
<h3 id="修改TCP连接等待队列长度"><a href="#修改TCP连接等待队列长度" class="headerlink" title="修改TCP连接等待队列长度"></a>修改TCP连接等待队列长度</h3><p>编辑系统控制文件,加入tcp最长队列参数<br>1、编辑文件 vim /etc/sysctl.conf 添加如下内容<br>net.core.somaxconn=5120<br>2、查看修改<br>sudo sysctl -p<br>3、同步修改<br>sudo sysctl vm.overcommit_memory=1<br>4、关闭透明大页</p>
<ul>
<li>具有sudo权限的用户 (尝试过echo 命令 ,权限不允许)<br>sudo vim /etc/grub2.cfg 文件尾加上<br>transparent_hugepage=never<br>【或者使用root用户执行 echo “transparent_hugepage=never”>> /etc/grub2.cfg 】</li>
<li>root用户<br><code>echo never>/sys/kernel/mm/transparent_hugepage/enabled</code></li>
<li>验证结果 返回 0 说明生效<br>$ grep -i HugePages_Total /proc/meminfo<br>HugePages_Total: 0<br>$ cat /proc/sys/vm/nr_hugepages<br>0</li>
</ul>
<h2 id="持久化"><a href="#持久化" class="headerlink" title="持久化"></a>持久化</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">save 900 1</span><br><span class="line">save 300 10</span><br><span class="line">save 60 10000</span><br></pre></td></tr></table></figure>
<p>指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合<br>save <seconds> <changes><br>分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。<br>建议值:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">save 900 20</span><br><span class="line">save 300 2000</span><br><span class="line">save 60 200000</span><br></pre></td></tr></table></figure>
<table>
<thead>
<tr>
<th>参数</th>
<th>含义</th>
<th>建议</th>
</tr>
</thead>
<tbody><tr>
<td>stop-writes-on-bgsave-error yes</td>
<td>配置项stop-writes-on-bgsave-error no (默认值为yes),即当bgsave快照操作出错时停止写数据到磁盘,这样后面写错做均会失败,为了不影响后续写操作,故需将该项值改为no。</td>
<td>强制关闭Redis快照可能会导致不能持久化。MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk.</td>
</tr>
<tr>
<td>rdbcompression yes</td>
<td>指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大</td>
<td>开启压缩</td>
</tr>
<tr>
<td>rdbchecksum yes</td>
<td>(对rdb数据进行校验,耗费CPU资源,默认为yes)默认值是yes。在存储快照后,让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。</td>
<td>建议关闭</td>
</tr>
<tr>
<td>appendfsync everysec 指定更新日志条件,共有3个可选值:no表示等操作系统进行数据缓存同步到磁盘(快);always表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全);everysec表示每秒同步一次(折衷,默认值)</td>
<td></td>
<td></td>
</tr>
<tr>
<td>no-appendfsync-on-rewrite no</td>
<td>是否在后台写时同步单写,默认值no(表示需要同步).这里的后台写,表示后台正在重写文件(包括bgsave和bgrewriteaof.bgrewriteaof网上很多资料都没有涉及到。其实关掉bgsave之后,主要的即是aof重写文件了).no表示新的主进程的set操作会被阻塞掉,而yes表示新的主进程的set不会被阻塞,待整个后台写完成之后再将这部分set操作同步到aof文件中。但这可能会存在数据丢失的风险(机率很小),如果对性能有要求,可以设置为yes,仅在后台写时会异步处理命令.</td>
<td>压测时建议修改成yes</td>
</tr>
<tr>
<td>auto-aof-rewrite-percentage 100</td>
<td>aof文件增长比例,指当前aof文件比上次重写的增长比例大小。aof重写即在aof文件在一定大小之后,重新将整个内存写到aof文件当中,以反映最新的状态(相当于bgsave)。这样就避免了,aof文件过大而实际内存数据小的问题(频繁修改数据问题).</td>
<td></td>
</tr>
<tr>
<td>auto-aof-rewrite-min-size 64mb</td>
<td>aof文件重写最小的文件大小,即最开始aof文件必须要达到这个文件时才触发,后面的每次重写就不会根据这个变量了(根据上一次重写完成之后的大小).此变量仅初始化启动redis有效.如果是redis恢复时,则lastSize等于初始aof文件大小.</td>
<td></td>
</tr>
<tr>
<td>aof-load-truncated yes</td>
<td>指redis在恢复时,会忽略最后一条可能存在问题的指令。默认值yes。即在aof写入时,可能存在指令写错的问题(突然断电,写了一半),这种情况下,yes会log并继续,而no会直接恢复失败.</td>
<td></td>
</tr>
</tbody></table>
<h2 id="主从配置"><a href="#主从配置" class="headerlink" title="主从配置"></a>主从配置</h2><table>
<thead>
<tr>
<th>参数</th>
<th>含义</th>
<th>建议</th>
</tr>
</thead>
<tbody><tr>
<td>slave-serve-stale-data yes</td>
<td>slave-serve-stale-data参数设置成yes,主从复制中,从服务器可以响应客户端请求</td>
<td></td>
</tr>
<tr>
<td>slave-read-only yes</td>
<td>如果为 yes,代表为只读状态,但并不表示客户端用集群方式以从节点为入口连入集群时,不可以进行 set 操作,且 set 操作的数据不会被放在从节点的槽上,会被放到某主节点的槽上</td>
<td></td>
</tr>
<tr>
<td>repl-diskless-sync no</td>
<td>一个RDB文件从master端传到slave端,分为两种情况:1、支持disk:master端将RDB file写到disk,稍后再传送到slave端;2、无磁盘diskless:master端直接将RDB file传到slave socket,不需要与disk进行交互。</td>
<td></td>
</tr>
<tr>
<td>无磁盘diskless方式适合磁盘读写速度慢但网络带宽非常高的环境。repl-diskless-sync no 默认不使用diskless同步方式</td>
<td></td>
<td></td>
</tr>
<tr>
<td>repl-diskless-sync-delay 5</td>
<td>无磁盘diskless方式在进行数据传递之前会有一个时间的延迟,以便slave端能够进行到待传送的目标队列中,这个时间默认是5秒</td>
<td></td>
</tr>
<tr>
<td>repl-disable-tcp-nodelay no</td>
<td>是否启用TCP_NODELAY,如果启用则会使用少量的TCP包和带宽去进行数据传输到slave端,当然速度会比较慢;如果不启用则传输速度比较快,但是会占用比较多的带宽。</td>
<td></td>
</tr>
<tr>
<td>slave-priority 100</td>
<td>slave端的优先级设置,值是一个整数,数字越小表示优先级越高。当master故障时将会按照优先级来选择slave端进行恢复,如果值设置为0,则表示该slave永远不会被选择。</td>
<td></td>
</tr>
</tbody></table>
<h1 id="Redis-使用规范"><a href="#Redis-使用规范" class="headerlink" title="Redis 使用规范"></a>Redis 使用规范</h1><p>来自:《<a target="_blank" rel="noopener" href="https://time.geekbang.org/column/article/309089">加餐(六)| Redis的使用规范小建议</a>》</p>
<h2 id="业务层面"><a href="#业务层面" class="headerlink" title="业务层面"></a>业务层面</h2><p>1、key 的长度尽量短,节省内存空间<br>2、避免 bigkey,防止阻塞主线程<br>3、4.0+版本建议开启 lazy-free<br>4、把 Redis 当作缓存使用,设置过期时间<br>5、不使用复杂度过高的命令,例如SORT、SINTER、SINTERSTORE、ZUNIONSTORE、ZINTERSTORE<br>6、查询数据尽量不一次性查询全量,写入大量数据建议分多批写入<br>7、批量操作建议 MGET/MSET 替代 GET/SET,HMGET/HMSET 替代 HGET/HSET<br>8、禁止使用 KEYS/FLUSHALL/FLUSHDB 命令<br>9、避免集中过期 key<br>10、根据业务场景选择合适的淘汰策略<br>11、使用连接池操作 Redis,并设置合理的参数,避免短连接<br>12、只使用 db0,减少 SELECT 命令的消耗<br>13、读请求量很大时,建议读写分离,写请求量很大,建议使用切片集群</p>
<h2 id="运维层面"><a href="#运维层面" class="headerlink" title="运维层面"></a>运维层面</h2><p>1、按业务线部署实例,避免多个业务线混合部署,出问题影响其他业务<br>2、保证机器有足够的 CPU、内存、带宽、磁盘资源<br>3、建议部署主从集群,并分布在不同机器上,slave 设置为 readonly<br>4、主从节点所部署的机器各自独立,尽量避免交叉部署,对从节点做维护时,不会影响到主节点<br>5、推荐部署哨兵集群实现故障自动切换,哨兵节点分布在不同机器上<br>6、提前做好容量规划,防止主从全量同步时,实例使用内存突增导致内存不足<br>7、做好机器 CPU、内存、带宽、磁盘监控,资源不足时及时报警,任意资源不足都会影响 Redis 性能<br>8、实例设置最大连接数,防止过多客户端连接导致实例负载过高,影响性能<br>9、单个实例内存建议控制在 10G 以下,大实例在主从全量同步、备份时有阻塞风险<br>10、设置合理的 slowlog 阈值,并对其进行监控,slowlog 过多需及时报警<br>11、设置合理的 repl-backlog,降低主从全量同步的概率<br>12、设置合理的 slave client-output-buffer-limit,避免主从复制中断情况发生<br>13、推荐在从节点上备份,不影响主节点性能<br>14、不开启 AOF 或开启 AOF 配置为每秒刷盘,避免磁盘 IO 拖慢 Redis 性能<br>15、调整 maxmemory 时,注意主从节点的调整顺序,顺序错误会导致主从数据不一致<br>16、对实例部署监控,采集 INFO 信息时采用长连接,避免频繁的短连接<br>17、做好实例运行时监控,重点关注 expired_keys、evicted_keys、latest_fork_usec,这些指标短时突增可能会有阻塞风险<br>18、扫描线上实例时,记得设置休眠时间,避免过高 OPS 产生性能抖动</p>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/kity.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/kityminder.core.min.js"></script><script defer="true" type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/mindmap.min.js"></script><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/mindmap.min.css">
</div>
<footer class="post-footer">
<div class="post-tags">
<a href="/tags/Redis/" rel="tag"># Redis</a>
</div>
<div class="post-nav">
<div class="post-nav-item">
<a href="/1942bbd0.html" rel="prev" title="Redis作为缓存系统">
<i class="fa fa-angle-left"></i> Redis作为缓存系统
</a>
</div>
<div class="post-nav-item">
<a href="/f5668bf0.html" rel="next" title="分布式系统的设计原理">
分布式系统的设计原理 <i class="fa fa-angle-right"></i>
</a>
</div>
</div>
</footer>
</article>
</div>
</div>
</main>
<footer class="footer">
<div class="footer-inner">
<div class="copyright">
©
<span itemprop="copyrightYear">2025</span>
<span class="with-love">
<i class="fa fa-heart"></i>
</span>
<span class="author" itemprop="copyrightHolder">tallate</span>
</div>
<div class="powered-by">由 <a href="https://hexo.io/" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/" rel="noopener" target="_blank">NexT.Gemini</a> 强力驱动
</div>
</div>
</footer>
<div class="back-to-top" role="button" aria-label="返回顶部">
<i class="fa fa-arrow-up fa-lg"></i>
<span>0%</span>
</div>
<a href="https://github.com/tallate" class="github-corner" title="在 GitHub 上关注我" aria-label="在 GitHub 上关注我" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>
<noscript>
<div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/next-boot.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hexo-generator-searchdb/1.4.1/search.js" integrity="sha256-1kfA5uHPf65M5cphT2dvymhkuyHPQp5A53EGZOnOLmc=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>
<script class="next-config" data-name="mermaid" type="application/json">{"enable":true,"version":"7.1.2","options":null,"js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.3.0/mermaid.min.js","integrity":"sha256-9y71g5Lz/KLsHjB8uXwnkuWDtAMDSzD/HdIbqhJfTAI="}}</script>
<script src="/js/third-party/tags/mermaid.js"></script>
</body>
</html>