MySQL中如何实现半同步semi-sync replication

一、半同步简介
  • MASTER节点在执行完客户端提交的事务后不是立刻返回结果给客户端,而是等待至少一个SLAVE节点接收并写到relay log中才返回给客户端。

  • 半同步相对于异步复制而言,提高了数据的安全性,同时也造成了一定程度的延迟,这个延迟最少是一个TCP往返的时间。所以,半同步复制最好在低延时的网络中使用。

  • MySQL从5.5开始就支持半同步复制,在5.7.2版本的时候对半同步复制进行了一次改进;原先的半同步策略为 AFTER_COMMIT 改进后的策略为 AFTER_SYNC 两者的差异在于SLAVE节点ACK应答MASTER的时机不同。

二、两种模式介绍

用Python轻松搭建Redis集群,快速提升应用的性能

AFTER_COMMIT 模式介绍

MASTER将每个事务写入到二进制日志并刷盘保存,同时将事务发送给SLAVE,然后将事务提交给存储引擎处理并进行提交,然后等待SLAVE返回确认信息,在收到确认信息后,MASTER将结果返回给客户端,然后当前客户端可以继续工作。

AFTER_SYNC 模式介绍

MASTER将每个事务写入到二进制日志并刷盘保存,同时将事务发送给SLAVE,然后等待SLAVE返回确认信息,收到确认信息后,将事务提交给存储引擎处理并进行提交,并将结果返回给客户端,然后当前客户端可以继续工作。

三、两种方式比较

对于第一种 AFTER_COMMIT 方式,当前客户端只有在服务器向存储引擎提交数据并收到SLAVE返回的确认后,才会收到事务的返回结果。在事务提交之后收到SLAVE返回确认信息之前,此刻其他客户端可以看到当前客户端提交的事务信息。如果SLAVE节点由于网络等原因并未收到MASTER节点传递过来的事务,而MASTER节点此刻crash了。HA进行故障转移,客户端都连到SLAVE节点上,这时先前在MASTER节点看到的事务在SLAVE节点并未看到,就会发生事务丢失的情况。

对于第二种 AFTER_SYNC 方式,当事务被SLAVE确认后MASTER在存储引擎层面进行提交事务后,所有客户端才能看到事务造成的数据更改。因此,所有客户端在MASTER上同一时刻看到是相同的数据。当MASTER节点crash的情况下,所有在MASTER上提交的事务都被复制到SLAVE(保存到中继日志中)。 MASTER服务器意外crash。此刻HA进行故障转移到SALVE后,客户端看到的数据是无损的,因为SLAVE是最新的。注意,然而,在这种情况下,MASTER不能直接恢复使用,因为它的二进制日志可能包含未提交的事务,此刻当二进制日志恢复并用于业务需求时,可能会导致与SLAVE的冲突。

四、如何开启半同步

方式1:半同步以插件的形式存在,咱们可以直接在线开启即可(本次采用这次方式)

主节点开启:

[root@GreatSQL][(none)]>
INSTALL PLUGIN rpl_semi_sync_master SONAME '
semisync_master.so'
;

Query OK, 0 rows affected (0.02 sec)

从节点开启:

[root@GreatSQL][(none)]>
INSTALL PLUGIN rpl_semi_sync_slave SONAME '
semisync_slave.so'
;

Query OK, 0 rows affected (0.02 sec)

PS:一般情况下所有节点都同步部署master和slave插件,这样故障切换的时候会比较方便处理

方式2:在my.cnf配置中进行开启

主从节点都同步配置开启:

plugin-load="
rpl_semi_sync_master=semisync_master.so;
rpl_sync_slave=semisync_slave.so"

rpl_semi_sync_master_enabled=1
rpl_semi_sync_slave_enabled=1 五、查看插件开启情况

方式1:查询plugin

主节点查看:

[root@GreatSQL][test]>
show plugins;

| rpl_semi_sync_master | ACTIVE | REPLICATION | semisync_master.so | GPL |

从节点查看:

[root@GreatSQL][(none)]>
show plugins;

| rpl_semi_sync_slave | ACTIVE | REPLICATION | semisync_slave.so | GPL |

方式二:查询information_schema.plugins信息更全面

主节点信息:

(Thu Feb 17 03:03:12 2022)[root@GreatSQL][(none)]>
select * from information_schema.plugins where plugin_name like "
%semi%"
\G;

