如何保證Redis性能與安全?看這篇Redis數(shù)據(jù)庫性能測試及安全優(yōu)化配置指南就夠了

本章目錄
0x00 Redis 性能指標監(jiān)控

(1) 性能指標

1.基本活動指標:Basic activity
2.性能指標:Performance
3.內存指標: Memory
4.持久性指標: Persistence
5.錯誤指標:Error
6.其他指標說明

(2) 性能測試工具

1.redis-benchmark 命令
2.redisbench 工具
3.rdb 內存分析工具

(3) 基準測試實踐

3.1 K8s中單實例redis測試

0x01 Redis 安全優(yōu)化

1.Security

非特權運行
文件權限
接口綁定
更改默認服務端口
認證配置
禁用特定命令
日志記錄
防范字符串轉義和 NoSQL 注入
防范由外部客戶端精心挑選的輸入觸發(fā)的攻擊
防火墻限制訪問
禁止redis中存儲敏感的明文數(shù)據(jù)
Redis 安全配置總結示例

2.Performance Optimization

關鍵優(yōu)化項
Redis 性能優(yōu)化總結示例


前置知識學習補充
1.Redis數(shù)據(jù)庫基礎入門介紹與安裝 - https://blog.weiyigeek.top/2019/4-17-49.html

2.Redis數(shù)據(jù)庫基礎數(shù)據(jù)類型介紹與使用 - https://blog.weiyigeek.top/2020/5-17-50.html

3.Redis基礎運維之原理介紹和主從配置 - https://blog.weiyigeek.top/2019/4-17-97.html

4.Redis基礎運維之哨兵和集群安裝配置 - https://blog.weiyigeek.top/2019/4-17-576.html

5.Redis基礎運維之在K8S中的安裝與配置 - https://blog.weiyigeek.top/2019/4-17-524.html

7.Redis數(shù)據(jù)庫容災備份企業(yè)實戰(zhàn) - https://blog.weiyigeek.top/2019/4-17-51.html

8.Redis數(shù)據(jù)庫客戶端操作實踐及入坑出坑 - https://blog.weiyigeek.top/2019/4-17-577.html


0x00 Redis 性能指標監(jiān)控

(1) 性能指標

Redis 服務端常見指標參數(shù):

redis-cli -a password info > redis-Performance.txt # 我們可以將redis服務端info相關信息導出到文件之中
  # 2.clients:
  # 3.memory:
  # 4.persistence:
  # 5.stats:通用統(tǒng)計數(shù)據(jù)
  # 6.Replication:
  # 7.CPU:CPU使用情況
  # 8.cluster:
  # 9.Keypass:鍵值對統(tǒng)計數(shù)量信息
  
10.20.172.108:6379> info  # (1) Redis 服務端信息交互式查看
# Server 服務器運行的環(huán)境參數(shù)
redis_version:6.2.5
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:cb556a016f8668d
redis_mode:standalone
os:Linux 5.11.0-25-generic x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:c11-builtin
gcc_version:9.3.0
process_id:187640
process_supervised:no
run_id:97838216d4fe0de4739e7814b5a2e1d0d32d0982
tcp_port:6379
server_time_usec:1630241617439942
uptime_in_seconds:10930
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:2851665
executable:/opt/databases/redis-6.2.5/src/./redis-server
config_file:/home/weiyigeek/redis/6379/redis-6379.conf
io_threads_active:0

# Clients 客戶端相關信息
connected_clients:7
cluster_connections:0
maxclients:10000
client_recent_max_input_buffer:32
client_recent_max_output_buffer:0
blocked_clients:0
tracking_clients:0
clients_in_timeout_table:0

# Memory 服務器運行內存統(tǒng)計數(shù)據(jù)
used_memory:2050432
used_memory_human:1.96M
used_memory_rss:5140480
used_memory_rss_human:4.90M
used_memory_peak:2253512
used_memory_peak_human:2.15M
used_memory_peak_perc:90.99%
used_memory_overhead:1982152
used_memory_startup:810376
used_memory_dataset:68280
used_memory_dataset_perc:5.51%
allocator_allocated:2204376
allocator_active:2555904
allocator_resident:5230592
total_system_memory:12442619904
total_system_memory_human:11.59G
used_memory_lua:37888
used_memory_lua_human:37.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.16
allocator_frag_bytes:351528
allocator_rss_ratio:2.05
allocator_rss_bytes:2674688
rss_overhead_ratio:0.98
rss_overhead_bytes:-90112
mem_fragmentation_ratio:2.59
mem_fragmentation_bytes:3153776
mem_not_counted_for_evict:124
mem_replication_backlog:1048576
mem_clients_slaves:0
mem_clients_normal:123000
mem_aof_buffer:128
mem_allocator:jemalloc-5.1.0
active_defrag_running:0
lazyfree_pending_objects:0
lazyfreed_objects:0

# Persistence 持久化數(shù)據(jù)相關信息
loading:0
current_cow_size:0
current_cow_size_age:0
current_fork_perc:0.00
current_save_keys_processed:0
current_save_keys_total:0
rdb_changes_since_last_save:3
rdb_bgsave_in_progress:0
rdb_last_save_time:1630230687
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:-1
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:0
aof_enabled:1
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:0
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:462848
module_fork_in_progress:0
module_fork_last_cow_size:0
aof_current_size:150
aof_base_size:92
aof_pending_rewrite:0
aof_buffer_length:0
aof_rewrite_buffer_length:0
aof_pending_bio_fsync:0
aof_delayed_fsync:0

# Stats 通用統(tǒng)計數(shù)據(jù)信息
total_connections_received:25
total_commands_processed:50482
instantaneous_ops_per_sec:4
total_net_input_bytes:2758703
total_net_output_bytes:22330756
instantaneous_input_kbps:0.23
instantaneous_output_kbps:0.55
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
expired_stale_perc:0.00
expired_time_cap_reached_count:0
expire_cycle_cpu_milliseconds:0
evicted_keys:0
keyspace_hits:1
keyspace_misses:0
pubsub_channels:1
pubsub_patterns:0
latest_fork_usec:310
total_forks:1
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0
tracking_total_keys:0
tracking_total_items:0
tracking_total_prefixes:0
unexpected_error_replies:0
total_error_replies:8
dump_payload_sanitizations:0
total_reads_processed:48899
total_writes_processed:97139
io_threaded_reads_processed:0
io_threaded_writes_processed:0

# Replication 主從相關指標信息
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:32da05299a5a36de431b4c05122f7d2b93eca169
master_replid2:3e15749ad586d60bd0d1c93854f6f719a22316ce
master_repl_offset:8915
second_repl_offset:829
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:8915

