1 postgresql架构与原理。
PostgreSQL
体系结构分两部分
- 实例
instance
- 进程
- 内存存储结构
- 磁盘存储
进程主要分为:主进程Postmaster
和一些辅助进程
- 主进程
Postmaster
:整个数据库实例的总控进程,负责启动和关闭数据库实例 - 辅助进程
Syslogger
(系统日志)进程:Postgres.conf
中logging_collection
设置为on
,此时主进程才会启动Syslogger
辅助进程。BgWriter
(后台)写进程:把共享内存中的脏页写到磁盘上的进程。主要是为了提高插入、更新和删除数据的性能WalWrite
(预写式日志)进程:在修改数据之前把修改操作记录到磁盘中,以便后面更新实时数据时就不需要数据持久化到文件中- PgArch(归档)进程:WAL日志会循环使用,PgArch在归档前会将WAL日志备份出来。通过PITY技术,对数据库进行全量备份后,将备份时间点之后的WAL日志通过归档进行备份,使用数据库的全量备份再加上后面产生的WAL日志,即可把数据库向前推到全量备份后的任一时间点
- AutoVacuum(自动清理)进程:对标进行DELETE操作后,旧的数据并不会立即删除,并且在更新数据时,也不会在旧的数据上做更新,而是新生成一行数据。旧的数据只是被标识为删除状态,只有在没有并发的其他事务读到这些数据时,才会被清除。这个清除工作就是AutoVacuum进程完成。
- PgStat(统计数据收集)进程:主要用于查询优化时的代价估算,包括一个表和索引进行了多少此的插入、更新、删除操作,磁盘块读写的次数、行的读次数。
pg_statistic
中存储了PgStat收集的数据 Checkpointer
检查点进程:检查点进程 (CKPT) 在特定时间自动执行一个检查点,通过向数据库写入进程 (BgWriter) 传递消
息来启动检查点请求。在检查点时,所有脏数据页都冲刷到磁盘并且向日志文件中写入一条特殊的检查点记录。startup
启动进程:用于数据库恢复的进程Session
会话进程:每一个用户发起连接后,一旦验证成功,postmaster进程就会fork—个新的子进程负责连接此
用户。
内存存储结构:包括共享内存和本地内存
- 共享内存:服务启动后,会生成一块共享内存,用于做数据块的缓冲区,以便提高读写性能。
WAL
日志缓冲区和commit log(Clog)
缓冲区也存在共享内存中,此外还有全局信息比如进程、锁、全局统计等也都保存在共享内存中。 - 本地内存:非全局存储的数据都存储在本地内存中,主要包括:
- 临时缓冲区:用于访问临时表的缓冲区。
tem_buffer
控制,默认是8M。 work_mem
:内部排序操作和Hash表在使用临时操作文件之前使用的存储缓冲区。manintance_work_mem
:用于一些维护操作
- 临时缓冲区:用于访问临时表的缓冲区。
2 基于流复制完成postgresql的高可用。
实验环境
- Master:10.0.0.6
- Standby:10.0.0.3
2.1 Master节点配置
#1 创建复制的用户并授权
postgres=# create role repluser with replication login password 'lgq123456';
CREATE ROLE
#2 修改pg_hba.conf进行授权
[21:27:17 root@ubuntu2004 ~]$ vi /pgsql/data/pg_hba.conf
local replication all trust
##在这一行下面添加下面一行的授权
host replication all 0.0.0.0/0 md5
#3 修改配置(可选)
[21:27:54 root@ubuntu2004 ~]$ vi /pgsql/data/postgresql.conf
synchronous_standby_names = '*' #开启此项,表示同步方式,需要同时打开synchronous_commit = on,此为默认值,默认是异步方式
synchronous_commit = on #开启同步模式
archive_mode = on #建议打开归档模式,防止长时间无法同步,WAL被覆盖造成数据丢失
archive_command = '[ ! -f /archive/%f ] && cp %p /archive/%f'
wa1_level = replica #设置wal的级别
max_wal_senders = 5 #这个设置可以最多有几个流复制连接,一般有几个从节点就设置几个
wal_keep_segments = 128 #设置流复制保留的最多的WAL文件数目
wal_sender_timeout = 60s #设置流复制主机发送数据的超时时间
max_connections = 200 # 一般查多于写的应用从库的最大连接数要比较大
hot_standby = on #对主库无影响,用于将来可能会成为从库,这台机器不仅仅是用于数据归档,也用于数据查询,在从库上配置此项后为只读
max_standby_streaming_delay = 30s #数据流备份的最大延迟时间
wal_receiver_status_interval = 10s #多久向主报告一次从的状态,当然从每次数据复制都会向主报告状态,只是设置最长的间隔时间
hot_standby_feedback = on #如果有错误的数据复制,是否向主进行反馈
wal_log_hints = on #对非关键更新进行整页写入
#重启服务
2.2 Standby节点配置
#清空数据和归档
[21:34:07 root@rocky ~]$ systemctl stop postgresql.service
[21:34:30 root@rocky ~]$ rm -rf /pgsql/data/*
[21:34:53 root@rocky ~]$ rm -rf /archive/*
[21:35:09 root@rocky ~]$ rm -rf /pgsql/backup/*
#备份主库数据到standby节点
[21:37:09 root@rocky ~]$ pg_basebackup -D /pgsql/backup/ -Ft -Pv -Upostgres -h 10.0.0.6 -p 5432 -R
#还原
[21:38:03 root@rocky ~]$ tar xf /pgsql/backup/base.tar -C /pgsql/data/
[21:38:45 root@rocky ~]$ tar xf /pgsql/backup/pg_wal.tar -C /archive/
#修改配置文件
[21:41:06 root@rocky ~]$ vi /pgsql/data/postgresql.conf
##修改下面两行的选项值
primary_conninfo = 'host=10.0.0.6 port=5432 user=repluser password=lgq123456'
restore_command = 'cp /archive/%f %p'
##下面配置是可选的
hot_standby = on #开启此项,此是默认项
recovery_target_timeline = latest # 默认
max_connections = 120 # 大于等于主节点,正式环境应当重新考虑此值的大小
max_standby_streaming_delay = 30s
wal_receiver_status_interval = 10
shot_standby_feedback = on
max_wal_senders = 15
1ogging_co1lector = on
1og_directory = 'pg_log'
1og_filename = 'postgresql-%Y-%m-%d_%H%M%S.1og'
#启动服务
[21:45:49 root@rocky ~]$ systemctl start postgresql.service
2.3 监控同步状态
2.3.1 在主库查看状态
[22:02:45 root@ubuntu2004 ~]$ pg_controldata
pg_control version number: 1300
Catalog version number: 202107181
Database system identifier: 7146423305602937695
Database cluster state: in production #主库状态
postgres=# select pid,state,client_addr,sync_priority,sync_state from pg_stat_replication;
pid | state | client_addr | sync_priority | sync_state
-------+-----------+-------------+---------------+------------
23455 | streaming | 10.0.0.3 | 0 | async
(1 row)
#下面只在主节点查看同步模式,注意:如果无从节点连接,将无任何显示信息
postgres=# \x
Expanded display is on.
postgres=# select pg_current_wal_insert_lsn(),* from pg_stat_replication;
-[ RECORD 1 ]-------------+------------------------------
pg_current_wal_insert_lsn | 0/21000EE8
pid | 23455
usesysid | 10
usename | postgres
application_name | walreceiver
client_addr | 10.0.0.3
client_hostname |
client_port | 55636
backend_start | 2022-10-18 22:01:05.190842+08
backend_xmin |
state | streaming
sent_lsn | 0/21000EE8
write_lsn | 0/21000EE8
flush_lsn | 0/21000EE8
replay_lsn | 0/21000EE8
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
reply_time | 2022-10-18 22:05:54.621397+08
##服务器查看数据库是否为备库,f表主库 t表示为备库
postgres=# select * from pg_is_in_recovery();
pg_is_in_recovery
-------------------
t
(1 row)
2.3.2 在从库查看状态
[22:12:28 root@rocky ~]# pg_controldata
pg_control version number: 1300
Catalog version number: 202107181
Database system identifier: 7146423305602937695
Database cluster state: in archive recovery #从库状态
postgres=# SELECT * FROM pg_stat_wal_receiver;
-[ RECORD 1 ]---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
pid | 5387
status | streaming
receive_start_lsn | 0/21000000
receive_start_tli | 1
written_lsn | 0/21000EE8
flushed_lsn | 0/21000EE8
received_tli | 1
last_msg_send_time | 2022-10-18 22:14:06.419656+08
last_msg_receipt_time | 2022-10-18 22:14:05.239946+08
latest_end_lsn | 0/21000EE8
latest_end_time | 2022-10-18 22:01:05.196065+08
slot_name |
sender_host | 10.0.0.6
sender_port | 5432
conninfo | user=postgres password=******** channel_binding=disable dbname=replication host=10.0.0.6 port=5432 fallback_application_name=walreceiver sslmode=disable sslcompression=0 sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres target_session_attrs=any
3 实现postgresql的时间点还原。
案例说明:每天2:00备份,第二天10:00误删除数据库,如何恢复?
3.1 备份
#1 在postgresql服务器上开启归档日志
[20:08:59 root@ubuntu2004 ~]$ vi /pgsql/data/postgresql.conf
archive_mode = on
archive_command = '[ ! -f /archive/%f ] && %p /archive/%f'
#2 创建测试数据
postgres=# create database testdb;
postgres=# \c testdb;
testdb=# create table t1(id int);
CREATE TABLE
testdb=# insert into t1 values(1);
INSERT 0 1
testdb=# select * from t1
testdb-# ;
id
----
1
(1 row)
#3 在备份服务器上进行完全备份
[20:14:30 root@rocky ~]$ pg_basebackup -D /pgsql/backup/ -Ft -Pv -Upostgres -h 10.0.0.6 -p 5432 -R
Password:
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/1D000028 on timeline 1
pg_basebackup: starting background WAL receiver
pg_basebackup: created temporary replication slot "pg_basebackup_20102"
152628/152628 kB (100%), 1/1 tablespace
pg_basebackup: write-ahead log end point: 0/1D000138
pg_basebackup: waiting for background process to finish streaming ...
pg_basebackup: syncing data to disk ...
pg_basebackup: renaming backup_manifest.tmp to backup_manifest
pg_basebackup: base backup completed
##至此已经完成了每天2:00进行备份的任务
#4 在postgresql服务器上继续生成测试数据
testdb=# insert into t1 values(2);
INSERT 0 1
testdb=# insert into t1 values(3);
INSERT 0 1
testdb=# select * from t1;
id
----
1
2
3
(3 rows)
#5 模拟10:00时间误删除了这个数据库
testdb=# \c hellodb
You are now connected to database "hellodb" as user "postgres".
hellodb=# drop database testdb;
DROP DATABASE
hellodb=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
hellodb | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
hellodb2 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
(5 rows)
#6发现故障,停止用户访问
#查看当前日志文件
hellodb=# select pg_walfile_name(pg_current_wal_lsn());
pg_walfile_name
--------------------------
00000001000000000000001E
(1 row)
#查看当前事务ID
hellodb=# select txid_current();
txid_current
--------------
904
(1 row)
3.2 故障还原
#1 在postgresql服务器上切换归档日志
hellodb=# select pg_switch_wal();
pg_switch_wal
---------------
0/1E000E18
(1 row)
#2 在备份服务器上停止服务,准备还原
[20:15:53 root@rocky ~]$ systemctl stop postgresql.service
[20:30:55 root@rocky ~]$ rm -rf /pgsql/data/*
#3 在备份服务器中进行还原
[20:31:03 root@rocky ~]$ tar xf /pgsql/backup/base.tar -C /pgsql/data/
##下面可以不执行,在4中直接将PG服务器/archive中的归档日志全部拷贝过去
[20:32:02 root@rocky ~]$ tar xf /pgsql/backup/pg_wal.tar -C /archive/
[20:32:42 root@rocky ~]$ ll /archive/
total 16384
-rw------- 1 postgres postgres 16777216 Oct 18 20:15 00000001000000000000001D
#4 复制PG服务器的归档日志到还原的测试服务器
[20:32:45 root@rocky ~]$ rsync -a 10.0.0.6:/archive/ /archive/
#5 查看故障点事务ID
##前面看到删除数据库是发生在00000001000000000000001E日志文件中
[20:38:55 root@rocky ~]$ pg_waldump /archive/00000001000000000000001E|grep "DROP dir"
rmgr: Database len (rec/tot): 38/ 38, tx: 903, lsn: 0/1E000CF8, prev 0/1E000C80, desc: DROP dir 1663/16603
##查看此指令的事务ID为903,所以需要恢复到此事务的前一个事务902
#6 修改配置文件
[20:39:20 root@rocky ~]$ vi /pgsql/data/postgresql.conf
##将下面两个参数修改为
restore_command = 'cp /archive/%f %p'
#指定还原至上面查到的事务ID
recovery_target_xid = '902'
##也可以通过下面方式进行指定还原的位置
recovery_target_name = 'restore_point' #指定还原点名称
recovery_target_time = '2021-01-17 16:26:12' #指定还原至时间点
recovery_target_lsn = '0/3E000148' #指定还原到LSN号的位置
#7 启动服务
[20:42:42 root@rocky ~]$ systemctl start postgresql.service
#8 验证数据
[20:45:24 root@rocky ~]$ psql
psql (14.2)
Type "help" for help.
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
hellodb | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
hellodb2 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
testdb | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
(6 rows)
postgres=# \c testdb
You are now connected to database "testdb" as user "postgres".
testdb=# \dt
List of relations
Schema | Name | Type | Owner
--------+------+-------+----------
public | t1 | table | postgres
(1 row)
testdb=# select * from t1;
id
----
1
2
3
(3 rows)
#9 当前无法写入,需要恢复到正常模式
testdb=# select pg_wal_replay_resume();
pg_wal_replay_resume
----------------------
(1 row)
[19:54:12 root@rocky ~]# pg_controldata
pg_control version number: 1300
Catalog version number: 202107181
Database system identifier: 7146423305602937695
Database cluster state: in production
##现在处于production状态,可以正常写入
testdb=# insert into t1 values(4);
INSERT 0 1
testdb=# select * from t1;
id
----
1
2
3
4
(4 rows)
4 规划高可用的LAMP,要求wordpress网站放在NFS共享存储上,并且用户可以正常发布博客,上传图片。尝试更新wordpress版本,测试网站仍可用。
4.1 在10.0.0.8上搭建DNS
#1 安装软件
[09:50:56 root@DNS-server ~]$ yum -y install bind bind-utils
[09:51:59 root@DNS-server ~]$ systemctl enable --now named.service
Created symlink /etc/systemd/system/multi-user.target.wants/named.service → /usr/lib/systemd/system/named.service.
#2 修改配置文件
[09:56:29 root@DNS-server ~]$ vi /etc/named.conf
options {
listen-on port 53 { localhost; }; #修改这一行为localhost,放置以后该主机ip地址换了,还需要在修改这个配置;或则直接讲这一行注释掉也行,他就会默认监听localhos
listen-on-v6 port 53 { ::1; };
directory "/var/named";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
secroots-file "/var/named/data/named.secroots";
recursing-file "/var/named/data/named.recursing";
allow-query { any; }; #修改这一行为any
#3 创建区域数据库配置文件
[09:57:18 root@DNS-server ~]$ cd /var/named/
[09:57:28 root@DNS-server named]$ touch yanlinux.org.zone
[09:57:46 root@DNS-server named]$ chmod 640 yanlinux.org.zone
[09:58:02 root@DNS-server named]$ chgrp named yanlinux.org.zone
[09:58:15 root@DNS-server named]$ ll yanlinux.org.zone
-rw-r----- 1 root named 0 Oct 24 09:57 yanlinux.org.zone
[09:58:19 root@DNS-server named]$ vi yanlinux.org.zone
$TTL 1D
@ IN SOA master admin.yanlinux.org (
0
3H
10M
1D
6H)
NS master
master A 10.0.0.8
www A 10.0.0.18
www A 10.0.0.28
@ A 10.0.0.18
@ A 10.0.0.28
[10:01:02 root@DNS-server named]$ vi /etc/named.rfc1912.zones
##最后面加上以下几行
zone "yanlinux.org" IN {
type master;
file "yanlinux.org.zone";
};
#4 检查配置文件是否错误
[10:05:56 root@DNS-server named]$ named-checkconf
[10:06:08 root@DNS-server named]$ named-checkzone yanlinux.org yanlinux.org.zone
zone yanlinux.org/IN: loaded serial 0
OK
#5 重载配置文件
[10:06:21 root@DNS-server named]$ rndc reload
server reload successful
[10:06:27 root@DNS-server named]$ dig yanlinux.org @127.0.0.1
; <<>> DiG 9.11.36-RedHat-9.11.36-3.el8_6.1 <<>> yanlinux.org @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3302
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 2
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 6666bc93f471482f0446feee6355f32b96cb93d04fc0af45 (good)
;; QUESTION SECTION:
;yanlinux.org. IN A
;; ANSWER SECTION:
yanlinux.org. 86400 IN A 10.0.0.18
yanlinux.org. 86400 IN A 10.0.0.28
;; AUTHORITY SECTION:
yanlinux.org. 86400 IN NS master.yanlinux.org.
;; ADDITIONAL SECTION:
master.yanlinux.org. 86400 IN A 10.0.0.8
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Oct 24 10:06:35 CST 2022
;; MSG SIZE rcvd: 138
4.2 搭建数据库服务
利用 Mycat 实现 MySQL 的读写分离
- MyCat:10.0.0.58
- master:10.0.0.68
- slave1:10.0.0.78
- slave2: 10.0.0.88
4.2.1 搭建主从节点
#1 在10.0.0.68上安装mysql-server服务端。作为mysql master节点
[10:26:12 root@Master-server ~]$ yum -y install mysql-server
[10:28:24 root@Master-server ~]$ systemctl enable --now mysqld
##1.1 进入mysql配置网站数据库以及账号授权
##安全设置,设置密码
[10:38:49 root@Master-server ~]$ mysql_secure_installation
[10:29:05 root@Master-server ~]$ mysql
mysql> create database wordpress;
mysql> create user wordpress@'10.0.0.%' identified by 'lgq123456';
mysql> grant all on wordpress.* to wordpress@'10.0.0.%'
##1.2 修改配置文件实现主节点
[14:26:49 root@Master-server ~]$ vi /etc/my.cnf
###在文件中添加以下几行
[mysqld]
server-id=68
log-bin=/data/mysql/mysql-bin
skip_name_resolve=1
general_log
##1.3 创建存放日志文件的目录,并重启服务
[14:33:12 root@Master-server ~]$ mkdir /data/mysql/
[14:36:57 root@Master-server ~]$ chown mysql.mysql /data/mysql/
[14:37:20 root@Master-server ~]$ systemctl restart mysqld.service
##1.4 创建复制账号以及授权
mysql> create user repluser@'10.0.0.%' identified by 'lgq123456';
mysql> grant replication slave on *.* to repluser@'10.0.0.%';
##1.5 备份数据库
[14:50:44 root@Master-server ~]$ mysqldump -uroot -p'lgq123456' -A -F --single-transaction --master-data > all.sql
##1.6 将备份数据拷贝至两个slave节点
[14:51:27 root@Master-server ~]$ scp all.sql 10.0.0.78:
[14:51:51 root@Master-server ~]$ scp all.sql 10.0.0.88:
#2 slave1节点实现
##2.1 修改配置文件
[14:52:13 root@mysql-slave1 ~]$ yum -y install mysql-server
[14:58:57 root@mysql-slave1 ~]$ vi /etc/my.cnf
###添加下面几行
[mysqld]
server-id=78
log-bin=/data/mysql/mysql-bin
read-only
relay_log_purge=0
skip_name_resolve=1
general_log
##2.2 创建日志存放目录
[15:02:49 root@mysql-slave1 ~]$ mkdir /data/mysql
[15:03:17 root@mysql-slave1 ~]$ chown mysql.mysql /data/mysql/ -R
##2.3 修改备份数据库,添加主节点信息
[15:04:08 root@mysql-slave1 ~]$ vi all.sql
###将备份数据库文件的25行修改为以下信息
25 CHANGE MASTER TO
26 MASTER_HOST='10.0.0.68',
27 MASTER_USER='repluser',
28 MASTER_PASSWORD='lgq123456',
29 MASTER_PORT=3306, 30 MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=156;
##2.4 启动服务,并还原数据库
[15:07:26 root@mysql-slave1 ~]$ systemctl enable --now mysqld
[15:10:01 root@mysql-slave1 ~]$ mysql
mysql> set sql_log_bin=0;
mysql> source /root/all.sql;
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| wordpress |
+--------------------+
5 rows in set (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 10.0.0.68
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 156
Relay_Log_File: mysql-slave1-relay-bin.000002
Relay_Log_Pos: 324
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 156
Relay_Log_Space: 540
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 68
Master_UUID: 9f781520-5343-11ed-a5ab-000c29784c7b
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set, 1 warning (0.00 sec)
mysql> set sql_log_bin=1;
#3 slave2节点实现
##3.1 拷贝slave1上已经添加了主节点信息的备份数据库文件
[15:16:12 root@mysql-slave2 ~]$ yum -y install mysql-server
[15:20:55 root@mysql-slave2 ~]$ scp 10.0.0.78:/root/all.sql ./
##3.2 修改配置文件
[15:23:37 root@mysql-slave2 ~]$ vi /etc/my.cnf
###添加以下几行
[mysqld]
server-id=88
log-bin=/data/mysql/mysql-bin
read-only
relay_log_purge=0
skip_name_resolve=1
general_log
##3.3 创建日志存放目录
[15:24:44 root@mysql-slave2 ~]$ mkdir /data/mysql
[15:25:39 root@mysql-slave2 ~]$ chown -R mysql.mysql /data/mysql/
##3.4 启动服务,还原数据,开启复制线程
[15:26:03 root@mysql-slave2 ~]$ systemctl enable --now mysqld
[15:27:04 root@mysql-slave2 ~]$ mysql
mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)
mysql> source /root/all.sql
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 10.0.0.68
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 156
Relay_Log_File: mysql-slave2-relay-bin.000002
Relay_Log_Pos: 324
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 156
Relay_Log_Space: 540
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 68
Master_UUID: 9f781520-5343-11ed-a5ab-000c29784c7b
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set, 1 warning (0.01 sec)
mysql> set sql_log_bin=1;
Query OK, 0 rows affected (0.00 sec)
4.2.2 在管理节点10.0.0.98上安装两个包mha4mysql-manager
和mha4mysql-node
#下载两个rpm文件
[15:31:24 root@MHA-manager ~]$ wget https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
[16:29:43 root@MHA-manager ~]$ wget https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58-0.el7.centos.noarch.rpm
#下载安装依赖
##下面就是安装mha4mysql_manager所需的所有依赖
[23:41:15 root@MHA-manager ~/dependece]$ ll
total 2348
-rw-r--r-- 1 root root 42804 Jul 2 2019 perl-B-Hooks-EndOfScope-0.21-6.el8.noarch.rpm
-rw-r--r-- 1 root root 17292 Jul 2 2019 perl-Class-Data-Inheritable-0.08-27.el8.noarch.rpm
-rw-r--r-- 1 root root 49884 Jul 2 2019 perl-Class-Method-Modifiers-2.12-8.el8.noarch.rpm
-rw-r--r-- 1 root root 26924 Jul 2 2019 perl-Devel-CallChecker-0.008-3.el8.x86_64.rpm
-rw-r--r-- 1 root root 23460 Jul 2 2019 perl-Devel-Caller-2.06-15.el8.x86_64.rpm
-rw-r--r-- 1 root root 12952 Nov 27 2020 perl-Devel-GlobalDestruction-0.14-1.of.el8.noarch.rpm
-rw-r--r-- 1 root root 20328 Jul 2 2019 perl-Devel-LexAlias-0.05-16.el8.x86_64.rpm
-rw-r--r-- 1 root root 36188 Jul 2 2019 perl-Devel-StackTrace-2.03-2.el8.noarch.rpm
-rw-r--r-- 1 root root 24508 Jun 29 2021 perl-Dist-CheckConflicts-0.11-1.of.el8.noarch.rpm
-rw-r--r-- 1 root root 21920 Jul 2 2019 perl-DynaLoader-Functions-0.003-2.el8.noarch.rpm
-rw-r--r-- 1 root root 28324 Jul 2 2019 perl-Eval-Closure-0.14-5.el8.noarch.rpm
-rw-r--r-- 1 root root 51000 Jul 2 2019 perl-Exception-Class-1.44-2.el8.noarch.rpm
-rw-r--r-- 1 root root 54192 Jul 2 2019 perl-Exporter-Tiny-1.000000-4.el8.noarch.rpm
-rw-r--r-- 1 root root 20436 Jul 2 2019 perl-Import-Into-1.002005-7.el8.noarch.rpm
-rw-r--r-- 1 root root 76008 Jul 2 2019 perl-List-MoreUtils-0.428-2.el8.noarch.rpm
-rw-r--r-- 1 root root 62340 Jul 2 2019 perl-List-MoreUtils-XS-0.428-3.el8.x86_64.rpm
-rw-r--r-- 1 root root 93188 Sep 11 2019 perl-Log-Dispatch-2.68-1.el8.noarch.rpm
-rw-r--r-- 1 root root 58288 Jul 2 2019 perl-Mail-Sender-0.903-7.el8.noarch.rpm
-rw-r--r-- 1 root root 40484 Sep 6 2019 perl-Mail-Sendmail-0.80-4.el8.noarch.rpm
-rw-r--r-- 1 root root 115344 Jul 2 2019 perl-MailTools-2.20-2.el8.noarch.rpm
-rw-r--r-- 1 root root 102236 Sep 11 2019 perl-MIME-Lite-3.030-16.el8.noarch.rpm
-rw-r--r-- 1 root root 78932 Jul 2 2019 perl-MIME-Types-2.17-3.el8.noarch.rpm
-rw-r--r-- 1 root root 24276 Jul 2 2019 perl-Module-Implementation-0.09-15.el8.noarch.rpm
-rw-r--r-- 1 root root 24440 Nov 11 2020 perl-Module-Runtime-0.016-1.of.el8.noarch.rpm
-rw-r--r-- 1 root root 72012 Oct 17 2019 perl-Moo-2.003004-7.el8.noarch.rpm
-rw-r--r-- 1 root root 32740 Jul 2 2019 perl-namespace-autoclean-0.28-10.el8.noarch.rpm
-rw-r--r-- 1 root root 38280 Jul 2 2019 perl-namespace-clean-0.27-7.el8.noarch.rpm
-rw-r--r-- 1 root root 42588 Jul 2 2019 perl-Package-Stash-0.37-9.el8.noarch.rpm
-rw-r--r-- 1 root root 39028 Jul 2 2019 perl-Package-Stash-XS-0.28-17.el8.x86_64.rpm
-rw-r--r-- 1 root root 31848 Jul 2 2019 perl-PadWalker-2.3-2.el8.x86_64.rpm
-rw-r--r-- 1 root root 39892 Nov 15 2019 perl-Parallel-ForkManager-2.02-5.el8.noarch.rpm
-rw-r--r-- 1 root root 36460 Jul 2 2019 perl-Params-Classify-0.015-2.el8.x86_64.rpm
-rw-r--r-- 1 root root 39232 Jul 2 2019 perl-Params-ValidationCompiler-0.27-1.el8.noarch.rpm
-rw-r--r-- 1 root root 27024 Jul 2 2019 perl-Ref-Util-0.203-4.el8.noarch.rpm
-rw-r--r-- 1 root root 26416 Jul 2 2019 perl-Ref-Util-XS-0.117-2.el8.x86_64.rpm
-rw-r--r-- 1 root root 30304 Jul 2 2019 perl-Role-Tiny-2.000006-2.el8.noarch.rpm
-rw-r--r-- 1 root root 163392 Jul 2 2019 perl-Specio-0.42-2.el8.noarch.rpm
-rw-r--r-- 1 root root 25212 Jul 2 2019 perl-Sub-Exporter-Progressive-0.001013-5.el8.noarch.rpm
-rw-r--r-- 1 root root 29488 Jul 2 2019 perl-Sub-Identify-0.14-6.el8.x86_64.rpm
-rw-r--r-- 1 root root 51020 Jul 2 2019 perl-Sys-Syslog-0.35-397.el8.x86_64.rpm
-rw-r--r-- 1 root root 438388 Jul 2 2019 perltidy-20180220-1.el8.noarch.rpm
-rw-r--r-- 1 root root 60424 Jul 2 2019 perl-Variable-Magic-0.62-3.el8.x86_64.rpm
[23:42:27 root@MHA-manager ~/dependece]$ yum -y install *.rpm
#安装mha4mysql-node和mha4mysql-manager
[23:44:32 root@MHA-manager ~]$ yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
4.2.3 在所有mysql节点服务器上安装mha4mysql-node
[17:12:04 root@Master-server ~]$ yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm
[17:12:45 root@mysql-slave1 ~]$ yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm
[17:12:52 root@mysql-slave2 ~]$ yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm
4.2.4 在所有节点实现相互之间ssh key验证
[23:46:40 root@MHA-manager ~]$ ssh-keygen
[23:46:57 root@MHA-manager ~]$ ssh-copy-id 127.0.0.1
[23:51:28 root@MHA-manager ~]$ rsync -av .ssh/ 10.0.0.68:/root/
[23:52:38 root@MHA-manager ~]$ rsync -av .ssh/ 10.0.0.78:/root/
[23:52:47 root@MHA-manager ~]$ rsync -av .ssh/ 10.0.0.88:/root/
4.2.5 在master上创建mha可以远程连接MYSQL所有节点的用户,授予其管理的权限
[23:55:08 root@Master-server ~]$ mysql -uroot -p
mysql> create user mhauser@'10.0.0.%' identified by 'lgq123456';
Query OK, 0 rows affected (0.01 sec)
mysql> grant all on *.* to mhauser@'10.0.0.%';
Query OK, 0 rows affected (0.01 sec)
4.2.6 在管理节点建立配置文件
注意: 此文件的行尾不要加空格等符号
#创建配置文件
[09:45:18 root@MHA-manager ~]$ mkdir /etc/mastermha/
[10:03:14 root@MHA-manager ~]$ vi /etc/mastermha/app1.cnf
[server default]
user=mhauser
password=lgq123456
manager_workdir=/data/mastermha/app1/
manager_log=/data/mastermha/app1/manager.log
remote_workdir=/data/mastermha/app1/
ssh_user=root
repl_user=repluser
repl_password=lgq123456
ping_interval=1
master_ip_failover_script=/usr/local/bin/master_ip_failover
report_script=/usr/local/bin/sendmail.sh
check_repl_delay=0
master_binlog_dir=/data/mysql/
[server1]
hostname=10.0.0.68
candidate_master=1
[server2]
hostname=10.0.0.78
candidate_master=1
[server3]
hostname=10.0.0.88
#创建VIP切换脚本,并放在/usr/local/bin目录下
[10:07:51 root@MHA-manager ~]$ vi /usr/local/bin/master_ip_failover
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
use MHA::DBHelper;
my (
$command, $ssh_user, $orig_master_host,
$orig_master_ip, $orig_master_port, $new_master_host,
$new_master_ip, $new_master_port, $new_master_user,
$new_master_password
);
# The vip IP address needs to be modified according to its own situation
my $vip = '10.0.0.100/24';#这个地址根据环境网段设置 一个没有使用的IP,带表漂移IP,目前漂移在master节点上,等master节点宕机时,会漂移到设置的新的master节点上
my $key = "1"; #指定VIP所在网卡的别名
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip"; #临时加漂移VIP时的命令
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";
GetOptions(
'command=s' => \$command,
'ssh_user=s' => \$ssh_user,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
'new_master_user=s' => \$new_master_user,
'new_master_password=s' => \$new_master_password,
);
exit &main();
sub main {
if ( $command eq "stop" || $command eq "stopssh" ) {
# $orig_master_host, $orig_master_ip, $orig_master_port are passed.
# If you manage master ip address at global catalog database,
# invalidate orig_master_ip here.
my $exit_code = 1;
eval {
# updating global catalog, etc
$exit_code = 0;
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
if ($@) {
warn $@;
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK \n";
`ssh $ssh_user\@$orig_master_host \" $ssh_start_vip \"`;
exit 0;
}
else {
&usage();
exit 1;
}
}
sub start_vip() {
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
# A simple system call that disable the VIP on the old_master
sub stop_vip() {
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}
#设置报警脚本
[10:11:18 root@MHA-manager ~]$ vi /usr/local/bin/sendmail.sh
#!/bin/bash
echo "MHA is failover!" | mail -s "MHA Warning" lgq6579@163.com
#给两个脚本添加执行权限
[10:14:13 root@MHA-manager ~]$ chmod +x /usr/local/bin/master_ip_failover
[10:14:35 root@MHA-manager ~]$ chmod +x /usr/local/bin/sendmail.sh
#检查基于key验证环境
[10:15:45 root@MHA-manager ~]$ masterha_check_ssh --conf=/etc/mastermha/app1.cnf
[info] All SSH connection tests passed successfully.
#检查复制环境
[10:16:22 root@MHA-manager ~]$ masterha_check_repl --conf=/etc/mastermha/app1.cnf
Tue Oct 25 10:18:01 2022 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Tue Oct 25 10:18:01 2022 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Tue Oct 25 10:18:01 2022 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
Tue Oct 25 10:18:01 2022 - [info] MHA::MasterMonitor version 0.58.
Creating directory /data/mastermha/app1/.. done.
Tue Oct 25 10:18:02 2022 - [error][/usr/share/perl5/vendor_perl/MHA/MasterMonitor.pm, ln427] Error happened on checking configurations. Redundant argument in sprintf at /usr/share/perl5/vendor_perl/MHA/NodeUtil.pm line 201.
Tue Oct 25 10:18:02 2022 - [error][/usr/share/perl5/vendor_perl/MHA/MasterMonitor.pm, ln525] Error happened on monitoring servers.
Tue Oct 25 10:18:02 2022 - [info] Got exit code 1 (Not master dead).
MySQL Replication Health is NOT OK! #发现报错
##网上查找信息作出如下修改:
[10:39:59 root@MHA-manager ~]$ vi /usr/share/perl5/vendor_perl/MHA/NodeUtil.pm
###将该文件的这几行
sub parse_mysql_major_version($) {
my $str = shift;
my $result = sprintf( '%03d%03d', $str =~ m/(\d+)/g ); return $result;
}
###修改为下面信息
sub parse_mysql_major_version($) {
my $str = shift;
$str =~ /(\d+)\.(\d+)/;
my $strmajor = "$1.$2";
my $result = sprintf( '%03d%03d', $strmajor =~ m/(\d+)/g ); return $result;
}
#再次检查复制环境
[10:40:36 root@MHA-manager ~]$ masterha_check_repl --conf=/etc/mastermha/app1.cnf
...
MySQL Replication Health is OK.
#后台启动MHA服务
[10:41:43 root@MHA-manager ~]$ nohup masterha_manager --conf=/etc/mastermha/app1.cnf --remove_dead_master_conf --ignore_last_fail
#查看状态
[10:51:48 root@MHA-manager ~]$ masterha_check_status --conf=/etc/mastermha/app1.cnf
app1 (pid:2047) is running(0:PING_OK), master:10.0.0.68
4.3 在web服务器上安装配置web服务
#1 在web1 10.0.0.18上安装wordpress服务
[10:40:57 root@web-server1 ~]$ cat install_wordpress.sh
#!/bin/bash
#
#***********************************************************
#Author: yanli
#Date: 2022-10-22
#FileName: install_wordpress.sh
#Description:
#***********************************************************
. /etc/os-release
color(){
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \E[0m"
echo -n "$1" && $MOVE_TO_COL
echo -n "["
if [ $2 = "success" -o $2 = "0" ] ;then
${SETCOLOR_SUCCESS}
echo -n $" OK "
elif [ $2 = "failure" -o $2 = "1" ] ;then
${SETCOLOR_FAILURE}
echo -n $"FAILED"
else
${SETCOLOR_WARNING}
echo -n $"WARNING"
fi
${SETCOLOR_NORMAL}
echo -n "]"
echo
}
install_wordpress(){
#下载wordpress并解压
wget https://cn.wordpress.org/latest-zh_CN.zip
unzip latest-zh_CN.zip -d /opt
}
install_Dependent_components(){
if [ $ID = 'centos' -o $ID = 'rocky' ];then
yum -y install httpd php php-mysqlnd php-json && systemctl enable --now httpd
elif [ $ID = 'Ubuntu' ];then
color "不支持Ubuntu操作系统,退出!" 1
exit
else
color "不支持此操作系统,退出!" 1
exit
fi
}
move_wordpress(){
cd /opt/wordpress
mv * /var/www/html
chown -R apache. /var/www/html/ && color "wordpress配置完成!" 0 || color "wordpress配置失败!" 1
}
install_wordpress
install_Dependent_components
move_wordpress
##1.1 安装
[10:48:12 root@web-server1 ~]$ sh install_wordpress.sh
###其余剩下步骤在浏览器中配置网站
至此web WordPress已经搭建好,发布一篇测试博客。
##1.2 安装nfs-utils搭建挂载NFS,实现网站数据远程备份
[11:19:24 root@web-server1 ~]$ yum -y install nfs-utils
[11:21:43 root@web-server1 ~]$ showmount -e 10.0.0.38
Export list for 10.0.0.38:
/data/www *
##1.3 将网站图片拷贝至NFS服务器
[11:37:54 root@web-server1 ~]$ scp -r /var/www/html/wp-content/uploads/* 10.0.0.38:/data/www/
##1.4 实现永久挂载
[11:39:20 root@web-server1 ~]$ vi /etc/fstab
###在文件最后添加挂载信息
10.0.0.38:/data/www /var/www/html/wp-content/uploads nfs _netdev 0 0
[11:44:50 root@web-server1 ~]$ mount -a
[11:44:57 root@web-server1 ~]$ df -h|grep data
10.0.0.38:/data/www 70G 2.3G 68G 4% /var/www/html/wp-content/uploads
#2 在10.0.0.28上安装web2
[12:19:34 root@web-server2 ~]$ yum -y install httpd php php-mysqlnd php-json && systemctl enable --now httpd
##2.1 将10.0.0.18上的wordpress信息拷贝至/var/www/html
[12:27:00 root@web-server2 ~]$ rsync -a 10.0.0.18:/var/www/html/* /var/www/html/
[12:29:07 root@web-server2 ~]$ chown -R apache. /var/www/html/
##2.2 安装nfs-utils
[12:29:39 root@web-server2 ~]$ yum -y install nfs-utils
[12:31:50 root@web-server2 ~]$ systemctl enable --now nfs-server.service
##2.3 永久挂载NFS
[12:33:14 root@web-server2 ~]$ vi /etc/fstab
10.0.0.38:/data/www /var/www/html/wp-content/uploads nfs _netdev 0 0
[12:34:21 root@web-server2 ~]$ mount -a
[12:34:34 root@web-server2 ~]$ df -h |grep data
10.0.0.38:/data/www 70G 2.3G 68G 4% /var/www/html/wp-content/uploads
4.4 搭建NFS服务器
#1 首先在10.0.0.38NFS主服务器上安装配置NFS服务
[11:12:55 root@NFS-server ~]$ yum -y install nfs-utils
[11:13:22 root@NFS-server ~]$ systemctl enable --now nfs-server.service
##1.1 创建用于传输的账户
[11:15:10 root@NFS-server ~]$ useradd -u 666 www
##1.2 修改共享配置文件
[11:16:33 root@NFS-server ~]$ vi /etc/exports
/data/www *(rw,all_squash,anonuid=666,anongid=666)
##1.3 创建NFS共享文件夹
[11:18:07 root@NFS-server ~]$ mkdir /data/www/
[11:18:30 root@NFS-server ~]$ chown -R www. /data/www/
##1.4 下载sersync,实现数据实时备份同步到NFS备份服务器
###1.4.1 下载sersync,解压,设置PATH变量
[12:40:37 root@NFS-server ~]$ wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/sersync/sersync2.5.4_64bit_binary_stable_final.tar.gz
[12:49:20 root@NFS-server ~]$ tar xf sersync2.5.4_64bit_binary_stable_final.tar.gz
[12:50:14 root@NFS-server ~]$ cp -a GNU-Linux-x86 /usr/local/sersync
[12:50:40 root@NFS-server ~]$ echo "PATH=/usr/local/sersync:$PATH" > /etc/profile.d/sersync.sh
[12:51:42 root@NFS-server ~]$ source /etc/profile.d/sersync.sh
###1.4.2 备份sersync配置文件,修改配置文件
[12:57:53 root@NFS-server ~]$ vi /usr/local/sersync/confxml.xml
1 <?xml version="1.0" encoding="ISO-8859-1"?>
2 <head version="2.5">
3 <host hostip="localhost" port="8008"></host>
4 <debug start="false"/>
5 <fileSystem xfs="false"/>
6 <filter start="false">
7 <exclude expression="(.*)\.svn"></exclude>
8 <exclude expression="(.*)\.gz"></exclude>
9 <exclude expression="^info/*"></exclude>
10 <exclude expression="^static/*"></exclude>
11 </filter>
12 <inotify>
13 <delete start="true"/>
14 <createFolder start="true"/>
15 <createFile start="false"/>
16 <closeWrite start="true"/>
17 <moveFrom start="true"/>
18 <moveTo start="true"/>
19 <attrib start="true"/> ##修改此行为true,文件属性变化后也会同步
20 <modify start="false"/>
21 </inotify>
22
23 <sersync>
24 <localpath watch="/data/www"> ##修改此行,需要同步的源目录
25 <remote ip="10.0.0.48" name="backup"/> #修改此行,指定备份服务器地址和rsync daemon的模块名,开启了ssh start,此时name为远程的shell方式运行时的目标目录
26 <!--<remote ip="192.168.8.39" name="tongbu"/>-->
27 <!--<remote ip="192.168.8.40" name="tongbu"/>-->
28 </localpath>
29 <rsync>
30 <commonParams params="-artuz"/>
31 <auth start="true" users="rsyncuser" passwordfile="/etc/rsync.pas"/> #修改此行为true,指定备份服务器的rsync配置的用户和密码
###1.4.3 以后台方式执行同步
[13:08:24 root@NFS-server ~]$ sersync2 -dro /usr/local/sersync/confxml.xml
###1.4.4 生成验证文件
[13:08:47 root@NFS-server ~]$ echo lgq123456 > /etc/rsync.pas
[13:13:35 root@NFS-server ~]$ chmod 600 /etc/rsync.pas
#2 在10.0.0.48 NFS备份服务器以独立服务方式运行rsync并实现验证功能
[13:21:00 root@NFS-backup ~]$ yum -y install rsync-daemon
##2.1 创建备份目录
[13:27:34 root@NFS-backup ~]$ mkdir -pv /data/backup
##2.2 修改配置文件
[13:27:58 root@NFS-backup ~]$ vi /etc/rsyncd.conf
uid = www
gid = www
max connections = 0
ignore errors
exclude = lost+found/
log file = /var/log/rsyncd.log
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsyncd.lock
reverse lookup = no
[backup]
path = /data/backup/
comment = backup dir
read only = no
auth users = rsyncuser
secrets file = /etc/rsync.pas
##2.3 创建验证文件
[13:31:23 root@NFS-backup ~]$ echo "rsyncuser:lgq123456" > /etc/rsync.pas
[13:32:05 root@NFS-backup ~]$ chmod 600 /etc/rsync.pas
##2.4
[13:39:13 root@NFS-backup ~]$ useradd -u 666 www
[13:39:51 root@NFS-backup ~]$ chown www.www /data/backup/ -R
[13:39:56 root@NFS-backup ~]$ rsync --daemon
4.5 测试结果
#NFS解析结果
[10:45:58 root@DNS-server scripts]$ dig yanlinux.org @127.0.0.1
; <<>> DiG 9.11.36-RedHat-9.11.36-3.el8_6.1 <<>> yanlinux.org @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23840
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 2
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 961eff915c3fed2265b4254f63562cafa1b883d88f4ee353 (good)
;; QUESTION SECTION:
;yanlinux.org. IN A
;; ANSWER SECTION:
yanlinux.org. 86400 IN A 10.0.0.18
yanlinux.org. 86400 IN A 10.0.0.28
;; AUTHORITY SECTION:
yanlinux.org. 86400 IN NS master.yanlinux.org.
;; ADDITIONAL SECTION:
master.yanlinux.org. 86400 IN A 10.0.0.8
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Oct 24 14:11:59 CST 2022
;; MSG SIZE rcvd: 138
#2 wordpress网站发布博客测试,上传的数据都备份到了NFS服务器
[14:09:10 root@NFS-server ~]$ ls /data/www/2022/10/
2.jpg view.png
[14:09:30 root@NFS-backup ~]$ ls /data/backup/2022/10/
2.jpg view.png
5 redis数据类型有哪些?
Redis支持五种数据类型:string
(字符串),list
(列表),set
(集合)及zset
(sorted set
:有序集合),hash
(哈希)。
字符串
string
是 redis 最基本的类型。Redis 中所有 key 都是字符串类型的。此数据类型最为常用列表
Redis 列表是简单的字符串列表,按照插入顺序排序。支持双向读写,你可以添加一个元素到列表的头部(左边)或者尾部(右边)。常用于存入日志等场景,此数据类型比较常用
集合
Set 是一个无序的字符串合集,同一个集合中的每个元素是唯一无重复的,支持在两个不同的集合中对数据进行逻辑处理,常用于取交集,并集,统计等场景,例如: 实现共同的朋友
有序集合
Redis有序集合和Redis集合类似,是不包含相同字符串的合集。它们的差别是,每个有序集合的成员都关联着一个双精度浮点型的评分,这个评分用于把有序集合中的成员按最低分到最高分排序。有序集合的成员不能重复,但评分可以重复,一个有序集合中最多的成员数为 2^32 - 1=4294967295个,经常用于排行榜的场景
哈希
hash
即字典, 用于保存字符串字段field和字符串值value之间的映射,即key/value
做为数据部分,hash特别适合用于存储对象场景.
一个hash最多可以包含2^32-1
个key/value
键值对
6 redis RDB和AOF比较?
- Redis 默认开启
RDB
持久化方式,在指定的时间间隔内,执行指定次数的写操作,则将内存中的数据写入到磁盘中,不能实时保存数据,可能会丢失自上一次执行RDB备份到当前的内存数据。而AOF
则需要手动开启,默认是每秒将写操作日志追加到AOF文件中,就算发生故障,也最多丢失一秒钟数据。 RDB
持久化适合大规模的数据恢复但它的数据一致性和完整性较差。AOF 的数据完整性比RDB高,但记录内容多了,会影响数据恢复的效率。Redis 针对 AOF文件大的问题,提供重写的瘦身机制。RDB
可以理解为是一种全量数据更新机制,AOF
可以理解为是一种增量的更新机制,AOF重写
可以理解为是一种全量+增量的更新机制(第一次是全量,后面都是增量)RDB
适合服务器数据库数据量小,写命令频繁的场景。AOF
适合数据量大,写命令少的场景。AOF重写
适合在AOF运行了很久的写命令之后执行- RDB在大数据集时恢复的速度比AOF方式要快
AOF
文件有序地保存对数据库执行的所有写入操作,可通过该文件对数据重建
7 redis配置文件详解。
[09:53:25 root@rocky8 ~]$ grep -vE '^#|^$' /etc/redis.conf
bind 127.0.0.1 #指定监听地址,支持用空格隔开的多个监听IP
protected-mode yes #redis3.2之后加入的新特性,在没有设置bind IP和密码的时候,redis只允许访问127.0.0.1:6379,可以远程连接,但当访问将提示警告信息并拒绝远程访问
port 6379 #监听端口,可根据需求自己设置
tcp-backlog 511 #三次握手的时候server端收到client ack确认号之后的队列值,即全连接队列长度
timeout 0 #客户端和Redis服务端的连接超时时间,默认是0,表示永不超时
tcp-keepalive 300 #tcp 会话保持时间300s
daemonize no #默认no,即直接运行redis-server程序时,不作为守护进程运行,而是以前台方式运行,如果想在后台运行需改成yes,当redis作为守护进程运行的时候,它会写一个 pid 到/var/run/redis.pid 文件
supervised no #和OS相关参数,可设置通过upstart和systemd管理Redis守护进程,centos7后都使用systemd
pidfile /var/run/redis_6379.pid #pid文件路径,可以修改为/apps/redis/run/redis_6379.pid
loglevel notice #日志级别
logfile /var/log/redis/redis.log #日志路径,示例:logfile "/apps/redis/log/redis_6379.log"
databases 16 #设置数据库数量,默认:0-15,共16个库
always-show-logo yes #在启动redis时是否显示或在日志中记录记录redis的logo
save 900 1 #在900秒内有1个key内容发生更改,就执行快照机制
save 300 10 #在300秒内有10个key内容发生更改,就执行快照机制
save 60 10000 #60秒内如果有10000个key以上的变化,就自动快照备份
stop-writes-on-bgsave-error yes #默认为yes时,可能会因空间满等原因快照无法保存出错时,会禁止redis写入操作,生产建议为no #此项只针对配置文件中的自动save有效
rdbcompression yes #持久化到RDB文件时,是否压缩,"yes"为压缩,"no"则反之
rdbchecksum yes #是否对备份文件开启RC64校验,默认是开启
dbfilename dump.rdb #快照文件名
dir ./ #快照文件保存路径,示例:dir "/apps/redis/data"
#主从复制相关
# replicaof <masterip> <masterport> #指定复制的master主机地址和端口,5.0版之前的指令为slaveof
# masterauth <master-password> #指定复制的master主机的密码
replica-serve-stale-data yes #当从库同主库失去连接或者复制正在进行,从机库有两种运行方式:
#1、设置为yes(默认设置),从库会继续响应客户端的读请求,此为建议值
#2、设置为no,除去特定命令外的任何请求都会返回一个错误"SYNC with master in progress"。
replica-read-only yes #是否设置从库只读,建议值为yes,否则主库同步从库时可能会覆盖数据,造成数据丢失
repl-diskless-sync no #是否使用socket方式复制数据(无盘同步),新slave第一次连接master时需要做数据的全量同步,redis server就要从内存dump出新的RDB文件,然后从master传到slave,有两种方式把RDB文件传输给客户端:
#1、基于硬盘(disk-backed):为no时,master创建一个新进程dump生成RDB磁盘文件,RDB完成之后由父进程(即主进程)将RDB文件发送给slaves,此为默认值
#2、基于socket(diskless):master创建一个新进程直接dump RDB至slave的网络socket,不经过主进程和硬盘
#推荐使用基于硬盘(为no),是因为RDB文件创建后,可以同时传输给更多的slave,但是基于socket(为yes), 新slave连接到master之后得逐个同步数据。只有当磁盘I/O较慢且网络较快时,可用diskless(yes),否则一般建议使用磁盘(no)
repl-diskless-sync-delay 5 #diskless时复制的服务器等待的延迟时间,设置0为关闭,在延迟时间内到达的客户端,会一起通过diskless方式同步数据,但是一旦复制开始,master节点不会再接收新slave的复制请求,直到下一次同步开始才再接收新请求。即无法为延迟时间后到达的新副本提供服务,新副本将排队等待下一次RDB传输,因此服务器会等待一段时间才能让更多副本到达。推荐值:30-60
repl-ping-replica-period 10 #slave根据master指定的时间进行周期性的PING master,用于监测master状态,默认10s
repl-timeout 60 #复制连接的超时时间,需要大于repl-ping-slave-period,否则会经常报超时
repl-disable-tcp-nodelay no #是否在slave套接字发送SYNC之后禁用 TCP_NODELAY,如果选择"yes",Redis将合并多个报文为一个大的报文,从而使用更少数量的包向slaves发送数据,但是将使数据传输到slave上有延迟,Linux内核的默认配置会达到40毫秒,如果 "no" ,数据传输到slave的延迟将会减少,但要使用更多的带宽
repl-backlog-size 512mb #复制缓冲区内存大小,当slave断开连接一段时间后,该缓冲区会累积复制副本数据,因此当slave 重新连接时,通常不需要完全重新同步,只需传递在副本中的断开连接后没有同步的部分数据即可。只有在至少有一个slave连接之后才分配此内存空间,建议建立主从时此值要调大一些或在低峰期配置,否则会导致同步到slave失败
repl-backlog-ttl 3600 #多长时间内master没有slave连接,就清空backlog缓冲区
replica-priority 100 #当master不可用,哨兵Sentinel会根据slave的优先级选举一个master,此值最低的slave会优先当选master,而配置成0,永远不会被选举,一般多个slave都设为一样的值,让其自动选择
#min-replicas-to-write 3 #至少有3个可连接的slave,mater才接受写操作
#min-replicas-max-lag 10 #和上面至少3个slave的ping延迟不能超过10秒,否则master也将停止写操作
requirepass foobared #设置redis连接密码,之后需要AUTH pass,如果有特殊符号,用" "引起来,生产建议设置
rename-command #重命名一些高危命令,示例:rename-command FLUSHALL "" 禁用命令
#示例: rename-command del magedu
maxclients 10000 #Redis最大连接客户端
maxmemory <bytes> #redis使用的最大内存,单位为bytes字节,0为不限制,建议设为物理内存一半,8G内存的计算方式8(G)*1024(MB)1024(KB)*1024(Kbyte),需要注意的是缓冲区是不计算在maxmemory内,生产中如果不设置此项,可能会导致OOM
#maxmemory-policy noeviction 此为默认值
# MAXMEMORY POLICY:当达到最大内存时,Redis 将如何选择要删除的内容。您可以从以下行为中选择一种:
#
# volatile-lru -> Evict 使用近似 LRU,只有设置了过期时间的键。在具有过期集的键中使用近似 LRU 驱逐。
# allkeys-lru -> 使用近似 LRU 驱逐任何键。
# volatile-lfu -> 使用近似 LFU 驱逐,只有设置了过期时间的键。
# allkeys-lfu -> 使用近似 LFU 驱逐任何键。
# volatile-random -> 删除设置了过期时间的随机密钥。
# allkeys-random -> 删除一个随机密钥,任何密钥。
# volatile-ttl -> 删除过期时间最近的key(次TTL)
# noeviction -> 不要驱逐任何东西,只是在写操作时返回一个错误。
#
# LRU 表示最近最少使用
# LFU 表示最不常用
#
# LRU、LFU 和 volatile-ttl 都是使用近似随机算法实现的。
#
# 注意:使用上述任何一种策略,当没有合适的键用于驱逐时,Redis 将在需要更多内存的写操作时返回错误。这些通常是创建新密钥、添加数据或修改现有密钥的命令。一些示例是:SET、INCR、HSET、LPUSH、SUNIONSTORE、SORT(由于 STORE 参数)和 EXEC(如果事务包括任何需要内存的命令)。
appendonly no #是否开启AOF日志记录,默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了,但是redis如果中途宕机,会导致可能有几分钟的数据丢失(取决于dump数据的间隔时间),根save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性,Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。默认不启用此功能
appendfilename "appendonly.aof" #文本文件AOF的文件名,存放在dir指令指定的目录中
appendfsync everysec #aof持久化策略的配置
#no表示由操作系统保证数据同步到磁盘,Linux的默认fsync策略是30秒,最多会丢失30s的数据
#always表示每次写入都执行fsync,以保证数据同步到磁盘,安全性高,性能较差
#everysec表示每秒执行一次fsync,可能会导致丢失这1s数据,此为默认值,也生产建议值
#同时在执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof往往会涉及大量磁盘操作,这样就会造成主进程在写aof文件的时候出现阻塞的情形,以下参数实现控制
no-appendfsync-on-rewrite no #在aof rewrite期间,是否对aof新记录的append暂缓使用文件同步策略,主要考虑磁盘IO开支和请求阻塞时间。
#默认为no,表示"不暂缓",新的aof记录仍然会被立即同步到磁盘,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题
#为yes,相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。丢失多少数据呢?Linux的默认fsync策略是30秒,最多会丢失30s的数据,但由于yes性能较好而且会避免出现阻塞因此比较推荐
#rewrite 即对aof文件进行整理,将空闲空间回收,从而可以减少恢复数据时间
auto-aof-rewrite-percentage 100 #当Aof log增长超过指定百分比例时,重写AOF文件,设置为0表示不自动重写Aof日志,重写是为了使aof体积保持最小,但是还可以确保保存最完整的数据
auto-aof-rewrite-min-size 64mb #触发aof rewrite的最小文件大小
aof-load-truncated yes #是否加载由于某些原因导致的末尾异常的AOF文件(主进程被kill/断电等),建议yes
aof-use-rdb-preamble no #redis4.0新增RDB-AOF混合持久化格式,在开启了这个功能之后,AOF重写产生的文件将同时包含RDB格式的内容和AOF格式的内容,其中RDB格式的内容用于记录已有的数据,而AOF格式的内容则用于记录最近发生了变化的数据,这样Redis就可以同时兼有RDB持久化和AOF持久化的优点(既能够快速地生成重写文件,也能够在出现问题时,快速地载入数据),默认为no,即不启用此功能
lua-time-limit 5000 #lua脚本的最大执行时间,单位为毫秒
cluster-enabled yes #是否开启集群模式,默认不开启,即单机模式
cluster-config-file nodes-6379.conf #由node节点自动生成的集群配置文件名称
cluster-node-timeout 15000 #集群中node节点连接超时时间,单位ms,超过此时间,会踢出集群
cluster-replica-validity-factor 10 #单位为次,在执行故障转移的时候可能有些节点和master断开一段时间导致数据比较旧,这些节点就不适用于选举为master,超过这个时间的就不会被进行故障转移,不能当选master,计算公式:(node-timeout * replica-validity-factor) + repl-ping-replica-period
cluster-migration-barrier 1 #集群迁移屏障,一个主节点至少拥有1个正常工作的从节点,即如果主节点的slave节点故障后会将多余的从节点分配到当前主节点成为其新的从节点。
cluster-require-full-coverage yes #集群请求槽位全部覆盖,如果一个主库宕机且没有备库就会出现集群槽位不全,那么yes时redis集群槽位验证不全,就不再对外提供服务(对key赋值时,会出现CLUSTERDOWN The cluster is down的提示,cluster_state:fail,但ping 仍PONG),而no则可以继续使用,但是会出现查询数据查不到的情况(因为有数据丢失)。生产建议为no
cluster-replica-no-failover no #如果为yes,此选项阻止在主服务器发生故障时尝试对其主服务器进行故障转移。 但是,主服务器仍然可以执行手动强制故障转移,一般为no
#Slow log 是 Redis 用来记录超过指定执行时间的日志系统,执行时间不包括与客户端交谈,发送回复等I/O操作,而是实际执行命令所需的时间(在该阶段线程被阻塞并且不能同时为其它请求提供服务),由于slow log 保存在内存里面,读写速度非常快,因此可放心地使用,不必担心因为开启 slow log 而影响Redis 的速度
slowlog-log-slower-than 10000 #以微秒为单位的慢日志记录,为负数会禁用慢日志,为0会记录每个命令操作。默认值为10ms,一般一条命令执行都在微秒级,生产建议设为1ms-10ms之间
slowlog-max-len 128 #最多记录多少条慢日志的保存队列长度,达到此长度后,记录新命令会将最旧的命令从命令队列中删除,以此滚动删除,即,先进先出,队列固定长度,默认128,值偏小,生产建议设为1000以上