一、LVS-主从数据库
# nat
# 添加规则
[root@DS ~]# ipvsadm -A -t 192.168.2.130:3306 -s rr
[root@DS ~]# ipvsadm -a -t 192.168.2.130:3306 -r 192.168.2.40:3306 -m
[root@DS ~]# ipvsadm -a -t 192.168.2.130:3306 -r 192.168.2.42:3310 -m
[root@DS ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.2.130:3306 rr
-> 192.168.2.40:3306 Masq 1 0 0
-> 192.168.2.42:3310 Masq 1 0 0
# 修改文件
[root@DS ~]# vim /etc/sysctl.conf
[root@DS ~]# sysctl -p
net.ipv4.ip_forward = 1
# 主数据库-添加网关
[root@master ~]# route del default
[root@master ~]# route add default gw 192.168.2.60
# 从数据库-添加网关
[root@slave ~]# route del default
[root@slave ~]# route add default gw 192.168.2.60
# 主数据库-创建用户
[root@master ~]# mysql -pHui@2003
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 49
Server version: 8.0.33 MySQL Community Server - GPL
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> create user 'aaaa'@'%' identified by 'aaaa';
Query OK, 0 rows affected (0.03 sec)
mysql> grant all on *.* to 'aaaa'@'%';
Query OK, 0 rows affected (0.01 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
# 客户端测试
./mysql -h192.168.2.130 -P3306 -uaaaa -paaaa
show variables like 'server_id';
二、nginx的高可用
# 安装ntpdate
[root@haproxy ~]# yum -y install ntpdate.x86_64
# 同步时间
[root@haproxy ~]# ntpdate cn.ntp.org.cn
14 Aug 10:22:43 ntpdate[1512]: adjust time server 203.107.6.88 offset 0.002669 sec
# 启动服务
[root@haproxy ~]# systemctl start ntpdate.service
# 设置开机启动
[root@haproxy ~]# systemctl enable ntpdate.service
# 安装haproxy
[root@haproxy ~]# yum -y install haproxy
# 修改配置文件
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
63行 frontend main *:80 # 把5000改为80
67行 # use_backend static if url_static # 注释
68行 default_backend web # 把app改为web
86行:添加内容
backend web
balance roundrobin
server weba 192.168.2.101:80 check
server webb 192.168.2.102:80 check
# 启动服务
[root@haproxy ~]# systemctl start haproxy.service
# 设置开机自启
[root@haproxy ~]# systemctl enable haproxy.service
# 本机测试
[root@haproxy ~]# curl 192.168.2.70
web===01
[root@haproxy ~]# curl 192.168.2.70
web===02
# 添加内容
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
# 定义web管理界面
listen statistics
bind *:9090 #定义监听端口
mode http #默认使用协议
stats enable #启用stats
stats uri /hadmin?stats #自定义统计页面的url
stats auth admin:admin #统计页面的账号密码
stats hide-version #隐藏在统计页面上
stats refresh 30s # 统计页面自动刷新时间
stats admin if TRUE # 如果认证通过就做管理功能,可以管理后端服务器
stats realm hapadmin #统计页面密码框上提示文件,默认haproxy\statistics
# 重启服务
[root@haproxy ~]# systemctl restart haproxy.service
浏览器访问:192.168.2.70:9090

关闭web02的nginx服务
root@web02 \~\]# nginx -s stop  ``` # 设置权重 [root@haproxy ~]# vim /etc/haproxy/haproxy.cfg backend web balance roundrobin server weba 192.168.2.101:80 weight 8 check server webb 192.168.2.102:80 weight 2 check [root@haproxy ~]# systemctl restart haproxy.service ``` 浏览器访问:192.168.2.70  ## 三、数据库的高可用 ## haproxy ``` [root@haproxy ~]# vim /etc/haproxy/haproxy.cfg 42 defaults 43 mode tcp # 将http改为tcp 67 #use_backend static if url_static # 注释 68 default_backend mysql # 将web改为mysql 91 添加内容 backend mysql balance roundrobin server master 192.168.2.40:3306 check server master 192.168.2.42:3310 check [root@haproxy ~]# systemctl restart haproxy.service ``` 主数据库-master ``` # 主数据库-创建用户 [root@master ~]# mysql -pHui@2003 mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 49 Server version: 8.0.33 MySQL Community Server - GPL Copyright (c) 2000, 2023, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> create user 'aaaa'@'%' identified by 'aaaa'; Query OK, 0 rows affected (0.03 sec) mysql> grant all on *.* to 'aaaa'@'%'; Query OK, 0 rows affected (0.01 sec) mysql> flush privileges; Query OK, 0 rows affected (0.00 sec) ``` 客户端测试 ``` [root@client ~]# ls anaconda-ks.cfg mysql-8.0.33-linux-glibc2.12-x86_64.tar [root@client ~]# tar -xf mysql-8.0.33-linux-glibc2.12-x86_64.tar [root@client ~]# tar -xf mysql-8.0.33-linux-glibc2.12-x86_64.tar.xz [root@client ~]# ls anaconda-ks.cfg mysql-8.0.33-linux-glibc2.12-x86_64 mysql-8.0.33-linux-glibc2.12-x86_64.tar mysql-8.0.33-linux-glibc2.12-x86_64.tar.xz mysql-router-8.0.33-linux-glibc2.12-x86_64.tar.xz mysql-test-8.0.33-linux-glibc2.12-x86_64.tar.xz [root@client ~]# cp -r mysql-8.0.33-linux-glibc2.12-x86_64 /usr/local/mysql [root@client ~]# cd /usr/local/mysql/ [root@client mysql]# ls bin docs include lib LICENSE man README share support-files [root@client mysql]# cd bin [root@client bin]# ./mysql -h192.168.2.70 -P5000 -uaaaa -paaaa mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 19 Server version: 8.0.33 MySQL Community Server - GPL Copyright (c) 2000, 2023, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show variables like 'server_id'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | server_id | 11 | +---------------+-------+ 1 row in set (0.01 sec) mysql> quit Bye [root@client bin]# ./mysql -h192.168.2.70 -P5000 -uaaaa -paaaa mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 50 Server version: 8.0.33 MySQL Community Server - GPL Copyright (c) 2000, 2023, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show variables like 'server_id'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | server_id | 10 | +---------------+-------+ 1 row in set (0.05 sec) ``` 远程访问测试  ## 四、读写分离 1.在生产中,查询和修改的比例为7:3,查询压力大,可以分出多的主机做查询,slave也是可以被查询,所以,可以将mysql做成高可用主从复制 2.用户发送请求服务器响应压力 (nginx,lvs,haproxy),但是web服务器要提供服务,需要从数据库读写数据,随着业务并发量的提高,单点mysql已经无法满足需求,所以需要配置一主一从,一主多从 3.对数据库的从服务是不用允许修改,否则M-S失效 4.读写分离 5.代码级别读写分离,另一种是中间件读写分析 ### 1.mysql的主从复制 #### (1)主数据库 ``` # master 1.rm -rf /etc/my.cnf 2.glibc下载解压 3.将解压后的文件移动到指定的/usr/local/mysql 4.mkdir /usr/local/mysql/mysl-files 5.user -r -s /sbin/nologin mysql 6.chown mysql:mysql /usr/local/mysql/mysql-files 7.chmod 750 /usr/local/mysql/mysql-files 8./usr/local/mysql/bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql/ 9.查看data目录和初始密码 10./usr/local/mysql/bin/mysql_ssl_rsa_setup --datadir=/usr/local/mysql/data 11.配置文件 [root@master ~]# vim /usr/local/mysql/my.cnf [mysqld] basedir=/usr/local/mysql datadir=/usr/local/mysql/data socket=/tmp/mysql.sock port=3306 log-error=/usr/local/mysql/data/db01-master.err log-bin=/usr/local/mysql/data/binlog server-id=10 character_set_server=utf8mb4 12.cp support-files/mysql.server /etc/init.d/mysql8 13.service mysql8 start 14.sed -i '$aexport PATH=$PATH:/usr/local/mysql/bin' /etc/profile 15.source /etc/profile ``` #### (2)创建用户 ``` 16.mysql -h192.168.2.40 -P3306 -uhaha -phaha 17.create user 'aaaa'%'aaaa' identified by 'an' 18.grant all on *.* to 'aaaa'; ``` #### (3)从数据库 ``` # slave 1.rm -rf /etc/my.cnf 2.glibc下载解压 3.将解压后的文件移动到指定的/usr/local/mysql 4.mkdir /usr/local/mysql/mysl-files 5.user -r -s /sbin/nologin mysql 6.chown mysql:mysql /usr/local/mysql/mysql-files 7.chmod 750 /usr/local/mysql/mysql-files 8.配置文件 [root@master ~]# vim /usr/local/mysql/my.cnf [mysqld] basedir=/usr/local/mysql datadir=/usr/local/mysql/data socket=/tmp/mysql.sock port=3310 log-error=/usr/local/mysql/data/mysql.log log-log=/usr/local/mysql/data/relaylog server-id=11 character_set_server=utf8mb4 9.cp support-files/mysql.server /etc/init.d/mysql8 10.sed -i '$aexport PATH=$PATH:/usr/local/mysql/bin' /etc/profile 11.source /etc/profile ``` #### (4)同步数据 ``` 1.yum -y install rsync 2.service mysql8 stop 3.master=> rm -rf /usr/local/mysql/data/auto.cnf 4.rsync -av /usr/local/mysql/data root@slaveip:/usr/local/mysql 5.slave=>service mysql8 start 6.master=>service mysql8 start ``` #### (5)设置主数据库 ###### 1.创建远程slave账号 ``` create user 'slave'@'%' identified by 'slave'; grant replication slave on *.* to 'slave'@'%'; flush privileges; ``` ###### 2.锁表 ``` flushtables with read lock; ``` ###### 3.查看主库信息 ``` show master status\G; • 1.文件名称 • 2.文件位置 ``` #### (6)设置从数据库 ###### 1.设置change master to ``` mysql> change master to -> master_host='192.168.2.40', -> master_user='slave', -> master_password='slave_123', -> master_log_file='binlog.000006', -> master_log_pos=1547, -> get_master_public_key=1; ``` ###### 2.启动slave并且查看状态 ``` start slave show slave status\G ``` ###### 3.解锁 ``` master=>unlock tables; ``` ## 2.python代码的读写分离 #### 1.环境配置 ``` [root@client ~]# python3 -m pip install --upgrade pip [root@client ~]# pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple [root@client ~]# pip3 install pymysql ``` #### 2.安装pymysql pymysql是python管理mysql的驱动,或者成为连接器 ``` [root@client ~]# pip3 install pymysql ``` #### 3.在python3的命令行界面输入 如pymysql ``` >>> import pymysql ``` #### 4.创建两个connection对象 一个指向master mysql,一个指向slave mysql ``` >>> import pymysql >>> master_conn=pymysql.connect(host="192.168.2.40",user="aaaa",password="aaaa",database="test",port=3306) >>> slave_conn=pymysql.connect(host="192.168.2.42",user="aaaa",password="aaaa",database="test",port=3310) ``` #### 5.master-主数据库 ##### (1)获取数据游标 ###### 语法: ``` master_cursor=master_conn.cursor() ``` ##### (2)执行查询 ###### 语法: ``` select_sql="select * from user"; master_cursor.execute(select_sql); rs=master_cursor.fetchall() ``` ###### 练习: ``` >>> master_cursor=master_conn.cursor() >>> select_sql="select * from user"; >>> master_cursor.execute(select_sql); 4 >>> rs=master_cursor.fetchall() >>> rs ((1, 'zhangsan', '123'), (2, 'lisi', '456'), (3, 'wangwu', '789'), (4, 'zhaoliu', 'aaa')) ``` ###### 在数据中查看 ``` mysql> select * from user; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | zhangsan | 123 | | 2 | lisi | 456 | | 3 | wangwu | 789 | | 4 | zhaoliu | aaa | +----+----------+----------+ 4 rows in set (0.00 sec) ``` ##### (3)执行修改 ###### 语法: ``` update_sql="update user set password='000' where username='aaa'" master_cursor.execute(update_sql) master_conn.commit() ``` ###### 练习: ``` >>> update_sql="update user set password='rrr' where username='lisi'" >>> master_cursor.execute(update_sql) 1 >>> master_conn.commit() ``` ###### 在数据中查看 ``` mysql> select * from user; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | zhangsan | 123 | | 2 | lisi | rrr | | 3 | wangwu | 789 | | 4 | zhaoliu | aaa | +----+----------+----------+ 4 rows in set (0.01 sec) ``` ##### (4)执行删除 ###### 语法: ``` delete_sql="delete user from user where username='aaaa'" master_cursor.execute(delete_sql) master_conn.commit() ``` ###### 练习: ``` >>> delete_sql="delete user from user where username='haha'" >>> master_cursor.execute(delete_sql) 1 >>> master_conn.commit() ``` ###### 在数据中查看 ``` mysql> select * from user; +------+----------+----------+ | id | username | password | +------+----------+----------+ | 1 | zhangsan | 123 | | 2 | lisi | rrr | | 3 | wangwu | 789 | | 4 | zhaoliu | aaa | | 1004 | haha | a1b2 | +------+----------+----------+ 5 rows in set (0.00 sec) mysql> select * from user; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | zhangsan | 123 | | 2 | lisi | rrr | | 3 | wangwu | 789 | | 4 | zhaoliu | aaa | +----+----------+----------+ 4 rows in set (0.00 sec) ``` ##### (5)执行新增 ###### 语法: ``` insert_sql="insert into user values(1004,'dddd','dddd')" master_cursor.execute(insert_sql) master_conn.commit() ``` ###### 练习: ``` >>> insert_sql="insert into user values(1004,'haha','a1b2')" >>> master_cursor.execute(insert_sql) 1 >>> master_conn.commit() ``` ###### 在数据中查看 ``` mysql> select * from user; +----+----------+----------+ | id | username | password | +----+----------+----------+ | 1 | zhangsan | 123 | | 2 | lisi | rrr | | 3 | wangwu | 789 | | 4 | zhaoliu | aaa | +----+----------+----------+ 4 rows in set (0.01 sec) mysql> select * from user; +------+----------+----------+ | id | username | password | +------+----------+----------+ | 1 | zhangsan | 123 | | 2 | lisi | rrr | | 3 | wangwu | 789 | | 4 | zhaoliu | aaa | | 1004 | haha | a1b2 | +------+----------+----------+ 5 rows in set (0.00 sec) ``` ##### (6)slave-从数据库 ``` >>> # 执行查询,获得slave游标 ... >>> slave_cursor=slave_conn.cursor() >>> select_sql 'select * from user' >>> slave_cursor.execute(select_sql) 4 >>> slave_cursor.fetchall() ((1, 'zhangsan', '123'), (2, 'lisi', 'rrr'), (3, 'wangwu', '789'), (4, 'zhaoliu', 'aaa')) ``` 脚本-判断如果是select开头,就去slave执行,如果是其他的就去master执行