# CPU 處理器模式占用信息
used_cpu_sys:12.012184
used_cpu_user:9.453505
used_cpu_sys_children:0.002158
used_cpu_user_children:0.000000
used_cpu_sys_main_thread:11.802969
used_cpu_user_main_thread:9.286577

# Modules 模塊加載情況

# Errorstats 錯誤狀態(tài)信息
errorstat_NOAUTH:count=6
errorstat_READONLY:count=1
errorstat_WRONGPASS:count=1

# Cluster 集群信息
cluster_enabled:0

# Keyspace 庫id與鍵數(shù)量相關信息
db0:keys=1,expires=0,avg_ttl=0


1.基本活動指標:Basic activity

Name Description
connected_clients 客戶端連接數(shù)
conected_laves slave數(shù)量
master_last_io_seconds_ago 最近一次主從交互之后的秒數(shù)
keyspace 數(shù)據(jù)庫中的key值總數(shù)
grep -En "connected_clients|conected_laves|master_last_io_seconds_ago|keyspace" redis-Performance.txt
27:connected_clients:7 # # 客戶端連接數(shù)量
28:connected_slaves:1  # # slave連接數(shù)量
128:keyspace_hits:1
129:keyspace_misses:0


2.性能指標:Performance

Name Description
latency Redis響應一個請求的時間
instantaneous_ops_per_sec 平均每秒處理請求總數(shù)
hi rate(calculated) 緩存命中率(計算出來的)
grep -En "latency|instantaneous_ops_per_sec|hi rate" redis-Performance.txt
114:instantaneous_ops_per_sec:3


3.內存指標: Memory

Name Description
used_memory 已使用內存
mem_fragmentation_ratio 內存碎片率
evicted_keys 由于最大內存限制被移除的key的數(shù)量
blocked_clients 由于BLPOP,BRPOP,or BRPOPLPUSH而備阻塞的客戶端
grep -En "used_memory|mem_fragmentation_ratio|evicted_keys|blocked_clients" redis-Performance.txt
32:blocked_clients:0
37:used_memory:2050432
38:used_memory_human:1.96M      # # 內存分配器從操作系統(tǒng)分配的內存總量
39:used_memory_rss:5234688     
40:used_memory_rss_human:4.99M  # # 操作系統(tǒng)看到的內存占用,top命令看到的內存
41:used_memory_peak:2253512
42:used_memory_peak_human:2.15M # # redis內存消耗的峰值
43:used_memory_peak_perc:90.99%
44:used_memory_overhead:1982152
45:used_memory_startup:810376
46:used_memory_dataset:68280
47:used_memory_dataset_perc:5.51%
53:used_memory_lua:37888
54:used_memory_lua_human:37.00K #  # lua腳本引擎占用的內存大小
55:used_memory_scripts:0
56:used_memory_scripts_human:0B
67:mem_fragmentation_ratio:2.63
127:evicted_keys:0

4.持久性指標: Persistence

Name Description
rdb_last_save_time 最后一次持久化保存磁盤的時間戳
rdb_changes_sice_last_save 自最后一次持久化以來數(shù)據(jù)庫的更改數(shù)
grep -En "rdb_last_save_time|rdb_changes_sice_last_save" redis-Performance.txt
88:rdb_last_save_time:1630230687
89:rdb_changes_since_last_save:0   # 自最后一次持久化以來數(shù)據(jù)庫的更改數(shù)

5.錯誤指標:Error

Name Description
rejected_connections 由于達到maxclient限制而被拒絕的連接數(shù)
keyspace_misses key值查找失敗(沒有命中)次數(shù)
master_link_down_since_seconds 主從斷開的持續(xù)時間(以秒為單位)
grep -En "rejected_connections|master_link_down_since_seconds" redis-Performance.txt
9:master_link_down_since_seconds:10937
119:rejected_connections:0
keyspace_misses:0    # key值查找失敗(沒有命中)次數(shù)策严,出現(xiàn)多次可能是被Hacker Attack


6.其他指標說明

# 1.復制積壓緩沖區(qū)如果設置得太小灶似,會導致里面的指令被覆蓋掉找不到偏移量,從而觸發(fā)全量同步
repl_backlog_size: 1048576

# 2.通過查看sync_partial_err變量的次數(shù)來決定是否需要擴大積壓緩沖區(qū)舌稀,它表示主從半同步復制失敗的次數(shù)
sync_partial_err:1


(2) 性能測試工具

1.redis-benchmark 命令

描述: Redis 性能測試是通過同時執(zhí)行多個命令實現(xiàn)的,該命令是在 redis 的目錄下執(zhí)行的;

官網(wǎng)參考: https://redis.io/topics/benchmarks

語法參數(shù):

Usage: redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests]> [-k <boolean>]

# 參數(shù)說明:
 -h <hostname>      Server hostname (default 127.0.0.1)
 -p <port>          Server port (default 6379)
 -s <socket>        Server socket (overrides host and port)
 -a <password>      Password for Redis Auth
 -c <clients>       Number of parallel connections (default 50)
 -n <requests>      Total number of requests (default 100000)
 -d <size>          Data size of SET/GET value in bytes (default 2)
 --dbnum <db>       SELECT the specified db number (default 0)
 -k <boolean>       1=keep alive 0=reconnect (default 1)
 -r <keyspacelen>   對SET/GET/INCR使用隨機鍵联喘,對SADD使用隨機值使用此選項基準將擴展參數(shù)內的字符串_rand_int _uu),該參數(shù)的指定范圍為0到keyspacelen-1之間的12位數(shù)字逗载。
 -P <numreq>        Pipeline <numreq> requests. Default 1 (no pipeline).
 -q                 Quiet. Just show query/sec values
 --csv              Output in CSV format
 -l                 Loop. Run the tests forever
 -t <tests>         Only run the comma separated list of tests. The test names are the same as the ones produced as output.
 -I                 Idle mode. Just open N idle connections and wait.


基礎實例:

# (1) 同時執(zhí)行 10000 個請求來檢測性能(所有默認測試),通過 -q 參數(shù)讓結果只顯示每秒執(zhí)行的請求數(shù)
$ ./redis-benchmark -h 127.0.0.1 -p 6379 -t set,lpush -n 10000 -q
$ ./redis-benchmark -n 10000  -q 
   # PING_INLINE: 41493.78 requests per second
   # PING_BULK: 44843.05 requests per second
   # SET: 42194.09 requests per second
   # GET: 44052.86 requests per second
   # INCR: 43290.04 requests per second
   # LPUSH: 42194.09 requests per second
   # RPUSH: 42372.88 requests per second
   # LPOP: 42194.09 requests per second
   # RPOP: 42194.09 requests per second
   # SADD: 43668.12 requests per second
   # HSET: 42372.88 requests per second
   # SPOP: 44843.05 requests per second
   # LPUSH (needed to benchmark LRANGE): 42553.19 requests per second
   # LRANGE_100 (first 100 elements): 21367.52 requests per second
   # LRANGE_300 (first 300 elements): 9451.80 requests per second
   # LRANGE_500 (first 450 elements): 6807.35 requests per second
   # LRANGE_600 (first 600 elements): 5350.46 requests per second
   # MSET (10 keys): 36363.64 requests per second

