架构学习第四周--高可用与NoSQL数据库

目录

一、HAProxy介绍

二、HAProxy基本使用

2.1,HAProxy调度算法

2.2,HAProxy高级用法

三、高可用Keepalived介绍

3.1,Keepalived介绍

3.2,Keepalived单主架构实现

3.3,脑裂

四、Keepalived实例--实现单主架构的LVS-DR模型

五、实例--通过Keepalived实现HAProxy高可用

六、NoSQL数据库Redis

6.1,Redis简介

6.2,Redis持久化

6.3,Redis使用介绍

七、实例--构建Redis主从哨兵模式

7.1,主从复制优化

7.2,常见主从复制故障

7.3,实例--构筑主从哨兵模式

八、实例--三节点Redis集群搭建

一、HAProxy介绍

负载均衡(Load Balance),简称LB,是一种服务或基于硬件设备等实现的高可用反向代理技术,负载均衡将特定的业务(web服务、网络流量等)分担给指定的一个或多个后端特定的服务器或设备,从而提高了公司业务的并发处理能力、保证了业务的高可用性、方便了业务后期的水平动态扩展。

HAProxy是使用C语言开发的开源软件,具有高并发(一万以上)、高性能的TCP和HTTP负载均衡器,支持基于cookie的持久性,自动故障切换,支持正则表达式及web状态统计。

#包安装HAProxy

root@ubuntu-test1:~# apt-get install --no-install-recommends software-properties-common

root@ubuntu-test1:~# add-apt-repository ppa:vbernat/haproxy-2.8

root@ubuntu-test1:~# apt-get install haproxy=2.8.\*

#编译安装HAProxy

#编译安装Lua

root@ubuntu-test1:~# apt update && apt -y install gcc make libssl-dev libpcre3 libpcre3-dev zlib1g-dev libreadline-dev libsystemd-dev #安装依赖包

root@ubuntu-test1:~#wget http://www.lua.org/ftp/lua-5.3.5.tar.gz #下载新版源码

root@ubuntu-test1:~#tar xf lua-5.3.5.tar.gz -C /usr/local/src/;cd /usr/local/src/

root@ubuntu-test1:/usr/local/src/lua-5.3.5# make linux test #编译安装

root@ubuntu-test1:/usr/local/src/lua-5.3.5#cd ~

root@ubuntu-test1:~# export PATH=$PATH:/usr/local/src/lua-5.3.5/src

root@ubuntu-test1:~# lua -v

Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio

#编译安装HAProxy

root@ubuntu-test1:~# wget http://www.haproxy.org/download/2.8/src/haproxy-2.8.0.tar.gz

root@ubuntu-test1:~# mkdir /home/apps/

root@ubuntu-test1:~# tar xf haproxy-2.8.0.tar.gz

root@ubuntu-test1:~# cd haproxy-2.8.0/

root@ubuntu-test1:~/haproxy-2.8.0# make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_PROMEX=1 USE_LUA=1 LUA_INC=/usr/local/src/lua-5.3.5/src/ LUA_LIB=/usr/local/src/lua-5.3.5/src/ #编译安装源码

root@ubuntu-test1:~/haproxy-2.8.0# make install prefix=/home/apps/haproxy

root@ubuntu-test1:~/haproxy-2.8.0#ln -s /home/apps/haproxy/sbin/haproxy /usr/local/sbin/

root@ubuntu-test1:~/haproxy-2.8.0# cd ~

root@ubuntu-test1:~# haproxy -v

HAProxy version 2.8.0-fdd8154 2023/05/31 - https://haproxy.org/

#配置HAProxy

root@ubuntu-test1:~#useradd -m -r -s /sbin/nologin -d /var/lib/haproxy haproxy

root@ubuntu-test1:~# mkdir /etc/haproxy

root@ubuntu-test1:~# vim /etc/haproxy/haproxy.cfg #编辑配置文件

global

maxconn 100000

chroot /home/apps/haproxy

stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin

user haproxy

group haproxy

daemon

nbthread 4

cpu-map auto:1-4 0-3

#log 127.0.0.1 local2 info

defaults

option http-keep-alive

option forwardfor

maxconn 100000

mode http

timeout connect 300000ms

timeout client 300000ms

timeout server 300000ms

listen stats

bind 0.0.0.0:9999

stats enable

log global

stats uri /haproxy-status

stats auth admin:123456

root@ubuntu-test1:~# vim /lib/systemd/system/haproxy.service #编辑service文件

Unit

Description=HAProxy Load Balancer

After=syslog.target network.target

Service

ExecStartPre=/usr/local/sbin/haproxy -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d/ -c -q

ExecStart=/usr/local/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d/ -p /var/lib/haproxy/haproxy.pid

ExecReload=/bin/kill -USR2 $MAINPID

LimitNOFILE=100000

Install

WantedBy=multi-user.target

root@ubuntu-test1:~# chown haproxy.haproxy /home/apps/haproxy/ -R

root@ubuntu-test1:~# chown haproxy.haproxy /etc/haproxy/ -R

root@ubuntu-test1:~# systemctl daemon-reload

root@ubuntu-test1:~# systemctl enable --now haproxy.service

二、HAProxy基本使用

2.1,HAProxy调度算法

#Socat是Linux下的一个多功能的网络工具,可以对服务器动态权重和其它状态进行调整

root@ubuntu-test1:~# apt update && apt -y install socat

root@ubuntu-test1:~# echo "show info" | socat stdio /var/lib/haproxy/haproxy.sock

