- redis高可用方案:哨兵、集群、lvs+keepalive,下面只介绍前两种
0.首先查下ip,linux查ip地址命令是ifconfig
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:53:58:0a:11 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.20.31.186 netmask 255.255.240.0 broadcast 172.20.31.255
inet6 fe80::216:3eff:fe04:52b prefixlen 64 scopeid 0x20<link>
ether 00:16:3e:04:05:2b txqueuelen 1000 (Ethernet)
RX packets 906944 bytes 471557280 (471.5 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 686363 bytes 285183872 (285.1 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 102707644 bytes 56312954474 (56.3 GB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 102707644 bytes 56312954474 (56.3 GB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis#
1.搭建主从
1.1 创建一个master-slave文件夹,cd到这个文件夹,然后创建三个子文件夹:redis11、redis12、redis13
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis# mkdir my-master-slave
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis# cd my-master-slave/
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# ll
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# mkdir redis11 redis12 redis13
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# ll
total 20
drwxr-xr-x 5 root root 4096 Aug 6 10:19 ./
drwxr-xr-x 5 root root 4096 Aug 6 10:19 ../
drwxr-xr-x 2 root root 4096 Aug 6 10:19 redis11/
drwxr-xr-x 2 root root 4096 Aug 6 10:19 redis12/
drwxr-xr-x 2 root root 4096 Aug 6 10:19 redis13/
1.2 复制redis-server到每个子文件夹
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# cp ~/redis-6.0.8/src/redis-server ./redis12
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# cp ~/redis-6.0.8/src/redis-server ./redis13
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# cp ~/redis-6.0.8/src/redis-server ./redis11
1.3 复制redis-cli到master-slave主文件夹
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# cp ~/redis-6.0.8/src/redis-cli ./
1.4 往子文件夹放入配置文件
- redis11的配置文件
bind 0.0.0.0 #不知道绑定那个地址就用0.0.0.0
port 8001 #设置主服务器端口选8001
logfile "8001.log" #改名日志文件存到本地
dbfilename "dump-8001.rdb" #将数据库转储到的文件名,默认dump.rdb
daemonize yes #设定为守护进程
rdbcompression yes #对于存储到磁盘中的快照文件,设置是否进行压缩,redis采用LZF压缩算法,如果想节省CPU性能可以关闭此功能,默认yes。
- redis12的配置文件
bind 0.0.0.0
port 8002
logfile "8002.log"
dbfilename "dump-8002.rdb"
daemonize yes
rdbcompression yes
slaveof 172.20.31.186 8001
- redis13的配置文件
bind 0.0.0.0
port 8003
logfile "8003.log"
dbfilename "dump-8003.rdb"
daemonize yes
rdbcompression yes
slaveof 172.20.31.186 8001
1.5 写linux脚本文件
1 #!/bin/bash
2
3 cd redis11/
4 ./redis-server redis.conf &
5 cd ..
6 cd redis12/
7 ./redis-server redis.conf &
8 cd ..
9 cd redis13/
10 ./redis-server redis.conf &
11 cd ..
1.6 启动用ps -elf|grep redis看主从的进程
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# ps -elf|grep redis
5 S root 518 1 0 80 0 - 57414 ep_pol Aug01 ? 00:12:06 /usr/local/bin/redis-server 127.0.0.1:6379
5 S root 30711 1 0 80 0 - 16292 ep_pol 10:38 ? 00:00:00 ./redis-server 0.0.0.0:8001
5 S root 30712 1 0 80 0 - 16292 ep_pol 10:38 ? 00:00:00 ./redis-server 0.0.0.0:8002
5 S root 31128 1 0 80 0 - 16292 ep_pol 10:42 ? 00:00:00 ./redis-server 0.0.0.0:8003
0 S root 31136 30030 0 80 0 - 3609 pipe_w 10:42 pts/3 00:00:00 grep --color=auto redis
1.7 主从缺点展示
- 当主服务器挂了之后,从服务器只能读,不能写
- 8002是从服务器,8001是主服务器,主服务器已经提前用kill -9 结束进程了
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# redis-cli -p 8002
127.0.0.1:8002> set name kuang
(error) READONLY You can't write against a read only replica.
127.0.0.1:8002> get 1
(nil)
1.8 redis不同版本主从复制
同步方式:
主从同步方式:
1)全量数据同步
master生成rdb发送给slave,rdb数据很大,slave就需要很长的时间同步
2)增量数据同步
只同步offset部分的数据,slaver只需要携带offset去看master的循环更新队列当中,master那就只需要发送循环更新队列当中offset的消息就可以了
1.8.1 redis 2.8版本之前(rdb持久化)
- 都是采用全量数据同步
1.若master和slaver出现短暂的时延:就需要进行全量数据同步
2.slaver持久化操作会进行fork操作
3.master进行持久化会有fork操作
- 游戏服务器崩溃问题:
0)背景:
每台电脑96g,有8节点,每个节点fork操作吃满内存,所以每台节点设置6g
1)描述:
由于过年人数暴增,造成有一台机器内存吃紧,运维会让内存吃紧的从节点重启,从而使与之对应的主节点不能提供服务(因为要全部进行fork持久化,然后发送给slave节点),从而server不能访问这台机器
2)解决:
方法:减少fork操作,或是不进行fork操作
具体:让8个master节点不同时fork操作,或不进行持久化
再具体一点:
1.master机器上关掉rdb持久化,不会有持久化(推荐两个数据库:unqlite\leveldb,这两个都是key-value数据库,磁盘数据库)
unqlite : 一个组件的形式,一个库的形式,c语言写的,可以将redis的数据持久化到磁盘当中
leveldb:采用rockdb的引擎,将大部分的数据都刷到磁盘当中,就不会有fork操作,我们的存储就非常安全了
总流程:①客户端把数据写入到redis;②redis返回ok;③客户端再把数据写到中间件(unqlite或leveldb);④中间件再根据对应的数据访问redis;⑤redis返回ok;⑥中间件再把数据落盘
2.伪装一个master的从数据库(psync redis协议)
①用unqlite或leveldb当作从数据库;
②同步由主从协议保证的
③从数据库将数据落盘到磁盘,就可以将redis的持久化关掉
1.8.2 redis 2.8版本
- 增加增量数据同步
1.8.3 redis 4.0版本(aof重写和aof&rdb混用的方式在4.0才出现)
- 主从切换的时候,之间也采用增量数据同步
2.搭建哨兵sentinel模式
- uorum在哨兵中有两层含义。第一层含义为:如果某个哨兵认为其监听的Master处于下线的状态,这个状态在Redis中标记为S_DOWN,即主观下线。假设quorum配置为2,则当有两个哨兵同时认为一个Master处于下线的状态时,会标记该Master为O_DOWN,即客观下线。只有一个Master处于客观下线状态时才会开始执行切换。第二层含义为:假设有5个哨兵,quorum配置为4。首先,判断客观下线需要4个哨兵才能认定。其次,当开始执行切换时,会从5个哨兵中选择一个leader执行该次选举,此时一个哨兵也必须得到4票才能被选举为leader,而不是3票(即哨兵的大多数)
2.1 修改三个子文件夹的redis.conf配置
//redis11-----------------------------
bind 0.0.0.0
port 9001
logfile "9001.log"
dbfilename "dump-9001.rdb"
daemonize yes
rdbcompression yes
//redis12-----------------------------
bind 0.0.0.0
port 9002
logfile "9002.log"
dbfilename "dump-9002.rdb"
daemonize yes
rdbcompression yes
slaveof 172.20.31.186 9001
//redis13-----------------------------
bind 0.0.0.0
port 9003
logfile "9003.log"
dbfilename "dump-9003.rdb"
daemonize yes
rdbcompression yes
slaveof 172.20.31.186 9001
2.2 复制redis-sentinel到三个子文件夹
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# cp ~/redis-6.0.8/src/redis-sentinel ./redis11
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# cp ~/redis-6.0.8/src/redis-sentinel ./redis12
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# cp ~/redis-6.0.8/src/redis-sentinel ./redis13
2.3 复制sentinel.conf到子文件夹
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# cp ~/redis-6.0.8/sentinel.conf ./redis11
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# cp ~/redis-6.0.8/sentinel.conf ./redis12
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# cp ~/redis-6.0.8/sentinel.conf ./redis13
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# tree
.
├── redis11
│ ├── 8001.log
│ ├── dump-8001.rdb
│ ├── redis.conf
│ ├── redis-sentinel
│ ├── redis-server
│ └── sentinel.conf
├── redis12
│ ├── 8002.log
│ ├── dump-8002.rdb
│ ├── redis.conf
│ ├── redis-sentinel
│ ├── redis-server
│ └── sentinel.conf
├── redis13
│ ├── 8003.log
│ ├── dump-8003.rdb
│ ├── redis.conf
│ ├── redis-sentinel
│ ├── redis-server
│ └── sentinel.conf
└── redis-cli
3 directories, 19 files
2.4 修改sentinel.conf文件
//redis11的修改的地方
# The port that this sentinel instance will run on
port 19001 #哨兵在的端口
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
#
# Tells Sentinel to monitor this master, and to consider it in O_DOWN
# (Objectively Down) state only if at least <quorum> sentinels agree.
#
# Note that whatever is the ODOWN quorum, a Sentinel will require to
# be elected by the majority of the known Sentinels in order to
# start a failover, so no failover can be performed in minority.
#
# Replicas are auto-discovered, so you don't need to specify replicas in
# any way. Sentinel itself will rewrite this configuration file adding
# the replicas using additional configuration options.
# Also note that the configuration file is rewritten when a
# replica is promoted to master.
#
# Note: master name should not include special characters or spaces.
# The valid charset is A-z 0-9 and the three characters ".-_".
sentinel monitor mymaster1 172.20.31.186 9001 2 #Sentinel去监视一个名为master1的主redis实例,这个主实例的IP地址为本机地址172.20.31.186,端口号为9001,
#而将这个主实例判断为失效至少需要2个 Sentinel进程的同意,只要同意Sentinel的数量不达标,自动failover就不会执行
//redis12的修改的地方
port 19001
sentinel monitor mymaster2 172.20.31.186 9002 2
//redis13的修改的地方
port 19001
sentinel monitor mymaster3 172.20.31.186 9003 2
2.5 测试哨兵
2.5.1 哨兵的主从跑起来
//脚本文件
#!/bin/bash
cd redis11/
./redis-server sentinel.conf --sentinel &
cd ..
cd redis12/
./redis-server sentinel.conf --sentinel &
cd ..
cd redis13/
./redis-server sentinel.conf --sentinel &
cd ..
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# start-all.sh
2.5.2 测试哨兵可用性
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# ps -elf|grep redis
0 S root 315 31570 0 80 0 - 3609 pipe_w 12:00 pts/8 00:00:00 grep --color=auto redis
5 S root 518 1 0 80 0 - 57414 ep_pol Aug01 ? 00:12:10 /usr/local/bin/redis-server 127.0.0.1:6379
4 S root 32747 1 0 80 0 - 15652 ep_pol 11:58 pts/8 00:00:00 ./redis-server *:19001 [sentinel]
4 S root 32748 1 0 80 0 - 15652 ep_pol 11:58 pts/8 00:00:00 ./redis-server *:19002 [sentinel]
4 S root 32749 1 0 80 0 - 15652 ep_pol 11:58 pts/8 00:00:00 ./redis-server *:19003 [sentinel]
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave# redis-cli -p 19001
127.0.0.1:19001> sentinel master mymaster1
1) "name"
2) "mymaster1"
3) "ip"
4) "172.20.31.186"
5) "port"
6) "9001"
7) "runid"
8) ""
9) "flags"
10) "s_down,master,disconnected"
11) "link-pending-commands"
12) "3"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "147660"
17) "last-ok-ping-reply"
18) "147660"
19) "last-ping-reply"
20) "147660"
21) "s-down-time"
22) "117626"
23) "down-after-milliseconds"
24) "30000"
25) "info-refresh"
26) "1628222487700"
27) "role-reported"
28) "master"
29) "role-reported-time"
30) "147660"
31) "config-epoch"
32) "0"
33) "num-slaves"
34) "0"
35) "num-other-sentinels"
36) "0"
37) "quorum"
38) "2"
39) "failover-timeout"
40) "180000"
41) "parallel-syncs"
42) "1"
127.0.0.1:19001>
//打印测试
//-------------------------------------------------
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave/redis13# netstat -anop | grep redis
tcp 0 0 0.0.0.0:9001 0.0.0.0:* LISTEN 447/redis-server 0. off (0.00/0/0)
tcp 0 0 0.0.0.0:9002 0.0.0.0:* LISTEN 471/redis-server 0. off (0.00/0/0)
tcp 0 0 0.0.0.0:9003 0.0.0.0:* LISTEN 482/redis-server 0. off (0.00/0/0)
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 518/redis-server 12 off (0.00/0/0)
tcp 0 0 0.0.0.0:19001 0.0.0.0:* LISTEN 32747/./redis-serve off (0.00/0/0)
tcp 0 0 0.0.0.0:19002 0.0.0.0:* LISTEN 32748/./redis-serve off (0.00/0/0)
tcp 0 0 0.0.0.0:19003 0.0.0.0:* LISTEN 32749/./redis-serve off (0.00/0/0)
root@iZbp1do67v9l7zwkcs2b22Z:~/kunmk/test/testForRedis/my-master-slave/redis11# ps -elf|grep redis
5 S root 471 1 0 80 0 - 16292 ep_pol 12:21 ? 00:00:00 redis-server 0.0.0.0:9002
5 S root 482 1 0 80 0 - 16292 ep_pol 12:21 ? 00:00:00 redis-server 0.0.0.0:9003
5 S root 518 1 0 80 0 - 57414 ep_pol Aug01 ? 00:12:12 /usr/local/bin/redis-server 127.0.0.1:6379
5 S root 556 1 0 80 0 - 16292 ep_pol 12:27 ? 00:00:00 redis-server 0.0.0.0:9001
0 S root 568 31570 0 80 0 - 3609 pipe_w 12:27 pts/8 00:00:00 grep --color=auto redis
4 S root 32747 1 0 80 0 - 15652 ep_pol 11:58 pts/8 00:00:02 ./redis-server *:19001 [sentinel]
4 S root 32748 1 0 80 0 - 15652 ep_pol 11:58 pts/8 00:00:02 ./redis-server *:19002 [sentinel]
4 S root 32749 1 0 80 0 - 15652 ep_pol 11:58 pts/8 00:00:02 ./redis-server *:19003 [sentinel]
3.搭建集群教学
- 之前做过了,连接放在下面
超顶的搭建集群