# (2) 運行指定項目的測試批什,例如我們要求在安靜模式下僅運行測試 SET 和 LPUSH 命令
$ redis-benchmark -t set,lpush -n 100000 -q
  # SET: 74239.05 requests per second
  # LPUSH: 79239.30 requests per second


# (3) 指定eval腳本命令進行基準測試
$ redis-benchmark -n 100000 -q script load "redis.call('set','foo','bar')"
  # script load redis.call('set','foo','bar'): 69881.20 requests per second

# (4) 選擇密鑰空間的大小,默認情況下基準測試針對單個密鑰運行,而我們通撑┣可以通過使用大鍵來模擬更真實的工作負載空間。
# 例如,如果我想運行 100 萬次 SET 操作乳规,在 10 萬個可能的密鑰中為每個操作使用一個隨機密鑰形葬,
$ redis-cli flushall
$ redis-benchmark -t set -r 100000 -n 1000000

# (5) 默認情況下,每個客戶端僅在收到上一個命令的回復時發(fā)送下一個命令, Redis 支持流水線暮的,因此可以一次發(fā)送多個命令可以想象為并行笙以。
# 例如: 使用 16 個命令的流水線在 MacBook Air 11" 中運行基準測試
redis-benchmark -n 1000000 -t set,get -P 16 -q
  # SET: 403063.28 requests per second
  # GET: 508388.41 requests per second

# (6) 使用 Unix 域套接字形式進行基準測試
$ numactl -C 6 ./redis-benchmark -q -n 100000 -s /tmp/redis.sock -d 256

# (7) 使用 使用 TCP loopback
$ numactl -C 6 ./redis-benchmark -q -n 100000 -d 256

WeiyiGeek.redis-benchmark


在Redis、Memcached內存數(shù)據(jù)庫基準測試對比:

#!/bin/bash

# BIN=./redis-benchmark
BIN=./mc-benchmark
payload=32
iterations=100000
keyspace=100000

for clients in 1 5 10 20 30 40 50 60 70 80 90 100 200 300
do
    SPEED=0
    for dummy in 0 1 2
    do
        S=$($BIN -n $iterations -r $keyspace -d $payload -c $clients | grep 'per second' | tail -1 | cut -f 1 -d'.')
        if [ $(($S > $SPEED)) != "0" ]
        then
            SPEED=$S
        fi
    done
    echo "$clients $SPEED"
done

最后以下是使用gnuplot生成的圖形形式的結果:

WeiyiGeek.Redis冻辩、Memcached內存數(shù)據(jù)庫基準測試


影響基準測試要素

    1. 工作負載(連接的客戶端的數(shù)量)
    1. 不同版本的Redis
    1. 提供服務的服務器物理配置(磁盤猖腕、網(wǎng)絡、CPU恨闪、內存)倘感,在多 CPU 插槽服務器上,Redis 性能取決于 NUMA 配置和進程位置咙咽。
# 不同虛擬化和裸機服務器上的基準測試結果老玛。
* 該測試由 50 個同時執(zhí)行 200 萬個請求的客戶端完成。
* 使用環(huán)回接口執(zhí)行測試犁珠。
* 使用 100 萬個密鑰的密鑰空間執(zhí)行測試逻炊。
* 測試在使用和不使用流水線(16 個命令流水線)的情況下執(zhí)行互亮。

# Intel(R) Xeon(R) CPU E5520 @ 2.27GHz(帶流水線)/ (無流水線)
$ ./redis-benchmark -r 1000000 -n 2000000 -t get,set,lpush,lpop -P 16 -q # 優(yōu)于無流水線犁享。
  SET: 552028.75 requests per second
  GET: 707463.75 requests per second
  LPUSH: 767459.75 requests per second
  LPOP: 770119.38 requests per second

$ ./redis-benchmark -r 1000000 -n 2000000 -t get,set,lpush,lpop -q
  SET: 122556.53 requests per second
  GET: 123601.76 requests per second
  LPUSH: 136752.14 requests per second
  LPOP: 132424.03 requests per second
    1. 與使用相同硬件不使用虛擬化的情況相比,Redis 在 VM 上運行速度較慢(推薦物理機按照Redis為首選)
    1. 根據(jù)平臺的不同豹休,unix 域套接字可以實現(xiàn)比 TCP/IP 環(huán)回(例如在 Linux 上)多約 50% 的吞吐量炊昆。
    1. 與 TCP/IP 環(huán)回相比,Unix 域套接字的性能優(yōu)勢在大量使用流水線(即長流水線)時趨于降低威根。
    1. 當使用以太網(wǎng)網(wǎng)絡訪問 Redis 時凤巨,當數(shù)據(jù)大小保持在以太網(wǎng)數(shù)據(jù)包大小(約 1500 字節(jié))以下時洛搀,使用流水線聚合命令特別有效, 在處理 10 字節(jié)敢茁、100 字節(jié)或 1000 字節(jié)的查詢幾乎會產(chǎn)生相同的吞吐量。


2.redisbench 工具

描述: 官方推薦的redis-benchmark在進行集群的基準測試時留美,沒有辦法指定集群模式彰檬,此處引入 Redis & Redis Cluster benchmark Tool 更方便對集群基準測試的處理。下載地址: https://github.com/panjiang/redisbench


redisbench 特點

  • 以 Golang 開發(fā)構建
  • 可以測試redis單實例
  • 可以測試redis集群
  • 可以利用多核
  • 支持同時在多臺機器上運行谎砾,用于測試大型redis集群(需要相同的機器硬件)


格式語法:

./redisbench -h
-a string   #Redis instance address or Cluster addresses. IP:PORT[,IP:PORT]
-c int      #Clients number for concurrence (default 1)
-cluster    #true: cluster mode, false: instance mode
-d int      #Data size in bytes (default 1000)
-ma string  #addresses for run multiple testers at the same time
-mo int     #the order current tester is in multiple testers
-n int      #Testing times at every client (default 1)


基礎示例:

# 測試單實例模式
./redisbench -a 127.0.0.1:6379 -c 200 -n 20000 -d 3

# 測試集群
./redisbench -cluster=true -a 192.168.1.11:6379,192.168.1.11:6380 -c 500 -n 2000 -d 3