*************************** 1. row ***************************
PLUGIN_NAME: rpl_semi_sync_master
PLUGIN_VERSION: 1.0
PLUGIN_STATUS: ACTIVE
PLUGIN_TYPE: REPLICATION
PLUGIN_TYPE_VERSION: 4.0
PLUGIN_LIBRARY: semisync_master.so
PLUGIN_LIBRARY_VERSION: 1.10
PLUGIN_AUTHOR: Oracle Corporation
PLUGIN_DESCRIPTION: Semi-synchronous replication master
PLUGIN_LICENSE: GPL
LOAD_OPTION: ON
1 row in set (0.00 sec)

ERROR:
No query specified

# 从节点信息
(Thu Feb 17 16:05:19 2022)[root@GreatSQL][(none)]>
select * from information_schema.plugins where plugin_name like "
%semi%"
\G;

*************************** 1. row ***************************
PLUGIN_NAME: rpl_semi_sync_slave
PLUGIN_VERSION: 1.0
PLUGIN_STATUS: ACTIVE
PLUGIN_TYPE: REPLICATION
PLUGIN_TYPE_VERSION: 4.0
PLUGIN_LIBRARY: semisync_slave.so
PLUGIN_LIBRARY_VERSION: 1.10
PLUGIN_AUTHOR: Oracle Corporation
PLUGIN_DESCRIPTION: Semi-synchronous replication slave
PLUGIN_LICENSE: GPL
LOAD_OPTION: ON
1 row in set (0.00 sec 六、开启半同步功能

因为上面是在线安装插件的,所以插件安装完成后,服务还要启动一下

主节点启用半同步复制:

[root@GreatSQL][test]>
SET GLOBAL rpl_semi_sync_master_enabled = on;

Query OK, 0 rows affected (0.00 sec)

从节点启用半同步复制:

t@GreatSQL][(none)]>
SET GLOBAL rpl_semi_sync_slave_enabled = on;

Query OK, 0 rows affected (0.00 sec)

以上设置完成后,从节点重启IO线程

(Mon Feb 14 15:19:58 2022)[root@GreatSQL][(none)]>

(Mon Feb 14 15:19:58 2022)[root@GreatSQL][(none)]>
STOP SLAVE IO_THREAD;

Query OK, 0 rows affected, 1 warning (0.01 sec)

(Mon Feb 14 15:21:41 2022)[root@GreatSQL][(none)]>
START SLAVE IO_THREAD;

Query OK, 0 rows affected, 1 warning (0.01 sec) 七、查看半同步是否运行

主节点:

[root@GreatSQL][test]>
show status like '
Rpl_semi_sync_master_status'
;

+-----------------------------+-------+
| Variable_name | Value |
+-----------------------------+-------+
| Rpl_semi_sync_master_status | ON |
+-----------------------------+-------+
1 row in set (0.00 sec)

从节点:

[root@GreatSQL][(none)]>
show status like '
Rpl_semi_sync_slave_status'
;

+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
1 row in set (0.01 sec)

查看主节点error.log,可以看出来从节点已经启用半同步复制了

# 关键信息 Start semi-sync binlog_dump to slave (server_id: 3306)
2022-02-14T02:16:35.411061-05:00 13 [Note] [MY-010014] [Repl] While initializing dump thread for slave with UUID <
652ade08-8b1c-11ec-9f62-00155dcff90a>
, found a zombie dump thread with the same UUID. Master is killing the zombie dump thread(12).
2022-02-14T02:16:35.411236-05:00 13 [Note] [MY-010462] [Repl] Start binlog_dump to master_thread_id(13) slave_server(3306), pos(, 4)
2022-02-14T02:16:35.411263-05:00 13 [Note] [MY-011170] [Repl] Start asynchronous binlog_dump to slave (server_id: 3306), pos(, 4).
2022-02-14T02:16:35.411419-05:00 12 [Note] [MY-011171] [Repl] Stop asynchronous binlog_dump to slave (server_id: 3306).
2022-02-14T02:19:33.913084-05:00 9 [Note] [MY-011130] [Repl] Semi-sync replication initialized for transactions.
2022-02-14T02:19:33.913133-05:00 9 [Note] [MY-011142] [Repl] Semi-sync replication enabled on the master.
2022-02-14T02:19:33.913638-05:00 0 [Note] [MY-011166] [Repl] Starting ack receiver thread.
2022-02-14T02:21:46.899725-05:00 14 [Note] [MY-010014] [Repl] While initializing dump thread for slave with UUID <
652ade08-8b1c-11ec-9f62-00155dcff90a>
, found a zombie dump thread with the same UUID. Master is killing the zombie dump thread(13).
2022-02-14T02:21:46.899894-05:00 14 [Note] [MY-010462] [Repl] Start binlog_dump to master_thread_id(14) slave_server(3306), pos(, 4)
2022-02-14T02:21:46.899953-05:00 14 [Note] [MY-011170] [Repl] Start semi-sync binlog_dump to slave (server_id: 3306), pos(, 4).