|-----------------------|----------------|-------------------------------------------------------------------------------|
| 静态算法 不支持socat | static-rr | 基于权重的轮询调度,,其后端主机数量没有限制,相当于 LVS 中的 wrr |
| 静态算法 不支持socat | first | 根据服务器列表位置,自上而下调度,只有第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置 |
| 动态算法支持socat | roundrobin | 基于权重的轮询动态调度算法 |
| 动态算法支持socat | leastconn | 加权的最少连接的动态,支持权重的运行时调整和慢启动,即根据当前连接最少的后端服务器而非权重进行优先调度,适合MySQL场景 |
| 动态算法支持socat | random | 基于随机数作为一致性 hash 的 key ,支持weight 的动态调整,权重越大越容易 获取新请求,适用于大型服务器场或经常添加或删除服务器 |
| source 算法 | map-based | 取模法,对 源地址进行hash计算,再基于服务器总权重的取模,不支持在线调整权重,此算法为hash-type 指定的默认值 |
| source 算法 | consistent | 一致性哈希,当服务器的总权重发生变化时,对调度结果影响是局部的,支持在线调整权重 |
| uri算法 || 基于对用户请求的 URI 的左半部分或整个 uri 做 hash ,再将 hash 结果对总权重进行取模,此算法基于应用层至支持mode http |
| url_param算法 || 对用户请求的 url 中的规定的 params 部分进行 hash计算,再将hash结果对总权重进行取模,若未指定param按 roundrobin 算法 |
| hdr算法 || 对用户每个 http 头部 请求中的指定信息做hash,再将hash结果对总权重进行取模 |
| rdp-cookie算法 || 对 Windows 远程桌面的负载,使用 cookie 保持会话,默认是静态,也可通过指定 hash-type 来定义使用取模法还是一致性 hash |

#HAProxy配置案例-源地址一致性哈希配置

#10.0.0.151--Rocky-test1

#10.0.0.152--Rocky-test2

root@Rocky-test1 \~\]# **yum -y install nginx** \[root@Rocky-test1 \~\]# **systemctl enable --now nginx.service** \[root@Rocky-test1 \~\]# **echo www.wlm.com \> /usr/share/nginx/html/index.html** \[root@Rocky-test2 \~\]#**echo www.wlm.io \> /usr/share/nginx/html/index.html** root@ubuntu-test1:\~# **vim /etc/haproxy/conf.d/web.cfg** #创建子配置文件 frontend web_http bind 10.0.0.161:80 use_backend web_hosts backend web_hosts balance source hash-type consistent server web1 10.0.0.151:80 check weight 2 inter 3000 fall 3 rise 2 server web2 10.0.0.152:80 check weight 1 inter 3000 fall 3 rise 2 root@ubuntu-test1:\~#**haproxy -c -f /etc/haproxy/conf.d/web.cfg** #检测配置文件 root@ubuntu-test1:\~# **systemctl reload haproxy.service** root@ubuntu-test1:\~# **curl 10.0.0.161** #测试 www.wlm.com

2.2,HAProxy高级用法

#ACL实例

#ACL实例--域名匹配

root@ubuntu-test1:~# vim /etc/hosts

10.0.0.161 www.wlm.com www.wlm.io www.wlm.org

root@ubuntu-test1:~# vim /etc/haproxy/conf.d/web.cfg

frontend web_http

bind 10.0.0.161:80

balance roundrobin

acl com_domain hdr_dom(host) -i www.wlm.com
acl io_domain hdr_dom(host) -i www.wlm.io
use_backend com_hosts if com_domain
use_backend io_hosts if io_domain
default_backend com_hosts

backend com_hosts

server web1 10.0.0.151:80 check weight 2 inter 3000 fall 3 rise 2

backend io_hosts

server web2 10.0.0.152:80 check weight 1 inter 3000 fall 3 rise 2

root@ubuntu-test1:~# systemctl reload haproxy.service

root@ubuntu-test1:~# curl www.wlm.org

www.wlm.com

root@ubuntu-test1:~#curl www.wlm.com

www.wlm.com

root@ubuntu-test1:~# curl www.wlm.io

www.wlm.io

#ACL实例--基于源地址访问控制

root@ubuntu-test1:~# vim /etc/haproxy/conf.d/web.cfg

frontend web_http

......

acl inter_src src 10.0.0.151 10.0.0.152
http-request deny if inter_src

......

root@ubuntu-test1:~# systemctl reload haproxy.service

root@ubuntu-test1:~# curl 10.0.0.161

www.wlm.com

root@Rocky-test1 \~\]# **curl 10.0.0.161** curl: (7) Failed to connect to 10.0.0.161 port 80: Connection refused **#ACL实例--动静分离** root@ubuntu-test1:\~# **vim /etc/haproxy/conf.d/web.cfg** frontend web_http bind 10.0.0.161:80 balance roundrobin acl static path_end -i .jpg .jpeg .html .css .js .png .gif acl php path_end -i .php use_backend com_hosts if static use_backend io_hosts if php default_backend com_hosts backend com_hosts server web1 10.0.0.151:80 check weight 2 inter 3000 fall 3 rise 2 backend io_hosts server web2 10.0.0.152:80 check weight 1 inter 3000 fall 3 rise 2 root@ubuntu-test1:\~# **systemctl reload haproxy.service**

三、高可用Keepalived介绍

3.1,Keepalived介绍

VRRP(Virtual Router Redundancy Protocol),虚拟路由冗余协议,解决静态网关单点风险。物理层面通过路由器、三层交换机实现,软件层面通过Keepalived实现。

Keepalived是高可用集群的通用无状态应用解决方案,其主要功能:

1,基于vrrp协议完成地址流动;

2,为vip地址所在的节点生成ipvs规则(在配置文件中预先定义);

3,为ipvs集群的各RS做健康状态检测;

4,基于脚本调用接口完成脚本中定义的功能,进而影响集群事务,以此支持nginx、haproxy等服务
#Keepalived安装

root@ubuntu-test1:~# apt list keepalived -a

Listing... Done

keepalived/focal-updates 1:2.0.19-2ubuntu0.2 amd64

#编译安装

root@ubuntu-test1:~# apt update && apt -y install make gcc ipvsadm build-essential pkg-config automake autoconf libipset-dev libnl-3-dev libnl-genl-3-dev libssl-dev libxtables-dev libip4tc-dev libip6tc-dev libmagic-dev libsnmp-dev libglib2.0-dev libpcre2-dev libnftnl-dev libmnl-dev libsystemd-dev #安装依赖包

root@ubuntu-test1:~# wget https://keepalived.org/software/keepalived-2.3.0.tar.gz

root@ubuntu-test1:~# tar xf keepalived-2.3.0.tar.gz -C /usr/local/src/

root@ubuntu-test1:~# mkdir /home/apps/

root@ubuntu-test1:~# cd /usr/local/src/keepalived-2.3.0/

root@ubuntu-test1:/usr/local/src/keepalived-2.3.0#./configure --prefix=/home/apps/keepalived --disable-iptables #指定目录编译