# 使用多個測試節(jié)點
./redisbench -cluster=true -a 192.168.1.11:6379,192.168.1.11:6380 -c 500 -n 2000 -d 3 -ma 192.168.1.11:9001,192.168.1.11:9002,192.168.1.11:9003 -mo 1 &
./redisbench -cluster=true -a 192.168.1.11:6379,192.168.1.11:6380 -c 500 -n 2000 -d 3 -ma 192.168.1.11:9001,192.168.1.11:9002,192.168.1.11:9003 -mo 2 &
./redisbench -cluster=true -a 192.168.1.11:6379,192.168.1.11:6380 -c 500 -n 2000 -d 3 -ma 192.168.1.11:9001,192.168.1.11:9002,192.168.1.11:9003 -mo 3

Tips: 測試結果會自動打印出:請求值逢倍,請求時間,TPS 此處不實際演示使用了景图,感興趣的朋友可以自行下載測試较雕。


3.rdb 內存分析工具

描述: RDR 是解析 redis rdbfile 工具。與redis-rdb-tools相比挚币,RDR 是由golang 實現(xiàn)的亮蒋,速度更快扣典。

  • 分析 Redis 內存中那個 Key 值占用的內存最多
  • 分析出 Redis 內存中那一類開頭的 Key 占用最多,有利于內存優(yōu)化
  • Redis Key 值以 Dashboard 展示慎玖,這樣更直觀

安裝下載地址: https://github.com/xueqiu/rdr/releases

注意事項:

  • 1.linux和windows使用前先添加可執(zhí)行權限 chmod +x rdr_linux

基礎語法:

# RDR 參數(shù)解釋
show 網(wǎng)頁顯示 rdbfile 的統(tǒng)計信息
keys 從 rdbfile 獲取所有 key
help 幫助

基礎實例(以Linux為例):

#1.分析統(tǒng)計多個 Redis rdb中各種類型的使用占比 
./rdr-linux keys *.rdb
SEARCH:PROJECTS_BY_ID:68
SEARCH:PROJECTS_BY_ID:64
SEARCH:PROJECTS_BY_PARENTID_LIST:0
SEARCH:PROJECTS_BY_PARENTID_LIST:64
SEARCH:PROJECTS_BY_PARENTID_LIST:66
SEARCH:PROJECTS_BY_PARENTID_LIST:68
SEARCH:PROJECTS_BY_ID:66
SEARCH:PROJECTSINFO_BY_PARENTID_LIST:64
ALLOW:SEARCH_BY_SFZH:230103197805153637

./rdr-linux dump dump.rdb
{"CurrentInstance": "dump.rdb",
"LargestKeyPrefixes": {
   "list": [
   {
      "Type": "list",
      "Key": "site",
      "Bytes": 144,
      "Num": 1
   }
],


#2.網(wǎng)頁顯示分析結果
./rdr-linux show -p 8080 *.rdb
start parsing...
parse dump.rdb  done
parsing finished, please access http://{$IP}:8080


(3) 基準測試實踐

3.1 K8s中單實例redis測試

環(huán)境說明:

# 運行該Pod的主機節(jié)點
osImage: Ubuntu 20.04.1 LTS
kernelVersion: 5.4.0-42-generic
kubeProxyVersion: v1.19.6
kubeletVersion: v1.19.6
containerRuntimeVersion: docker://19.3.14

$ Server 相關信息
redis_version:6.2.5
os:Linux 5.4.0-42-generic x86_64
arch_bits:64
gcc_version:10.3.1
process_id:1
process_supervised:no
tcp_port:6379
hz:10
configured_hz:10
lru_clock:3627023
io_threads_active:0

$ redis 配置的內存限額
maxmemory:1073741824
maxmemory_human:1.00G
maxmemory_policy:volatile-lru

$ cpu 相關信息
Model name: Intel(R) Xeon(R) CPU E3-1220 V2 @ 3.10GHz
物理CPU數(shù): 1
邏輯CPU數(shù): 4
CPU核心數(shù): 4


基準測試:

# 測試1.執(zhí)行1千萬次set命令與get命令激捏,其中每次讀取得大小為256字節(jié), 請求客戶端數(shù)默認50。
~$ redis-benchmark -h 10.102.39.181 -a 123456 -d 256 -t set,get -n 10000000 -q                            
SET: 42445.36 requests per second
GET: 49504.70 requests per second
# - 測試時 Pod 資源峰值
very 1.0s: kubectl top pod -n database redis-cm-0  Tue Sep  7 20:36:50 2021
NAME         CPU(cores)   MEMORY(bytes)
redis-cm-0   848          18Mi

# 測試2.同樣執(zhí)行1千萬次set命令與get命令凄吏,其中每次讀取得大小為256字節(jié)远舅,唯一不同的是采用 流水線 -P 16 進行測試(可以看出每秒set、get請求數(shù)顯著提升)痕钢。
~$ redis-benchmark -h 10.102.39.181 -a 123456 -d 256 -t set,get -n 10000000 -P 16 -q                            
SET: 96019.98 requests per second
GET: 316575.91 requests per second

# - 測試時 Pod 資源峰值
very 1.0s: kubectl top pod -n database redis-cm-0  Tue Sep  7 20:46:50 2021
NAME         CPU(cores)   MEMORY(bytes)
redis-cm-0   457m         337Mi


實踐測試

    1. 通過shell pipe 與 redis pipe插入10萬數(shù)據(jù)進行對比
## Shell-pipe.sh
#!/bin/bash
echo "開始時間: $(date +%s)"
for ((i=0;i<100000;i++));do
  echo -en "helloworld-redis-${i}" | redis-cli -h 10.102.39.181 --no-auth-warning -a 123456 -x set username${i} >> ok.txt
done
echo "完成時間: $(date +%s)"

## redis-pipe.sh
#!/bin/bash
echo "開始時間: $(date +%s)"
python3 redis-set.py >> set-command.txt
cat set-command.txt | redis-cli -h 10.102.39.181 -a 123456 --no-auth-warning --pipe
echo "完成時間: $(date +%s)"

## redis-set.py
tee redis-set.py <<'EOF'
#!/usr/bin/python
for i in range(100000):
  print('set name'+str(i)+' helloworld-redis-'+str(i))
EOF
    1. 利用time命令記錄了腳本插入的執(zhí)行效率
## redis pipe 方式插入數(shù)據(jù)
~/k8s/benchmark$ time ./redis-pipe.sh
  # 開始時間:1631020862
  # All data transferred. Waiting for the last reply...
  # Last reply received from server.
  # errors: 0, replies: 100000
  # 完成時間: 1631020862

  # real    0m0.466s
  # user    0m0.126s
  # sys     0m0.035s

# Keyspace
db0:keys=100000,expires=0,avg_ttl=0

## shell pipe 方式插入數(shù)據(jù)
~/k8s/benchmark$ time ./shell-pip.sh
  # 開始時間: 1631021312
  # 完成時間: 1631021921
  # real    10m9.265s # 程序開始至結束總用時(包括CPU)图柏。
  # user    3m44.411s # 程序本身以及調用子進程的時間。
  # sys     1m55.435s # 由程序本身或者間接調用的系統(tǒng)調用執(zhí)行時間任连。
# Keyspace
db0:keys=200000,expires=0,avg_ttl=0

Tips : 可以從上面的結果看出兩種方式real總耗時量相差之巨大蚤吹,redis pipe方式效率相比較普通shell pipe方式不是一個量級,所以在開發(fā)程序中盡量使用redis pipe管道方式進行提交數(shù)據(jù)随抠。

# 為了方便后續(xù)演示裁着,握又向數(shù)據(jù)庫中插入了80W條數(shù)據(jù),只用了大約4s拱她。
開始時間: 1631022423
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 800000
完成時間: 1631022427
real    0m4.023s
user    0m0.885s
sys     0m0.187s

0x01 Redis 安全優(yōu)化

1.Security

描述: Redis提供的訪問控制二驰、代碼安全問題、選擇惡意輸入可從外部觸發(fā)的攻擊等功能秉沼,需要我們運維人員進行相應的配置提高安全性桶雀。

非特權運行

描述: Redis 不需要 root 權限即可運行,建議以僅用于此目的的非特權redis用戶身份運行它唬复,此種方式能最大程度防止CONFIG SET/GET 目錄和其他類似運行時配置指令的可能性矗积。。

#設置一個單獨的redis賬戶很有必要敞咧,redis crackit就利用到了root用戶的特性來重置authorized_keys棘捣。首先創(chuàng)建一個redis賬戶,然后通過該賬戶啟動休建。
$ useradd redis
$ setsid sudo -u redis redis-server /etc/redis.conf
$ ps -elf|grep redis   #可以看到是redis用戶啟動
  # 4 S root      9048     1  0  80   0 - 59753 poll_s 19:43 ?        00:00:00 sudo -u redis redis-server /etc redis.conf
  # 4 S redis     9049  9048  0  80   0 - 38471 ep_pol 19:43 ?        00:00:00 redis-server 


文件權限

描述: 因為redis密碼明文存儲在配置文件中乍恐,所以我們需要限制redis文件目錄訪問權限,如設置redis的主目錄權限為700(rwx------),如果redis.conf配置文件獨立于redis主目錄權限修過為600(rw-------)丰包。

# 文件權限
chmod 700 /opt/redis/redis-5.0.4/
chmod 600 /etc/redis.conf

# 所屬者禁熏、組
chown redis:redis /etc/redis.conf
chown redis:redis /opt/redis/redis-5.0.4/


接口綁定

描述: 除了網(wǎng)絡中受信任的客戶端之外,每個人都應該拒絕訪問 Redis 端口邑彪,因此運行 Redis 的服務器應該只能由使用 Redis 實現(xiàn)應用程序的計算機直接訪問瞧毙。

假如服務器有兩個網(wǎng)絡接口(一個A區(qū)域、一個B區(qū)域),如果只需要A區(qū)域的機器訪問則只綁定到A區(qū)域網(wǎng)絡接口中宙彪,如服務器自身訪問則只綁定到本地回環(huán)接口上矩动。

# 通過在redis.conf文件中添加如下一行,可以將 Redis 綁定到單個接口:
bind 127.0.0.1 192.168.1.200

Tips:注意除了您可以綁定IPV4以為你還可綁定IPV6


更改默認服務端口

描述: 除了我們可以指定綁定的接口外释漆,我們還可以更改默認的redis服務端口悲没,可以防止黑客針對于Redis服務掃描探測。

# 將默認的服務斷開從6379變成63791
port 63791


認證配置

描述: 為Redis服務端設置一個認證密碼是非常必須男图,下面講解 Redis 配置密碼認證的幾種方式總結:

操作流程:

# 1.通過redis.conf文件中進行配置示姿,此種方式修改后需要重啟Redis。
vim /etc/redis.conf
requirepass WeiyiGeek  # WeiyiGeek 即認證密碼
masterauth  WeiyiGeek  # 配置主節(jié)點認證密碼, 注意若master配置了密碼則slave也要配置相應的密碼參數(shù)否則無法進行正常復制的

# 2.通過命令行進行配置逊笆,此種方式的優(yōu)點無需重啟Redis栈戳。
redis 127.0.0.1:6379[1]> config set requirepass my_redis  
OK  
redis 127.0.0.1:6379[1]> config get requirepass  
1) "requirepass" 
2) "my_redis"  


