安全高可用通信背后的 MySQL 优化实践
01 背景
互联网服务对高可用的要求非常高,无论是应用服务还是数据库,都要做到高可用。对于政府部门、集团企业等组织机构而言,系统高可用的重要性自然不言而喻。
以做到 99.9% 的稳定性为标准,意味着一年内累计有 8 个小时不能正常访问,而组织机构系统内包含许多模块,比如前端应用、缓存、数据库、搜索、消息队列等,每个模块都需要做到高可用,才能保证整个系统的运行稳定。
在整个组织机构中,通信系统使用频率最高、覆盖范围最广。通信系统又包含即时通讯与实时音视频两部分,即时通讯聊天过程中会产生大量文字、表情、图片、视频、文件等数据,实时音视频则会产生视频录制文件,部分信息存储在数据库中,所以,数据库是否高可用直接影响到通信系统的使用。
另一方面,一些组织机构对于信息安全非常重视,对不同人员设置不同查看权限,避免敏感信息被无关人员查看造成泄漏。接下来,我们从高可用和控制权限两方面来分析一下 MySQL 的优化实践。
02 高可用的优化
问题来源
1.因为单点故障导致数据库无法访问,从而影响整个服务,导致服务无响应。
2.虽然部署了数据库集群,但是发生故障后无法自动切换,导致故障时间延长。
优化思路
1.MySQL 采用了双主同步的部署方式,实现了数据高可用,单节点故障的情况下不会丢失用户的相关数据。
2.应用访问 MySQL 采用了本地 HA 代理方式,对于前端,因为是本地代理所以任何一台代理服务器(应用服务器)宕机均不会影响其它应用服务器的使用,对于后端,因为是 HA 代理模式,所以 MySQL 只要有一个节点存活,应用均可正常访问。
实施步骤
1.MySQL 配置双主模式
# Master 及 Slave 节点配置
[mysqld]
server-id=21 # 同一集群内不可出现相同的
id log_bin = /data/mysql/mysql-bin
# Master 节点创建主从复制用户
create user 'repl'@'%' identified with mysql_native_password by 'password'; grant replication slave on *.* to 'repl'@'%';
#查看 Master 节点 log_file 及 log_pos
show master status;
#Slave 节点配置 Master 节点信息
change master to master_host='mysql-master', master_port=4306, master_user='repli', master_password='123456', master_log_file='mysql-bin.000001', master_log_pos=123299 ;
# Slave 节点启用 slave
start slave;
2.应用服务器配置 Nginx HA 代理
upstream mysql{
server mysql-node-1:{{ mysql_port }} max_fails=10 fail_timeout=30s;
server mysql-node-2:{{ mysql_port }} backup;
}
server {
listen 5307;
proxy_pass mysql;
proxy_connect_timeout 5s;
proxy_timeout 120s;
access_log /data/logs/mysql-ha-access.log stream_main;
error_log /data/logs/mysql-ha-error.log;
}
3.MySQL 其中一台节点配置探测脚本,只有另一台节点宕机才允许应用访问
#!/bin/bash
export PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin'
mysql_status=`{{ mysql_app_path }}/bin/mysqladmin -u{{ database_user }} -p{{ database_password }} -hrce-mysql-node-1 -P{{ mysql_port }} PING 2>/dev/null`
Date=`date '+%Y-%m-%d %H:%M:%S'`
Date_m=`date '+%Y%m'`
if [ "$mysql_status" != "mysqld is alive" ]
then
iptables -D INPUT -s {{ host }} -j ACCEPT >/dev/null 2>&1
iptables -I INPUT -s {{ host }} -j ACCEPT
echo "$Date rce-mysql-node-1 is failed !!!" >> "{{ logs_path }}/scripts/set-mysql-iptables_$Date_m.log"
echo "$Date Accept service access rce-mysql-node-2" >> "{{ logs_path }}/scripts/set-mysql-iptables_$Date_m.log"
else
iptables -D INPUT -p tcp --dport 4306 -j DROP >/dev/null 2>&1
iptables -I INPUT -p tcp --dport 4306 -j DROP
iptables -D INPUT -s rce-mysql-node-1 -p tcp --dport 4306 -j ACCEPT >/dev/null 2>&1
iptables -I INPUT -s rce-mysql-node-1 -p tcp --dport 4306 -j ACCEPT
echo "$Date rce-mysql-node-1 is normal" >> "{{ logs_path }}/scripts/set-mysql-iptables_$Date_m.log"
echo "$Date Denial of service access rce-mysql-node-2" >> "{{ logs_path }}/scripts/set-mysql-iptables_$Date_m.log"
fi
03 控制权限的优化
问题来源1.MySQL 用户权限管理混乱,不同项目的用户均可访问所有资源,导致了信息泄露。2.MySQL 目录杂乱,难以快速检索,导致运维实施难度大。
优化思路1.MySQL 使用普通用户启动,且该用户无法登录,避免因系统权限漏洞导致的信息泄露。2.MySQL 用户均只针对该用户所需访问的库开放权限,避免了不同服务用户越权操作的隐患。3.MySQL 数据及应用目录,统一归档到一级目录,且仅授予 MySQL 启动用户权限,易于管理。
实施步骤1.MySQL 初始化及配置文件指定普通用户账户
[mysqld]
user = {{ mysql_user }}
2.MySQL 授权需指明需访问哪个应用的库
grant all on {{ database_name }}.* to {{ database_user }}@'%' identified by {{ database_password }};
3.MySQL 相关目录均在配置文件中指定至一级目录
[mysqld]
socket = /data/app/mysql-node-2/mysql.sock
datadir = /data/data/mysql-node-2
socket = /data/app/mysql-node-2/mysql.sock
pid-file = /data/app/mysql-node-2/mysqld.pid
tmpdir = /data/app/mysql-node-2/tmp
log-error = /data/logs/mysql-node-2/mysqld.err
slow_query_log_file = /data/logs/mysql-node-2/mysql-slow.log
log_bin = /data/logs/mysql-node-2/mysql-bin
log-bin-index = /data/logs/mysql-node-2/mysql-bin.index
relay-log = /data/logs/mysql-node-2/relay-bin
relay-log-index = /data/logs/mysql-node-2/relay-bin.index
lc_messages_dir = /data/app/mysql-node-2/share
pid-file = /data/app/mysql-node-2/mysqld.pid
组织机构可以先从 MySQL 优化来确保通信系统底层支持系统稳定,来提高整个通信系统的安全高可用。