以上,MySQL半同步复制搭建完毕!

八、半同步参数信息

主节点参数信息:

[root@GreatSQL][test]>
show variables like '
%Rpl%'
;

+-------------------------------------------+------------+
| Variable_name | Value |
+-------------------------------------------+------------+
| rpl_read_size | 8192 |
| rpl_semi_sync_master_enabled | ON |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_for_slave_count | 1 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_SYNC |
| rpl_stop_slave_timeout | 31536000 |
+-------------------------------------------+------------+
8 rows in set (0.00 sec)

部分参数简单说明:

从节点参数信息:

[root@GreatSQL][test]>
show variables like '
%Rpl%'
;

+---------------------------------+----------+
| Variable_name | Value |
+---------------------------------+----------+
| rpl_read_size | 8192 |
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
| rpl_stop_slave_timeout | 31536000 |
+---------------------------------+----------+
4 rows in set (0.00 sec)

部分参数简单说明:

九、半同步状态信息

主节点查看:

[root@GreatSQL][test]>
show status like '
%Rpl_semi%'
;

+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 0 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 0 |
| Rpl_semi_sync_master_tx_wait_time | 0 |
| Rpl_semi_sync_master_tx_waits | 0 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 0 |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

部分参数用途简要说明:

从节点转态信息:

show global status like '
%semi%'
;

+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
1 row in set (0.00 sec)

参数简单说明:

十、测试一下半同步的同步情况
  • 半同步是否会降级为异步复制?是会的。

  • 当半同步复制发生超时时(由rpl_semi_sync_master_timeout参数控制,单位是毫秒,默认为10000,即10s),会暂时关闭半同步复制,转而使用异步复制。

  • 当MASTER DUMP 线程发送完一个事务的所有事件之后,如果在rpl_semi_sync_master_timeout内,收到了从库的响应,则主从又重新恢复为半同步复制。

1.从节点暂时先关掉IO线程[root@GreatSQL][(none)]>
STOP SLAVE IO_THREAD;

Query OK, 0 rows affected, 1 warning (0.02 sec) 2.主节点写入几条测试数据[root@GreatSQL][test]>
insert into ptype values(4,'
4'
,'
4'
),(5,'
5'
,'
5'
),(6,'
6'
,'
6'
);

Query OK, 3 rows affected (0.02 sec) 3.等待10s后查看复制状态,半同步已经关掉了[root@GreatSQL][test]>
show status like '
Rpl_semi_sync_slave_status'
;

+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | OFF |
+----------------------------+-------+
1 row in set (0.00 sec) 4.从节点开启IO线程[root@GreatSQL][(none)]>
START SLAVE IO_THREAD;

Query OK, 0 rows affected, 1 warning (0.02 sec) 5.再次查看复制状态,半同步复制自动开启了t@GreatSQL][test]>
show status like '
Rpl_semi_sync_slave_status'
;

+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
1 row in set (0.00 sec)

Redis是当今流行的NoSQL数据库之一,其高性能、可扩展性以及灵活性广受认可,被越来越多的应用程序选用。为了满足大量应用对Redis的需求,搭建Redis集群已经成为一个必需的步骤。本文将介绍如何用Python快速搭建Redis集群,并探讨如何应对常见的问题。
1.搭建Redis集群的基本步骤
搭建Redis集群基于Redis Cluster,它将数据分片存储,提高了Redis数据库的可扩展性和容错性。 搭建Redis集群的步骤如下:
-安装Python Redis模块
-设置Redis集群配置文件
-启动Redis集群
-验证Redis集群是否正常工作
2.应对搭建Redis集群中的常见问题
搭建Redis集群可遇到多个问题,如节点迁移、数据丢失和故障恢复等。为了避免出现这些问题,建议在搭建Redis集群前做好准备工作,并按以下步骤操作:
-制定集群规划
-确保网络通畅
-设置节点间互信
-合理分配资源
-备份数据和文件
3.如何评估Redis集群的性能
性能评估是机器学习过程中一项关键任务,对于Redis集群同样如此。对Redis集群性能进行评估的步骤如下:
-确定评估对象和集群规模
-选择测试工具
-进行单节点测试和多节点测试
-记录评估结果
本文提供的不仅是纯技术方面的指导,还包括了一些操作实践技巧,不仅适用于Redis集群的搭建,也适用于其他集群的搭建。追随本文所讲的步骤,相信你一定能够实现快速搭建合理效率的Redis集群,为应用程序的高效稳定提供有力支撑。