使用密碼驗證登陸Redis服務器:

# 方式1:密碼明文會被記錄到系統(tǒng)命令執(zhí)行歷史中(極其不推薦/不安全)
redis-cli -h 127.0.0.1 -p 6379 -a WeiyiGeek

# 方式2:交互式進行配置
redis-cli -h 127.0.0.1 -p 6379
redis 127.0.0.1:6379> auth WeiyiGeek # OK

非常注意: AUTH 命令與其他所有 Redis 命令一樣,以未加密的方式發(fā)送难裆,因此它無法防范對網(wǎng)絡有足夠訪問權限以執(zhí)行竊聽的攻擊者, 所以對應高敏感的數(shù)據(jù)建議配置TLS 支持(Redis 在所有通信通道上都可選地支持 TLS)以加密數(shù)據(jù)與命令傳輸濒生。


禁用特定命令

描述: 我們可以禁用 Redis 中的命令或將它們重命名為不可猜測的名稱谓罗,以便普通客戶端僅限于指定的一組命令,比如漏洞就利用config/save兩個命令完成攻擊 臂寝。

由于redis無用戶權限限制霉撵,建議將危險的命令使用rename配置項進行禁用或重命名器罐,這樣外部不了解重命名規(guī)則攻擊者连霉,就不能執(zhí)行這類命令FLUSHDB, FLUSHALL, KEYS, PEXPIRE, DEL, CONFIG, SHUTDOWN, BGREWRITEAOF, BGSAVE, SAVE, SPOP, SREM, RENAME, DEBUG, EVAL

例如: 普通用戶可能無法調用Redis CONFIG 命令來更改實例的配置勇皇,但提供和刪除實例的系統(tǒng)應該能夠這樣做。

# redis.conf 配置文件
# 方式1.CONFIG / FLUSHALL命令被重命名為一個不可猜測的名稱
rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
rename-command FLUSHALL b840fc02d524045429941cc15f59e41cb7be6c53

# 方式2.通過將其重命名為空字符串來完全禁用它(或任何其他命令)
rename-command CONFIG ""
rename-command FLUSHALL  ""

Tips: 注意配置后需要重新redis-server服務侦讨。


日志記錄

