架构学习第四周--高可用与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

相关推荐
我是高手高手高高手14 分钟前
ThinkPHP8多应用配置及不同域名访问不同应用的配置
linux·服务器·前端·php
虾稿2 小时前
[手机Linux] 七,NextCloud优化设置
linux·运维·服务器
首发运维2 小时前
centos 释放系统预留内存并关闭Kdump服务
linux·运维·centos·linux操作系统问题
新子-存在了2 小时前
linux中 mysql备份
linux·运维·mysql
最后一个bug2 小时前
rt-linux中使用mlockall与free的差异
linux·c语言·arm开发·单片机·嵌入式硬件·算法
ZHOUPUYU2 小时前
VMware虚拟机超详细安装Linux教程(最新版)
linux·运维·服务器·windows·微软·centos·虚拟机
初级代码游戏2 小时前
关于linux的ld.so.conf.d
linux·运维·服务器
xianwu5432 小时前
反向代理模块。开发
linux·开发语言·网络·c++·git
m0_748232392 小时前
在Linux centos7环境下部署wblogic使用weblogic部署war包项目
linux·运维·服务器
李先静3 小时前
用 gdbserver 调试 arm-linux 上的 AWTK 应用程序
linux·arm开发·awtk