root@ubuntu-test1:/usr/local/src/keepalived-2.3.0# make -j2 && make install

root@ubuntu-test1:/usr/local/src/keepalived-2.3.0# cp ./keepalived/keepalived.service /lib/systemd/system/ #复制service文件

root@ubuntu-test1:/usr/local/src/keepalived-2.3.0# cd ~

root@ubuntu-test1:~# systemctl daemon-reload

root@ubuntu-test1:~# cp /home/apps/keepalived/etc/keepalived/keepalived.conf.sample /home/apps/keepalived/etc/keepalived/ #拷贝模板配置文件至本地,注意网卡名称

root@ubuntu-test1:/home/apps/keepalived#systemctl enable --now keepalived.service

root@ubuntu-test1:~#hostname -I

10.0.0.161 192.168.200.16 192.168.200.17 192.168.200.18

root@ubuntu-test1:~#vim /home/apps/keepalived/etc/keepalived/keepalived.conf #添加子配置文件路径

include /etc/keepalived/*.conf

root@ubuntu-test1:~# vim /home/apps/keepalived/etc/sysconfig/keepalived #开启日志

KEEPALIVED_OPTIONS="-D -S 6"

root@ubuntu-test1:~# vim /etc/rsyslog.conf

local6.* /var/log/keepalived.log

root@ubuntu-test1:~# systemctl restart rsyslog.service keepalived.service

root@ubuntu-test1:~#ll /var/log/keepalived.log

-rw-r----- 1 syslog adm 6261 Oct 23 10:44 /var/log/keepalived.log

3.2,Keepalived单主架构实现

#root@ubuntu-test1--10.0.0.161--主节点

#root@ubuntu-test2--10.0.0.162--备节点

#对两台主机进行编译安装Keepalived,同时添加网卡(仅主机模式)做心跳网络

root@ubuntu-test1:~# ip link set ens36 up

root@ubuntu-test1:~#vim /etc/netplan/00-installer-config.yaml

network:

ethernets:

ens33:

dhcp4: no

addresses:

  • 10.0.0.161/24

gateway4: 10.0.0.2

nameservers:

addresses: [8.8.8.8,223.5.5.5]

ens36:
dhcp4: no
addresses:

  • 192.168.10.10/24

version: 2

root@ubuntu-test1:~# netplan apply

#同样操作为ubuntu-test2添加192.168.10.20的网卡

#为两个节点配置keepalived配置文件

root@ubuntu-test1:~# vim /home/apps/keepalived/etc/keepalived/keepalived.conf

global_defs {

router_id LVS_DEVEL_161

vrrp_skip_check_adv_addr

vrrp_garp_interval 0

vrrp_gna_interval 0

vrrp_mcast_group4 230.0.0.100

}

include /etc/keepalived/*.conf

root@ubuntu-test1:~# vim /etc/keepalived/domain1.conf

vrrp_instance VI_1 {

state MASTER
interface ens36
virtual_router_id 88
priority 100

advert_int 1

authentication {

auth_type PASS

auth_pass 123456

}

virtual_ipaddress {

10.0.0.160/24 dev ens33 label ens33:1

}

}

root@ubuntu-test1:~# hostname -I

10.0.0.161 10.0.0.160 192.168.10.10

root@ubuntu-test2:~# vim /etc/keepalived/domain1.conf

vrrp_instance VI_1 {

state BACKUP

interface ens36

virtual_router_id 88

priority 80

advert_int 1

authentication {

auth_type PASS

auth_pass 123456

}

virtual_ipaddress {

10.0.0.160/24 dev ens33 label ens33:1

}

}

root@ubuntu-test2:~# hostname -I

10.0.0.162 192.168.10.20

#在心跳网络抓包

root@ubuntu-test2:~# tcpdump -i ens36 -nn host 230.0.0.100

15:24:52.577437 IP 192.168.10.10 > 230.0.0.100: VRRPv2, Advertisement, vrid 88, prio 100, authtype simple, intvl 1s, length 20

#默认使用多播通信会造成网络堵塞,可设置单播模式减少流量,单播优先级高于多播

root@ubuntu-test1:~# vim /etc/keepalived/domain1.conf

vrrp_instance VI_1 {

.......

unicast_src_ip 192.168.10.10

unicast_peer {

192.168.10.20

}

}

root@ubuntu-test2:~# vim /etc/keepalived/domain1.conf

vrrp_instance VI_1 {

.......

unicast_src_ip 192.168.10.20

unicast_peer {

192.168.10.10

}

}

3.3,脑裂

脑裂现象:主备节点同时拥有同一个VIP

产生原因

1,心跳线故障(在虚拟机环境中测试可以通过修改网卡的工作模式实现,断开网卡不行)

2,防火墙错误配置(在从节点执行iptables -A INPUT -s 主服务心跳网卡IP -j DROP进行模拟)

3,Keepalived配置错误(多播地址不同,interface错误,virtual_router_id不一致,密码不一致)

脑裂检测方法

在网络相连的其他主机使用arping -I 网卡 -c1 VIP命令

root@Rocky-test1 \~\]# arping -I ens160 -c1 10.0.0.160 ARPING 10.0.0.160 from 10.0.0.151 ens160 Unicast reply from 10.0.0.160 \[00:0C:29:40:FA:70\] 1.172ms Unicast reply from 10.0.0.160 \[00:0C:29:F7:F6:CF\] 1.264ms

四、Keepalived实例--实现单主架构的LVS-DR模型

#在3.2单主架构的基础上配置两台后端真实服务器

#root@Rocky-test1--10.0.0.151

#root@Rocky-test2--10.0.0.152

#在真实服务器配置

root@Rocky-test1 \~\]# **echo \`hostname\` \> /usr/share/nginx/html/index.html** \[root@Rocky-test1 \~\]# **echo 1 \> /proc/sys/net/ipv4/conf/all/arp_ignore** \[root@Rocky-test1 \~\]# **echo 2 \> /proc/sys/net/ipv4/conf/all/arp_announce** \[root@Rocky-test1 \~\]# **echo 1 \> /proc/sys/net/ipv4/conf/lo/arp_ignore** \[root@Rocky-test1 \~\]#**echo 2 \> /proc/sys/net/ipv4/conf/lo/arp_announce** \[root@Rocky-test1 \~\]# **ifconfig lo:1 10.0.0.160/32** #在Rocky-test2上进行同样操作 **#在Keepalived节点上为子文件追加相同配置** root@ubuntu-test2:\~# **vim /etc/keepalived/domain1.conf** ...... virtual_server 10.0.0.160 80 { delay_loop 3 lb_algo wrr lb_kind DR protocol TCP real_server 10.0.0.151 80 { weight 1 HTTP_GET { url { path / status_code 200 } connect_timeout 1 nb_get_retry 3 delay_before_retry 1 } } real_server 10.0.0.152 80 { weight 2 HTTP_GET { url { path / status_code 200 } connect_timeout 1 nb_get_retry 3 delay_before_retry 1 } } } root@ubuntu-test2:\~# **systemctl restart keepalived.service** root@ubuntu-test1:\~# **ipvsadm -Ln** #查看LVS调度规则 IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -\> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 10.0.0.160:80 wrr -\> 10.0.0.151:80 Route 1 0 0 -\> 10.0.0.152:80 Route 2 0 0 root@ubuntu-test3:\~# **while true;do curl 10.0.0.160;sleep 1;done** #在其他客户端访问测试 Rocky-test1 Rocky-test2 Rocky-test2 Rocky-test1 Rocky-test2 Rocky-test2 Rocky-test1 Rocky-test2 Rocky-test2 **#添加vrrp_script自定义资源监控脚本,实现节点自动切换** root@ubuntu-test1:\~# **vim /home/apps/keepalived/etc/keepalived/keepalived.conf** ....... vrrp_script check_keepalived { script /etc/keepalived/check_keepalived.sh interval 1 timeout 2 weight -30 fall 2 rise 3 } root@ubuntu-test1:\~# **vim /etc/keepalived/domain1.conf** vrrp_instance VI_1 { ....... track_script { check_keepalived } } root@ubuntu-test1:\~# **vim /etc/keepalived/check_keepalived.sh** #!/bin/bash /usr/bin/killall -0 keepalived root@ubuntu-test1:\~# **chmod +x /etc/keepalived/check_keepalived.sh** root@ubuntu-test1:\~#**systemctl restart keepalived.service** root@ubuntu-test1:\~# **systemctl stop keepalived.service** #模拟服务故障 root@ubuntu-test1:\~# **hostname -I** 10.0.0.161 192.168.10.10

五、实例--通过Keepalived实现HAProxy高可用

#ubuntu-test1--10.0.0.161--部署Keepalived+HAProxy

#ubuntu-test2--10.0.0.162--部署Keepalived+HAProxy

#Rocky-test1--10.0.0.151--部署Nginx

#Rocky-test2--10.0.0.152--部署Nginx

#先在ubuntu-test1,2创建HAProxy和keepalived子配置文件

root@ubuntu-test1:~# vim /etc/keepalived/domain1.conf

vrrp_instance VI_1 {

state MASTER

interface ens36

virtual_router_id 88

priority 100

advert_int 1

authentication {

auth_type PASS

auth_pass 123456

}

virtual_ipaddress {

10.0.0.160/24 dev ens33 label ens33:1

}

unicast_src_ip 192.168.10.10

unicast_peer {

192.168.10.20

}

track_script {

check_keepalived

}

}

root@ubuntu-test1:~#vim /etc/haproxy/conf.d/web.cfg

frontend web_http

bind 10.0.0.160:80

use_backend web_hosts

backend web_hosts

balance roundrobin

server web1 10.0.0.151:80 check weight 2 inter 3000 fall 3 rise 2

server web2 10.0.0.152:80 check weight 1 inter 3000 fall 3 rise 2

root@ubuntu-test1:~#systemctl reload haproxy.service keepalived.service

#编辑内核参数,允许进程绑定到不属于本机接口的 IP 地址

root@ubuntu-test1:~# vim /etc/sysctl.conf

net.ipv4.ip_nonlocal_bind = 1

root@ubuntu-test1:~# sysctl -p

#在其他客户端访问测试

root@Rocky-test3 \~\]# **curl 10.0.0.160** 10.0.0.151 Rocky-test1 \[root@Rocky-test3 \~\]# **curl 10.0.0.160** 10.0.0.151 Rocky-test1 \[root@Rocky-test3 \~\]# **curl 10.0.0.160** 10.0.0.152 Rocky-test2 **#在ubuntu-test1添加VRRP脚本实现高可用** root@ubuntu-test1:\~# **vim /etc/keepalived/check_haproxy.sh** #!/bin/bash if /usr/bin/killall -0 haproxy ;then exit 0 else systemctl restart haproxy fi root@ubuntu-test1:\~# **chmod +x /etc/keepalived/check_haproxy.sh** root@ubuntu-test1:\~# **vim /home/apps/keepalived/etc/keepalived/keepalived.conf** ....... vrrp_script check_haproxy { script /etc/keepalived/check_haproxy.sh interval 1 timeout 2 weight -30 fall 2 rise 3 } root@ubuntu-test1:\~#**vim /etc/keepalived/domain1.conf** ....... track_script { check_keepalived check_haproxy } } root@ubuntu-test1:\~# **systemctl restart keepalived.service** **#对后端服务器进行证书加密,HAProxy配置四层代理** \[root@Rocky-test1 \~\]# **mkdir /home/nginx.cert** \[root@Rocky-test1 \~\]#**cd /home/nginx.cert** \[root@Rocky-test1 nginx.cert\]# **openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 3650 -out ca.crt** \[root@Rocky-test1 nginx.cert\]# **openssl req -newkey rsa:4096 -nodes -sha256 -keyout www.wlm.com.key -out www.wlm.com.csr** \[root@Rocky-test1 nginx.cert\]#**openssl x509 -req -days 365 -in www.wlm.com.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out www.wlm.com.crt** \[root@Rocky-test1 nginx.cert\]# **cat www.wlm.com.crt ca.crt \> www.wlm.com.pem** \[root@Rocky-test1 \~\]# **vim /etc/nginx/nginx.conf** server { listen 80; listen 443 ssl http2; server_name www.wlm.com; root /usr/share/nginx/html; ssl_certificate /home/nginx.cert/www.wlm.com.pem; ssl_certificate_key /home/nginx.cert/www.wlm.com.key; if ( $scheme = http ) { rewrite \^(.\*) https://$server_name/$1 redirect; } \[root@Rocky-test1 \~\]# **systemctl reload nginx.service** root@ubuntu-test1:\~#**vim /etc/haproxy/conf.d/web.cfg** frontend web_http mode tcp bind 10.0.0.160:80 use_backend web_hosts backend web_hosts balance roundrobin mode tcp server web1 10.0.0.151:80 check weight 2 inter 3000 fall 3 rise 2 server web2 10.0.0.152:80 check weight 1 inter 3000 fall 3 rise 2 \[root@Rocky-test3 \~\]# **curl -k https://www.wlm.com** #测试成功 10.0.0.151 Rocky-test1

六、NoSQL数据库Redis

6.1,Redis简介

NoSQL 数据库,全称为****Not Only SQL,既可以适用关系型数据库也可以使用其他类型的数据存储。

Redis是一个开源的Key-Value存储系统,使用C语言开发,支持多种编程语言的API。它是一个高速缓存数据库,采用内存存储,并支持持久化,能够提供高性能的数据读写操作。

Redis特性:

属于非关系数据库,键值对数据库

高性能

纯内存操作,数据操作采用单线程(还有其他线程做备份等操作)

支持持久化

支持多种数据结构,编程语言
Redis高性能原因:

纯内存,数据操作较硬盘快

单线程操作数据,避免线程竞争,非阻塞IO,取消锁机制,epoll机制IO

|----------------|---------------------------------------|
| Redis常见应用场景 ||
| 缓存 | 缓存RDBMS中数据,比如网站的查询结果、商品信息、微博、新闻、消息 |
| Session 共享 | 实现Web集群中的多服务器间的session共享 |
| 计数器 | 商品访问排行榜、浏览数、粉丝数、关注、点赞、评论等和次数相关的数值统计场景 |
| 社交 | 朋友圈、共同好友、可能认识他们等 |
| 地理位置 | 基于地理信息系统实现摇一摇、附近的人、外卖等功能 |
| 消息队列 | ELK等日志系统缓存、业务的订阅/发布系统 |

|----------|----------------------------------------|-----------------------------------------------------|
| 名称 | 概念 | 解决方法 |
| 缓存穿透 | 缓存和Redis数据库中没有, MySQL关系数据库也没有的数据,被请求访问 | 在接口层增加校验,如用户鉴权校验 对无法查询的数据短期定义key-null |
| 缓存击穿 | 缓存和Redis数据库中没有, MySQL数据库中有的数据,被请求访问 | 设置热点数据永远不过期 |
| 缓存雪崩 | 缓存中数据大批量到过期时间, 而查询数据量巨大,引起数据库压力过大甚至宕机 | 设置热点数据永远不过期 缓存数据的过期时间设置随机 若数据库为分布式,热点数据均匀 分布不同缓存数据库 |

#编译安装Redis

root@ubuntu-test1:~# apt update && apt -y install gcc make libjemalloc-dev libsystemd-dev#安装依赖包

root@ubuntu-test1:~# wget http://download.redis.io/releases/redis-7.2.0.tar.gz

root@ubuntu-test1:~# tar xf redis-7.2.0.tar.gz

root@ubuntu-test1:~# mkdir /home/apps

root@ubuntu-test1:~#cd redis-7.2.0/

root@ubuntu-test1:~/redis-7.2.0# make -j 2 USE_SYSTEMD=yes PREFIX=/home/apps/redis install

root@ubuntu-test1:~# echo 'PATH=/home/apps/redis/bin:$PATH' > /etc/profile.d/redis.sh

root@ubuntu-test1:~#. /etc/profile.d/redis.sh

#优化参数,消除报警

root@ubuntu-test1:~# cat /proc/sys/net/core/somaxconn #需要大于128
4096

root@ubuntu-test1:~# echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.local

root@ubuntu-test1:~# chmod +x /etc/rc.local

root@ubuntu-test1:~# vim /etc/sysctl.conf

vm.overcommit_memory = 1

root@ubuntu-test1:~# sysctl -p

#创建Redis用户和Service文件

root@ubuntu-test1:~# useradd -r -s /sbin/nologin redis

root@ubuntu-test1:~# mkdir /home/apps/redis/{etc,data,log,run}

root@ubuntu-test1:~# cp /root/redis-7.2.0/redis.conf /home/apps/redis/etc/

root@ubuntu-test1:~# chown redis.redis -R /home/apps/redis/

root@ubuntu-test1:~#vim /lib/systemd/system/redis.service

Unit

Description=Redis persistent key-value database

After=network.target

Service

ExecStart=/home/apps/redis/bin/redis-server /home/apps/redis/etc/redis.conf --supervised systemd

ExecStop=/bin/kill -s QUIT $MAINPID

Type=notify

User=redis

Group=redis

RuntimeDirectory=redis

RuntimeDirectoryMode=0755

LimitNOFILE=1000000

Install

WantedBy=multi-user.target

root@ubuntu-test1:~# systemctl daemon-reload

root@ubuntu-test1:~# systemctl enable --now redis.service

root@ubuntu-test1:~# redis-cli

127.0.0.1:6379> ping

PONG

127.0.0.1:6379> info

Server

redis_version:7.2.0

......

Keyspace

127.0.0.1:6379> exit

#修改配置文件,开启远程端口

root@ubuntu-test1:~# vim /home/apps/redis/etc/redis.conf

bind 0.0.0.0

logfile "/home/apps/redis/log/redis.log"

save 3600 1 300 100 60 10000

dir /home/apps/redis/data

repl-diskless-sync no #取消无盘同步,使用硬盘同步

rename-command FLUSHALL "" #禁用该命令

rename-command SHUTDOWN ""

requirepass 123456

root@ubuntu-test1:~# systemctl restart redis.service

root@ubuntu-test1:~# grep -vE '^#|^$' /home/apps/redis/etc/redis.conf | grep slow

slowlog-log-slower-than 10000 #慢查询定义的时间

slowlog-max-len 128 #保留的最近慢查询记录上限

root@ubuntu-test1:~# redis-cli -a 123456

127.0.0.1:6379> slowlog len #查询慢查询条数

(integer) 0

127.0.0.1:6379> slowlog get #查看慢查询记录

6.2,Redis持久化

|---------------|------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------|
| 方法 | RDB(Redis DataBase) | AOF(AppendOnlyFile) |
| 概念 | 基于某个时间点的快照, 只保留一个最新版本, 相当于MySQL 的完全备份 | 初次启动时进行完全备份, 后续将持续执行增量性备份 |
| 实现 方式 | save: 同步, 不推荐, 使用主进程完成,会阻赛其它命令 bgsave:异步后台执行 , 会开启子进程,不会阻赛其它命令 | bgrewriteaof:会自动开启,也可手动执行,对数据进行重新整理 |
| 优点 | 1,只保存某个时间点的数据,恢复无需额外操作,适合灾备处理 2,在大集群时恢复速度较AOF快 | 1,数据安全性相对较高,每秒自动执行 2,写入操作采用append模式,宕机也不会损坏数据 3,会自动重写,重写操作绝对安全 4,AOF有记录所有操作的日志文件,可用于数据重建 |
| 缺点 | 1,不能实时保存,存在少量数据丢失风险 2,在数据集较大时,子进程可能会非常耗时,导致客户端长时间等待 | 1,AOF会记录重复操作,数据量大 2,AOF在恢复大数据集的速度比 RDB慢 3,fsync策略是appendfsync no时, AOF保存到磁盘的速度可能会慢于RDB 4,更易出现BUG |

redis.conf内的RDB相关参数

save 3600 1 300 100 60 10000 #bgsave触发条件

dir /home/apps/redis/data #bgsave存放位置

dbfilename dump.rdb #RDB文件名
#正确开启AOF功能(RDB已开启且已有数据),先动态修改内存参数,再修改配置文件

#AOF默认为关闭,初次开启并重启服务后,AOF会因为较高优先级先启动,AOF默认无数据文件会导致旧数据丢失

root@ubuntu-test1:~#ll /home/apps/redis/data/

-rw-r--r-- 1 redis redis 108 Oct 30 16:17 dump.rdb

root@ubuntu-test1:~# redis-cli -a 123456

127.0.0.1:6379>KEYS *

  1. "b"

  2. "a"

  3. "c"

127.0.0.1:6379> CONFIG GET appendonly

  1. "appendonly"

  2. "no"

127.0.0.1:6379> CONFIG SET appendonly yes

OK

127.0.0.1:6379> exit

root@ubuntu-test1:~#ll /home/apps/redis/data/

drwxr-xr-x 2 redis redis 4096 Oct 30 16:40 appendonlydir/

-rw-r--r-- 1 redis redis 108 Oct 30 16:17 dump.rdb

root@ubuntu-test1:~# vim /home/apps/redis/etc/redis.conf

appendonly yes

#模拟服务重启,测试数据是否会丢失

root@ubuntu-test1:~# systemctl restart redis.service

root@ubuntu-test1:~# redis-cli -a 123456

127.0.0.1:6379> KEYS *

  1. "a"

  2. "c"

  3. "b"

#Redis服务BGWRITEAOF配置介绍

root@ubuntu-test1:~# grep -vE '^#|^$' /home/apps/redis/etc/redis.conf|grep aof

appendfilename "appendonly.aof"

auto-aof-rewrite-percentage 100 #当增长超过100比例会触发执行

auto-aof-rewrite-min-size 64mb #触发的最小文件大小

aof-load-truncated yes #是否加载末尾异常的AOF文件(如断电,主进程kill)

aof-use-rdb-preamble yes

aof-timestamp-enabled no

aof-rewrite-incremental-fsync yes

root@ubuntu-test1:~# grep -vE '^#|^$' /home/apps/redis/etc/redis.conf|grep appendfsync

appendfsync everysec

no-appendfsync-on-rewrite no #是否暂缓AOF记录立即同步至磁盘,默认否最安全但是会造成阻塞;开启暂时会避免阻塞,但是Redis故障会导致数据丢失

6.3,Redis使用介绍

Redis常用命令:

INFO--显示Redis运行状态信息

SELECT--切换数据库

KEYS--查看当前数据库下的所有key,慎用

BGSAVE--手动执行RDB

DBSIZE --返回当前库下的所有key 数量

FLUSHDB --强制清空当前库中的所有key,慎用

FLUSHALL --删除所有数据,慎用

SHUTDOWN--关闭服务

TYPE--查询key的数据类型

|---------------|----------------------------------------|
| 数据类型 | 特点 |
| 字符串string | 基本数据类型,能包含任意类型的数据,单个值最大512M字节 |
| 列表list | 有序,可重复,可实现队列和栈 |
| 集合set | 无序,不可重复,实现集合操作(与sinter,或sunion,非sdiff) |
| 有序集合zset | 有序,无重复元素,由score(不可重复)和value组成,用于实现排行榜 |
| 字典hash | 无序,每个元素都是键值对,可存储复杂数据 |

七、实例--构建Redis主从哨兵模式

7.1,主从复制优化

Redis的主从同步是非阻塞的,即同步过程不会影响主服务器的正常访问;其主从复制分为全量同步和增量同步两种,主节点重启会导致全量同步,从节点重启只会导致增量同步。

全量复制触发情况:

1,从节点首次连接主节点;

2,从节点的复制偏移量不在复制积压缓冲区内;

3,从节点无法连接主节点超过一定的时间;

避免全量复制:

1,初次全量复制不可避免,后续全量复制可利用级联结构在低业务量时进行;
2,增大repl-backlog-size数值,避免复制积压缓冲区不足;

3,节点RUN_ID不匹配:主节点重启导致RUN_ID变化,会触发全量复制,可用config命令动态修改配置。故障转移例如哨兵或集群选举新的主节点也不会全量复制(从主节点重启只会触发增量复制);

避免复制风暴:
1,单主节点复制风暴(当主节点重启,多从节点复制)
解决方法:使用级联复制
2,单机器多实例复制风暴(机器宕机后,大量全量复制)
解决方法:主节点分散多机器

7.2,常见主从复制故障

1,主从节点的maxmemory不一致,主节点内存大于从节点内存,主从复制可能丢失数据

2,rename-command命令不一致,错执行被禁用的命令会导致主从节点不同步

3,从节点配置的master密码错误,验证不通过,无法建立主从同步

4,Redis版本不同导致兼容问题

5,开启了安全模式且未开启远程设置,无法进行远程连接

7.3,实例--构筑主从哨兵模式

#ubuntu-test1--10.0.0.161

#ubuntu-test2--10.0.0.162

#ubuntu-test3--10.0.0.163

#为三台服务器编译安装Redis并保持redis.conf配置一致(注意,Redis密码需要相同)

#以162为主节点,163为从节点创建主从同步测试

root@ubuntu-test3:~# vim /home/apps/redis/etc/redis.conf #修改配置文件重启生效

replicaof 10.0.0.162 6379

masterauth 123456

root@ubuntu-test3:~# redis-cli -a 123456 #配置修改在从节点进行

127.0.0.1:6379> replicaof 10.0.0.162 6379 #在线修改配置

OK

127.0.0.1:6379> config set masterauth 123456

OK

127.0.0.1:6379> info replication

Replication

role:slave

master_host:10.0.0.162

master_port:6379

master_link_status:up

root@ubuntu-test2:~# redis-cli -a 123456 #登录主节点查看信息

127.0.0.1:6379>info replication

role:master

connected_slaves:1

slave0:ip=10.0.0.163,port=6379,state=online,offset=3290,lag=0

127.0.0.1:6379> set key1 1

root@ubuntu-test3:~# redis-cli -a 123456 get key1 #确认主节点数据同步

"1"

#取消163从节点

root@ubuntu-test3:~# redis-cli -a 123456 replicaof no one #在从节点执行取消主从命令

root@ubuntu-test3:~# redis-cli -a 123456 info replication #验证信息

Replication

role:master

connected_slaves:0

#正式搭建主从哨兵架构

#在所有节点配置下列信息

root@ubuntu-test1:~#vim /home/apps/redis/etc/redis.conf

replicaof 10.0.0.161 6379 #7.2版本主节点不能配置该项

masterauth 123456

requirepass 123456

root@ubuntu-test1:~# cp ./redis-7.2.0/sentinel.conf /home/apps/redis/etc/

root@ubuntu-test1:~# chown redis.redis /home/apps/redis/etc/sentinel.conf

root@ubuntu-test1:~# vim /home/apps/redis/etc/sentinel.conf

dir /home/apps/redis/data

logfile "/home/apps/redis/log/sentinel.log"

sentinel monitor mymaster 10.0.0.161 6379 2

sentinel auth-pass mymaster 123456

sentinel down-after-milliseconds mymaster 5000 #判断主节点下线时间5s

root@ubuntu-test1:~# systemctl restart redis.service

root@ubuntu-test1:~# vim /lib/systemd/system/redis-sentinel.service

Unit

Description=Redis Sentinel

After=network.target

Service

ExecStart=/home/apps/redis/bin/redis-sentinel /home/apps/redis/etc/sentinel.conf --supervised systemd

ExecStop=/bin/kill -s QUIT $MAINPID

User=redis

Group=redis

RuntimeDirectory=redis RuntimeDirectory

Mode=0755

Install

WantedBy=multi-user.target

root@ubuntu-test1:~#systemctl enable --now redis-sentinel.service

root@ubuntu-test1:~#redis-cli -p 26379 info sentinel #查看哨兵状态

Sentinel

sentinel_masters:1

sentinel_tilt:0

sentinel_tilt_since_seconds:-1

sentinel_running_scripts:0

sentinel_scripts_queue_length:0

sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=10.0.0.161:6379,slaves=2,sentinels=3

#停止主节点服务,验证哨兵机制

root@ubuntu-test1:~# systemctl stop redis.service

root@ubuntu-test2:~# redis-cli -a 123456 info replication

Replication

role:slave
master_host:10.0.0.163

master_port:6379

master_link_status:up

root@ubuntu-test3:~# redis-cli -a 123456 info replication

Replication

role:master

connected_slaves:1

slave0:ip=10.0.0.162,port=6379,state=online,offset=88277,lag=0

master_failover_state:no-failover

#重启启动ubuntu-test1上的Redis

root@ubuntu-test1:~# systemctl start redis.service

root@ubuntu-test1:~# redis-cli -a 123456 info replication

Replication

role:slave
master_host:10.0.0.163

master_port:6379

master_link_status:up

root@ubuntu-test1:~# cat /home/apps/redis/etc/redis.conf | grep replicaof #哨兵自动修改配置文件

replicaof 10.0.0.163 6379

八、实例--三节点Redis集群搭建

哨兵只能解决Redis****高可用,实现自动故障转移,无法解决单主节点的写入性能瓶颈,使用分布式集群可解决该问题(建立Cluster时,节点需要清空数据,且网络中不能有哨兵主从)

#ubuntu-test1--10.0.0.161--Redis主节点

#ubuntu-test2--10.0.0.162--Redis主节点

#ubuntu-test3--10.0.0.163--Redis主节点

#ubuntu-test--10.0.0.160--安装多实例Redis做从节点

#在10.0.0.161/162/163主节点上修改配置文件

root@ubuntu-test1:~# vim /home/apps/redis/etc/redis.conf

masterauth "123456"

requirepass "123456"

cluster-enabled yes

cluster-config-file nodes-6379.conf

cluster-require-full-coverage no

#在10.0.0.160上配置多实例

root@ubuntu:~# vim /home/apps/redis/etc/redis6379.conf

bind 0.0.0.0

port 6379

pidfile "/var/run/redis_6379.pid"

logfile "/home/apps/redis/log/redis6379.log"

dbfilename "dump6379.rdb"

masterauth "123456"

requirepass "123456"

cluster-enabled yes

cluster-config-file nodes-6379.conf

cluster-require-full-coverage no

root@ubuntu:~# sed 's/6379/6380/' /home/apps/redis/etc/redis6379.conf > /home/apps/redis/etc/redis6380.conf

root@ubuntu:~# sed 's/6379/6381/' /home/apps/redis/etc/redis6379.conf > /home/apps/redis/etc/redis6381.conf

root@ubuntu:~# vim /lib/systemd/system/redis6379.service

......

ExecStart=/home/apps/redis/bin/redis-server /home/apps/redis/etc/redis6379.conf --supervised systemd

......

root@ubuntu:~#sed 's/6379/6380/' /lib/systemd/system/redis6379.service > /lib/systemd/system/redis6380.service

root@ubuntu:~# sed 's/6379/6381/' /lib/systemd/system/redis6379.service > /lib/systemd/system/redis6381.service

root@ubuntu:~#systemctl daemon-reload

root@ubuntu:~# systemctl enable --now redis6379.service redis6380.service redis6381.service

root@ubuntu:~#tree /home/apps/redis/

/home/apps/redis/

├── bin

│ ├── redis-benchmark

│ ├── redis-check-aof -> redis-server

│ ├── redis-check-rdb -> redis-server

│ ├── redis-cli

│ ├── redis-sentinel -> redis-server

│ └── redis-server

├── data

│ ├── nodes-6379.conf

│ ├── nodes-6380.conf

│ └── nodes-6381.conf

├── etc

│ ├── redis6379.conf

│ ├── redis6380.conf

│ └── redis6381.conf

├── log

│ ├── redis6379.log

│ ├── redis6380.log

│ ├── redis6381.log

│ └── redis.log

└── run

root@ubuntu-test1:~# redis-cli -a 123456 --cluster create 10.0.0.161:6379 10.0.0.162:6379 10.0.0.163:6379 10.0.0.160:6379 10.0.0.160:6380 10.0.0.160:6381 --cluster-replicas 1 #组建集群

>>> Performing hash slots allocation on 6 nodes...

Master[0] -> Slots 0 - 5460

Master[1] -> Slots 5461 - 10922

Master[2] -> Slots 10923 - 16383

Adding replica 10.0.0.160:6380 to 10.0.0.161:6379

Adding replica 10.0.0.160:6381 to 10.0.0.162:6379

Adding replica 10.0.0.160:6379 to 10.0.0.163:6379

M: d48544aa7962934c443741a43f88cbb38cb5244d 10.0.0.161:6379

slots:[0-5460],[7365],[15495] (5461 slots) master

M: c954b82ff2f86fc5feecca51b6e481010e98dc3c 10.0.0.162:6379

slots:[3300],[5461-10922],[15495] (5462 slots) master

M: fba93a9b96fff704a86b66fbf83ffb33824bc466 10.0.0.163:6379

slots:[3300],[7365],[10923-16383] (5461 slots) master

S: ddc047ac5f0ef2bdc1e77076aace31ecc219d7fa 10.0.0.160:6379

replicates fba93a9b96fff704a86b66fbf83ffb33824bc466

S: bfd046c0b9f4ac6318cfb218edb2327d8b2d5daa 10.0.0.160:6380

replicates d48544aa7962934c443741a43f88cbb38cb5244d

S: 7f2e05c72c2c54eece48a908d0a3c59662d0f8c7 10.0.0.160:6381

replicates c954b82ff2f86fc5feecca51b6e481010e98dc3c

Can I set the above configuration? (type 'yes' to accept): yes

root@ubuntu-test1:~# cat /home/apps/redis/data/nodes-6379.conf #节点信息存放文件

root@ubuntu-test1:~# redis-cli -a 123456 cluster nodes

Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.

15af0ab4decfe08de958223266efb401dd29b377 10.0.0.161:6379@16379 myself,master - 0 1730704529000 1 connected 0-5460

60d3a2d1b5c24e03683e7453e7c05f6b6ebdeb56 10.0.0.162:6379@16379 master - 0 1730704533365 2 connected 5461-10922

148d09fcaa36daeb8ab367338eede0f6a01dd941 10.0.0.160:6381@16381 slave 60d3a2d1b5c24e03683e7453e7c05f6b6ebdeb56 0 1730704531000 2 connected

d8ee0bd1c084a34e3a77ebfc860156ea44a54644 10.0.0.160:6380@16380 slave 15af0ab4decfe08de958223266efb401dd29b377 0 1730704531000 1 connected

be21431937366822cb55ef481d9562c0e9253583 10.0.0.160:6379@16379 slave 40d8dfe76324fab1925bf1c457eb4aaf2f9b9ac4 0 1730704532328 3 connected

40d8dfe76324fab1925bf1c457eb4aaf2f9b9ac4 10.0.0.163:6379@16379 master - 0 1730704531291 3 connected 10923-16383

root@ubuntu-test1:~# redis-cli -a 123456 -c #-c自动跳转槽位
127.0.0.1:6379> set a 1

-> Redirected to slot [15495] located at 10.0.0.163:6379

OK
10.0.0.163:6379> set z 2

-> Redirected to slot [8157] located at 10.0.0.162:6379

OK
10.0.0.162:6379>get a

-> Redirected to slot [15495] located at 10.0.0.163:6379

"1"

**Redis cluster的从节点是只读连接的,也就是说集群模式中的从节点是拒绝任何读写请求的。并且当多个节点运行一段时间后,可能会出现倾斜现象,**某个节点数据偏多,内存消耗更大,或者用户请求访问更多,主要原因如下:

节点和槽分配不均

不同槽对应键值数量差异较大

包含bigkey,建议少用

内存相关配置不一致

热点数据不均衡 : 一致性不高时,可以使用本缓存和MQ

相关推荐
郝亚军2 小时前
ubuntu-18.04.6-desktop-amd64安装步骤
linux·运维·ubuntu
Konwledging2 小时前
kernel-devel_kernel-headers_libmodules
linux
Web极客码2 小时前
CentOS 7.x如何快速升级到CentOS 7.9
linux·运维·centos
一位赵2 小时前
小练2 选择题
linux·运维·windows
代码游侠3 小时前
学习笔记——Linux字符设备驱动开发
linux·arm开发·驱动开发·单片机·嵌入式硬件·学习·算法
Lw老王要学习3 小时前
CentOS 7.9达梦数据库安装全流程解析
linux·运维·数据库·centos·达梦
CRUD酱4 小时前
CentOS的yum仓库失效问题解决(换镜像源)
linux·运维·服务器·centos
zly35004 小时前
VMware vCenter Converter Standalone 转换Linux系统,出现两个磁盘的处理
linux·运维·服务器
Albert Edison4 小时前
【Python】函数
java·linux·python·pip
General_G4 小时前
Linux中的信号
linux·运维·服务器