描述: 為Redis創(chuàng)建訪問(或Debug)日志(根據(jù)需求設置)驶冒,在建立Redis蜜罐時苟翻,如果有攻擊嘗試時韵卤,就開業(yè)及時發(fā)現(xiàn)監(jiān)控redis安全狀態(tài), 以及可以監(jiān)控cmdstat_*指標信息報警;

# 執(zhí)行info commandstats 看出命令執(zhí)行的次數(shù)、命令耗費的 CPU 時間(單位毫秒)崇猫、執(zhí)行每個命令耗費的平均 CPU 時間(單位毫秒)
cmdstat_get:calls=2,usec=15,usec_per_call=7.50
cmdstat_select:calls=1,usec=9,usec_per_call=9.00
cmdstat_keys:calls=4,usec=1948,usec_per_call=487.00
cmdstat_auth:calls=3123,usec=8291,usec_per_call=2.65

日志記錄配置:

logfile "/usr/local/redis/redis.log" #日志文件存放目錄
loglevel verbose  #記錄訪問信息


防范字符串轉義和 NoSQL 注入

描述: Redis 協(xié)議沒有字符串轉義的概念沈条,所以一般情況下使用普通客戶端庫是不可能注入的, 但有可能會通過EVAL和EVALSHA命令執(zhí)行的 Lua 腳本來構造惡意腳本。

> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second

解決辦法: 應用程序應該避免使用從不受信任的來源獲得的字符串來組成 Lua 腳本的主體诅炉。

Tips : EVALSHA 通過其 SHA1 摘要評估緩存在服務器端的腳本蜡歹。腳本使用SCRIPT LOAD命令緩存在服務器端。該命令在其他方面與EVAL相同涕烧。


防范由外部客戶端精心挑選的輸入觸發(fā)的攻擊

描述: 有可能攻擊者構造惡意的數(shù)據(jù)結構插入到 Redis 數(shù)據(jù)庫中, 這可能會觸發(fā)Redis 內部實現(xiàn)的數(shù)據(jù)結構的病態(tài)(最壞情況)算法復雜性月而。

例如,攻擊者可以通過 Web 表單將一組已知散列到同一桶的字符串提供到散列表中议纯,以便將 O(1)預期時間(平均時間)變?yōu)镺(N )最壞的情況父款,消耗比預期更多的 CPU,并最終導致拒絕服務。

解決辦法: 為了防止這種特定的攻擊憨攒,Redis 對哈希函數(shù)使用了每次執(zhí)行的偽隨機種子世杀。


防火墻限制訪問

描述: 前面針對Redis-server服務層面進行安全配置,此處針對網(wǎng)絡層面進行限制肝集,只允許指定的IP地址進行訪問瞻坝,在主機上配置防火墻的優(yōu)點是防止同一網(wǎng)段的東西流量。

在Linux上系統(tǒng)防火墻設置命令:

iptables -A INPUT -s x.x.x.x -p tcp --dport 6379 -j ACCEPT  #如果需要其他機器訪問或者設置了slave模式杏瞻,那就記得加上相應的防火墻設置(Centos6)
firewall-cmd --add-rich-rule="rule family="ipv4" source address="x.x.x.x" port protocol="tcp" port="6379" accept" --permanent  #(Centos7)

在Windows上系統(tǒng)防火墻設置命令:

New-NetFirewallRule -Name "redis-server-access" -DisplayName "redis-server" -Description "redis-server 客戶端訪問防火墻規(guī)則" -Direction Inbound -LocalPort 6379 -RemoteAddress x.x.x.x -Protocol TCP -Action Allow -Enabled True
Get-NetFirewallRule -Name "redis-server-access"  | Format-Table


禁止redis中存儲敏感的明文數(shù)據(jù)

描述: Redis設計旨在提供高性能的KV服務所刀,至少目前在權限訪問控制和數(shù)據(jù)持久化方面比較弱化,所以從應用層面上捞挥,不建議使用Redis來存儲敏感信息勉痴,例如鑒權的密碼。


Redis 安全配置總結示例

安全配置示例:

# 配置文件 vim /etc/redis/redis.conf
# 1.信任的內網(wǎng)運行,盡量避免有公網(wǎng)訪問(如果存在內網(wǎng)中其他固定IP則需要設置防火墻)
bind 127.0.0.1 

# 2.綁定redis監(jiān)聽的網(wǎng)絡接口(通過redis配置項bind,可同時綁定多個IP), 把6379改為其他得端口(或者采用unix管道進行數(shù)據(jù)管理)
port 63791  

# 3.開啟redis密碼認證,并設置高復雜度密碼設置树肃,因查詢效率高蒸矛,auth這種命令每秒能處理10w次以上(所以需要增加強度)
# echo -e "weiyigeek"|sha256sum 
requirepass 097575a79efcd7ea7b1efa2bcda78a4fc7cbd0820736b2f2708e72c3d21f8b61

# 4.日志文件存放目錄以及記錄redis訪問信息。
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably) 默認
# warning (only very important / critical messages are logged)
logfile "/usr/local/redis/redis.log" 
loglevel verbose  

# 5.默認情況下胸嘴,啟用保護模式雏掠。只有在以下情況下才應禁用(no)它
# - 您確定希望其他主機的客戶端連接到Redis
# - 即使沒有配置身份驗證,也沒有特定的接口集
# - 使用“bind”指令顯式列出劣像。
protected-mode yes

# 6.重命名特殊命令(根據(jù)需求)
# `FLUSHDB, FLUSHALL, KEYS, PEXPIRE, DEL, CONFIG, SHUTDOWN, BGREWRITEAOF, BGSAVE, SAVE, SPOP, SREM, RENAME, DEBUG, EVAL`
rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
rename-command FLUSHDB b840fc02d524045429941cc15f59e41cb7be6c53
rename-command FLUSHALL b840fc02d524045429941cc15f59e41cb7be6c54
rename-command EVAL b840fc02d524045429941cc15f59e41cb7be6c55
rename-command DEBUG b840fc02d524045429941cc15f59e41cb7be6c56
rename-command SHUTDOWN b840fc02d524045429941cc15f59e41cb7be6c7


2.Performance Optimization

描述: Redis開發(fā)和運維人員更加關注的是Redis本身的一些配置優(yōu)化乡话,例如AOF和RDB的配置優(yōu)化、數(shù)據(jù)結構的配置優(yōu)化等耳奕,但是對于操作系統(tǒng)是否需要針對Redis做一些配置優(yōu)化不甚了解或者不太關心绑青,然而事實證明一個良好的系統(tǒng)操作配置能夠為Redis服務良好運行保駕護航。

關鍵優(yōu)化項

  • Step 1.vm.overcommit_memory 最佳實踐
    Redis在啟動時可能會出現(xiàn)這樣的日志, 然后弄清楚什么是overcommit?
    描述: Linux 操作系統(tǒng)對大部分申請內存的請求都回復yes以便能運行更多的程序屋群。因為申請內存后并不會馬上使用內存闸婴,這種技術叫做overcommit。
# 如果Redis在啟動時有上面的日志芍躏,說明`vm.overcommit_memory=0`邪乍,Redis提示把它設置為1。
# WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the 
command 'sysctl -w vm.overcommit_memory=1' for this to take effect.

# 注意:本文的可用內存代表物理內存與swap之和对竣。
# 最佳實踐
- Redis建議把這個值設置為1是為了讓fork能夠在低內存下也執(zhí)行成功(設置合理的maxmemory保證機器有20%~30%的閑置內存)庇楞。
- 集中化管理aof重寫和rdb的bgsave。

Tips : 日志中的 Background save 代表的是 bgsave 和 bgrewriteaof否纬,如果當前可用內存不足吕晌,操作系統(tǒng)應該如何處理fork。如果vm.overcommit_memory=0临燃,代表如果沒有可用內存睛驳,就申請內存失敗壁拉,對應到Redis就是fork執(zhí)行失敗,在Redis的日志會出現(xiàn):Cannot allocate memory


  • Step 2.vm.swapniess 最佳實踐
    描述: swap對于操作系統(tǒng)來比較重要柏靶,當物理內存不足時弃理,可以swap out一部分內存頁,以解燃眉之急屎蜓。但世界上沒有免費午餐痘昌,swap空間由硬盤提供,對于需要高并發(fā)炬转、高吞吐的應用來說辆苔,磁盤IO通常會成為系統(tǒng)瓶頸。在Linux中扼劈,并不是要等到所有物理內存都使用完才會使用到swap驻啤,系統(tǒng)參數(shù)swppiness會決定操作系統(tǒng)使用swap的傾向程度。swappiness的取值范圍是0~100荐吵,swappiness的值越大骑冗,說明操作系統(tǒng)可能使用swap的概率越高,swappiness值越低先煎,表示操作系統(tǒng)更加傾向于使用物理內存贼涩。

如果Linux > 3.5的情況下 vm.swapniess=1 (寧愿swap也不要OOM killer) 否則 vm.swapniess=0 (寧愿OOM killer也不用swap) 從而實現(xiàn)如下兩個目標:

1.物理內存充足時候,使Redis足夠快薯蝎。
2.物理內存不足時候遥倦,避免Redis死掉(如果當前Redis為高可用,死掉比阻塞更好)占锯。

運維提示:OOM(Out Of Memory) killer機制是指Linux操作系統(tǒng)發(fā)現(xiàn)可用內存不足時袒哥,強制殺死一些用戶進程(非內核進程),來保證系統(tǒng)有足夠的可用內存進行分配消略。


  • Step 3.kernel.mm.transparent_hugepage.enabled 最佳實踐
    Redis在啟動時可能會看到如下日志:
WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.

Tips : 從提示看Redis建議修改Transparent Huge Pages (THP)的相關配置堡称,Linux kernel在2.6.38內核增加了Transparent Huge Pages (THP)特性 ,支持大內存頁(2MB)分配疑俭,默認開啟粮呢。當開啟時可以降低fork子進程的速度,但fork之后钞艇,每個內存頁從原來4KB變?yōu)?MB,會大幅增加重寫期間父進程內存消耗豪硅。同時每次寫命令引起的復制內存頁單位放大了512倍哩照,會拖慢寫操作的執(zhí)行時間,導致大量寫操作慢查詢懒浮。

因此Redis日志中建議將此特性進行禁用飘弧,禁用方法如下:echo never > /sys/kernel/mm/transparent_hugepage/enabled


  • Step 4.Transparent Huge Pages
    Redis在啟動時可能會看到如下日志:WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.

從提示看Redis建議修改Transparent Huge Pages (THP)的相關配置识藤,Linux kernel在2.6.38內核增加了Transparent Huge Pages (THP)特性 ,支持大內存頁(2MB)分配次伶,默認開啟痴昧。當開啟時可以降低fork子進程的速度,但fork之后冠王,每個內存頁從原來4KB變?yōu)?MB赶撰,會大幅增加重寫期間父進程內存消耗。同時每次寫命令引起的復制內存頁單位放大了512倍柱彻,會拖慢寫操作的執(zhí)行時間豪娜,導致大量寫操作慢查詢。例如簡單的incr命令也會出現(xiàn)在慢查詢中哟楷。因此Redis日志中建議將此特性進行禁用瘤载,禁用方法如下:

# 配置機器重啟后THP配置依然生效
tee -a /etc/rc.local <<'EOF'
echo never >  /sys/kernel/mm/transparent_hugepage/enabled
EOF


  • Step 5.OOM killer 優(yōu)化配置
    OOM killer會在可用內存不足時選擇性的殺掉用戶進程,它會為每個用戶進程設置一個權值,這個權值越高卖擅,被“下手”的概率就越高鸣奔,反之概率越低。每個進程的權值存放在/proc/{progress_id}/oom_score中惩阶,這個值是受/proc/{progress_id}/oom_adj的控制溃蔫,oom_adj在不同的Linux版本的最小值不同,可以參考Linux源碼中oom.h(從-15到-17)

oom_adj設置為最小值時琳猫,該進程將不會被OOM killer殺掉伟叛,設置方法如下:

# 命令
echo {value} > /proc/${process_id}/oom_adj

# 腳本
for redis_pid in $(pgrep -f "redis-server")
do
  echo -17 > /proc/${redis_pid}/oom_adj
done


  • Step 6.設置其打開文件數(shù)句柄數(shù)以及單個用戶最大進程數(shù)
    描述: 下面得參數(shù)主要設置是單個進程能夠使用得Linux最大文件句柄數(shù), 解決在高并發(fā)的情況下不會異常報錯。在Redis官方提到的建議
# You requested maxclients of 10000 requiring at least 10032 max file descriptors.
第一行:Redis建議把open files至少設置成10032脐嫂,那么這個10032是如何來的呢统刮?因為maxclients的默認是10000,這些是用來處理客戶端連接的账千,除此之外侥蒙,Redis內部會使用最多32個文件描述符,所以這里的10032 = 10000 + 32匀奏。

# Redis can’t set maximum open files to 10032 because of OS error: Operation not permitted.
第二行:Redis不能將open files設置成10032鞭衩,因為它沒有權限設置。

# Current maximum open files is 4096. Maxclients has been reduced to 4064 to compensate for low ulimit. If you need higher maxclients increase ‘ulimit –n’.
第三行:當前系統(tǒng)的open files是4096娃善,所以maxclients被設置成4096-32=4064個论衍,如果你想設置更高的maxclients,請使用ulimit -n來設置聚磺。從上面的三行日志分析可以看出open files的限制優(yōu)先級比maxclients大坯台。

解決辦法:

# 臨時
ulimit –Sn 10032
# 永久
tee etc/security/limits.conf <<'EOF'
*  soft    nofile          10032
*  hard    nofile          10032
*  soft    nproc           65535
*  hard    nproc           65535
EOF


  • Step 7.TCP backlog 日志隊列優(yōu)化
    描述: Redis 默認的 tcp-backlog 為511 我們可以通過修改配置 tcp-backlog 進行調整,如果Linux的tcp-backlog 小于Redis設置的 tcp-backlog瘫寝,那么在Redis啟動時會看到如下日志:
# WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.

解決方法:

# 查看
cat /proc/sys/net/core/somaxconn
128

# 修改
echo 511 > /proc/sys/net/core/somaxconn


  • Step 8.保證Redis服務器時鐘的一致性
    描述: 我們知道像Redis Sentinel和Redis Cluster這兩種需要多個Redis實例的類型蜒蕾,可能會涉及多臺服務器稠炬。雖然Redis并沒有對多個服務器的時鐘有嚴格的要求,但是假如多個Redis實例所在的服務器時鐘不一致咪啡,對于一些異常情況的日志排查是非常困難的首启,例如Redis Cluster的故障轉移,如果日志時間不一致撤摸,對于我們排查問題帶來很大的困擾(注:但不會影響集群功能毅桃,集群節(jié)點依賴各自時鐘)。一般公司里都會有NTP服務用來提供標準時間服務愁溜,從而達到糾正時鐘的效果

例如:每小時的同步1次NTP服務

0 * * * * /usr/sbin/ntpdate ntp.xx.com > /dev/null 2>&1


Redis 性能優(yōu)化總結示例

系統(tǒng)優(yōu)化配置

# - 設置內存分配策略
sudo sysctl -w vm.overcommit_memory=1

# - 盡量使用物理內存(速度快)針對內核版本大于>=3.x (寧愿swap也不要OOM killer)
sudo sysctl -w vm.swapniess=1

# - 禁用 THP 特性減少內存消耗
echo never > /sys/kernel/mm/transparent_hugepage/enabled

# - OOM killer 特性優(yōu)化
for redis_pid in $(pgrep -f "redis-server")
do
  echo -17 > /proc/${redis_pid}/oom_adj
done

# - 設置其打開文件數(shù)句柄數(shù)以及單個用戶最大進程數(shù)
tee etc/security/limits.conf <<'EOF'
*  soft    nofile          10032
*  hard    nofile          10032
*  soft    nproc           65535
*  hard    nproc           65535
EOF

# - SYN隊列長度設置此參數(shù)可以容納更多等待連接的網(wǎng)絡疾嗅。
echo 511 > /proc/sys/net/core/somaxconn
sudo sysctl -w net.ipv4.tcp_max_syn_backlog=2048 

# - 每個小時同步一次時間
0 * * * * /usr/sbin/ntpdate ntp.xx.com > /dev/null 2>&1


應用配置優(yōu)化

# 最大客戶端上限連接數(shù)(需根據(jù)實際情況調整與系統(tǒng)的open files有關,其數(shù)量值為open files(10032) - 32)
maxclients 10000

# 集群配置優(yōu)化關鍵項
# 集群超時時間冕象,如果此時間設置太小時由于網(wǎng)絡波動可能會導致進行重新選Master的操作
cluster-node-timeout 5000
# 主節(jié)點寫入后必須同步到一臺從上代承,防止數(shù)據(jù)丟失的有效方法(要求是其從節(jié)點必須>=1)
min‐replicas‐to‐write 1


應用使用中優(yōu)化

# (1) 查詢執(zhí)行時間指的是不包括像客戶端響應(talking)、發(fā)送回復等 IO 操作渐扮,而單單是執(zhí)行一個查詢命令所耗費的時間
redis> SLOWLOG LEN   # 管理 redis 的慢日志查看當前日志的數(shù)量 
redis> SLOWLOG RESET # 清空 slowlog 此時上面 LEN 變成 0

# (2) 斷開耗時連接
# 列出所有已連接客戶端
redis 127.0.0.1:6379> CLIENT LIST
addr=127.0.0.1:43501 fd=5 age=10 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client
# 殺死當前客戶端的連接
redis 127.0.0.1:6379> CLIENT KILL 127.0.0.1:43501
OK

文章書寫不易论悴,如果您覺得這篇文章還不錯的,請給這篇專欄 【點個贊墓律、投個幣膀估、收個藏、關個注耻讽,轉個發(fā)】(人間五大情)察纯,這將對我的肯定,謝謝针肥!饼记。

本文章來源 我的Blog站點WeiyiGeek 公眾賬號 以及 我的BiliBili專欄 (技術交流、友鏈交換請郵我喲),謝謝支持慰枕!(?′?‵?) ?
歡迎各位志同道合的朋友一起學習交流具则,如文章有誤請留下您寶貴的知識建議,通過郵箱【master#weiyigeek.top】聯(lián)系我喲具帮!

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末博肋,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蜂厅,更是在濱河造成了極大的恐慌匪凡,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葛峻,死亡現(xiàn)場離奇詭異锹雏,居然都是意外死亡,警方通過查閱死者的電腦和手機术奖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門礁遵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人采记,你說我怎么就攤上這事佣耐。” “怎么了唧龄?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵兼砖,是天一觀的道長。 經(jīng)常有香客問我既棺,道長讽挟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任丸冕,我火速辦了婚禮耽梅,結果婚禮上,老公的妹妹穿的比我還像新娘胖烛。我一直安慰自己眼姐,他們只是感情好,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布佩番。 她就那樣靜靜地躺著众旗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪趟畏。 梳的紋絲不亂的頭發(fā)上贡歧,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機與錄音赋秀,去河邊找鬼利朵。 笑死,一個胖子當著我的面吹牛沃琅,可吹牛的內容都是我干的哗咆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼益眉,長吁一口氣:“原來是場噩夢啊……” “哼晌柬!你這毒婦竟也來了?” 一聲冷哼從身側響起郭脂,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤年碘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后展鸡,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體屿衅,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年莹弊,在試婚紗的時候發(fā)現(xiàn)自己被綠了涤久。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涡尘。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖响迂,靈堂內的尸體忽然破棺而出考抄,到底是詐尸還是另有隱情,我是刑警寧澤蔗彤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布川梅,位于F島的核電站,受9級特大地震影響然遏,放射性物質發(fā)生泄漏贫途。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一待侵、第九天 我趴在偏房一處隱蔽的房頂上張望丢早。 院中可真熱鬧,春花似錦诫给、人聲如沸香拉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凫碌。三九已至,卻和暖如春胃榕,著一層夾襖步出監(jiān)牢的瞬間盛险,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工勋又, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留苦掘,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓楔壤,卻偏偏與公主長得像鹤啡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蹲嚣,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內容