MysqlFabric 高可用 & 读写分离

感觉有点不够成熟的样子 而且在测试中还存在单点故障 在生产环境谨慎使用

1. 程序必须通过Fabric-aware connectors来连接mysql实现路由,目前只支持PHP,Python 和Java;

2. fabric state store和fabric note当前是单点,虽然fabric-aware连接器可以缓存路由信息(可以配置ttl值);

3. fabric state store(backing store)和fabric note当前是单点,mysqlfabric进程本身不提供容错,出现故障时需要重启,当mysql fabric不可用时,fabric-aware连接器能够通过本地的cache继续路由操作(配置ttl值);-- 在测试过程中 backing store挂了 是致命伤(如果能在非常短时间内恢复则没有问题)  即使backint store恢复 也不能正常插入 不知到是脚本问题 还是确实如此

4. mysql实例进行恢复后,fabric不会自动改变实例的状态,需要手工修改;

5. 自动把slaves都设置为read_only 这点值得表扬。

6. 基于GTID的复制本身存在一些限制。

7. 使用fabric不需要对slave配置vip,不像MHA和MMM等需要对vip进行管理;

8. 使用fabric实现mysql复制高可用,以组为单位对mysql实例进行管理,可以管理多个HA组;

9. mysql实例需要指出gtid,也是就要升级到mysql 5.6.10以上版本;

查看mysqlfabric命令帮助:

mysqlfabric help:显示简短的语法信息和帮忙命令

mysqlfabric help commands: 列出所有可用命令和描述

mysqlfabric help groups: 列出可用命令组

mysqlfabric help [group] [command]: 提供命令的详细帮助信息

常用相关命令

mysqlfabricgroup create my_group          #创建HA组

mysqlfabricgroup destroy my_group        #删除HA组

mysqlfabricgroup add my_group 10.1.1.208:3306     #添加组成员

mysqlfabricgroup remove my_group c505ce10-9bc0-11e4-bfd4-000c290e7abe   #移出组成员

mysqlfabricgroup lookup_servers m_ygroup  #查看组成员

mysqlfabricgroup promote my_group --slaves=10.1.1.207:3306     #选举master

mysqlfabric group demote my_group          #降级在组中的任何primary,不会重新选取一个新master,千万不能在业务进行期间做此操作,同时也不会关闭故障检测。

mysqlfabric groupactivate my_group        #激活自动故障转移

mysqlfabric group deactivate my_group           #禁用自动故障转移

mysqlfabric server set_status server_uuid status #变更服务器状态

mysqlfabrichelp manage   #manage命令帮助

mysqlfabrichelp group     #group命令帮助

mysqlfabrichelp server      #server命令帮助

架构图

    10.1.1.206    mysql master
    10.1.1.207    mysql slave
    10.1.1.208    mysql slave
    10.1.1.210    mysqlfabric backingstore(mysql实例) + node(指fabric服务)        -- backingstore是一个mysql实例 用于存储管理的mysql实例的角色和状态 版本必须与其他实例的mysql版本一直 而且必须高于5.6.10
fabric

mysql-fabric

配置受管理的mysqld实例 -- 206,207,208
-- 给所有受管理的mysql实例安装半同步 206,207,208

-- Mysql安装好后,每个fabric管理的实例需要开启gtid、二进制日志(不需要启动复制,由fabric完成),将以下配置放到[mysqld]段下面:


添加以下内容

配置Mysql Fabric

    1. -- 在backing store节点给fabric node节点授权 必须对fabric库有完全权限 -- 在210上操作
    mysql
    2. -- 在所有受管理的mysql节点给fabric node节点授权 需要对所有数据库拥有完全权限 -- 在206,207,208上操作
    mysql
    3. -- 修改fabric配置文件

      修改以下内容


      -- 其他参数解释 请查看/mysql/MySQL Utilities/mysqlFabric/fabric.cfg 配置文件详解

    4. -- 给backingstore 初始化fabric数据库 -- 在210上操作
   # mysqlfabric manage setup --param=storage.user=fabric --param=storage.password=fabric
    -------------------------------------------- 命令执行后的输出--------------------------------------
          [INFO] 1450940601.418141 - MainThread - Initializing persister: user (fabric), server (10.1.1.210:3306), database (fabric).
            Finishing initial setup                                                -- 表示完成初始化fabric数据库
            =======================
            Password for admin user is not yet set.
            Password for admin/xmlrpc:                                    -- 这里表示要给 admin 设置一个密码 我这里填了fabric
            Repeat Password:                                                       -- 再次输入 fabric
            Password set.
            Password set.
            -----------------------------------------------------------------------------------------------------

运行fabric

    mysqlfabric manage start
    -- 如运行上述命令没有提示错误 则使用以下命令把fabric以服务模式运行 日志信息便会输出到日志文件 /var/log/fabric.log
    mysqlfabric manage start --daemonize
    -- 关闭命令
    mysqlfabric manage stop                                    -- 关闭fabric
    Password for admin:                                             -- 输入刚刚初始化fabric数据库时设置的密码 fabric
    -- 查看监听端口
    netstat -tnlp | grep python
    tcp        0      0 0.0.0.0:32274               0.0.0.0:*                   LISTEN      30937/python
    tcp        0      0 127.0.0.1:32275             0.0.0.0:*                   LISTEN      30937/python

使用fabric创建mysql复制高可用组

-- 创建组 在fabric node 210上操作
mysqlfabric group create my_group                    -- 创建组 名称叫my_group
Password for admin:                                                 -- 输入admin密码 fabric 也可以把密码写在fabric的配置文件 便不需要每次输入密码 但这里建议每次输入密码 防误操作
------------------------------------------ 创建成功输出 ----------------------------------
Fabric UUID:  5ca1ab1e-a007-feed-f00d-cab3fe13249e
Time-To-Live: 1
                                uuid finished success result
------------------------------------ -------- ------- ------
12243c47-bd5c-4695-a9f5-29bbeda5618e        1       1      1
state success          when                                                  description
----- ------- ------------- ------------------------------------------------------------
    3       2   1.45094e+09 Triggered by <mysql.fabric.events.Event object at 0xf57c50>.
    4       2   1.45094e+09                            Executing action (_create_group).
    5       2   1.45094e+09                             Executed action (_create_group).
----------------------------------------------------------------------------------------------
-- 把受管理的mysql实例(206,207,208)添加到组 此操作还不会导致配置主从和failover  在fabric node 210上操作
mysqlfabric group add my_group 10.1.1.206:3306                    -- 添加206
Password for admin:                                               -- 输入admin密码 fabric
mysqlfabric group add my_group 10.1.1.207:3306                    -- 添加207
mysqlfabric group add my_group 10.1.1.208:3306                    -- 添加208

查看组信息

-- 查看状态
mysqlfabric group lookup_servers my_group
------------------------ 输出如下 -----------------------------------------
Fabric UUID:  5ca1ab1e-a007-feed-f00d-cab3fe13249e
Time-To-Live: 1
                         server_uuid                                         address                    status              mode         weight
------------------------------------                            ---------------             ---------             ---------          ------
9507aa71-9280-11e5-88d8-525400ef6331     10.1.1.207:3306     SECONDARY     READ_ONLY    1.0
e0424b22-9ee9-11e5-99c6-52540082b02e    10.1.1.208:3306     SECONDARY     READ_ONLY    1.0
f9d3f20e-9ee8-11e5-99c0-525400b3b967      10.1.1.206:3306     SECONDARY     READ_ONLY    1.0
解释
server_uuid                                    -- mysql实例的uuid
address                                           -- 实例地址
status                                               -- 实例状态 primary 表示为主 secondary 表示为从 spare 表示为备用(不能被读写的意思) faulty 表示故障
-----------------------------------------------------------------------------

-- 查看健康情况

mysqlfabric group health my_group
-------------------------  输出如下 -----------------------------------------
Fabric UUID:  5ca1ab1e-a007-feed-f00d-cab3fe13249e
Time-To-Live: 1
                                uuid is_alive  status is_not_running is_not_configured io_not_running sql_not_running io_error sql_error
------------------------------------ -------- --------- -------------- ----------------- -------------- --------------- -------- ---------
9507aa71-9280-11e5-88d8-525400ef6331        1     SECONDARY              0                 1              0               0    False     False
e0424b22-9ee9-11e5-99c6-52540082b02e        1     SECONDARY              0                 1              0               0    False     False
f9d3f20e-9ee8-11e5-99c0-525400b3b967        1     SECONDARY              0                 1              0               0    False     False
issue
-----
解释
1为是 0为不是
------------------------------------------------------------------------------

配置主从用户 

-- fabric默认用其连接受管理mysql实例的用户配置slave  而且每个slave都有可能成为master 所以要在所有实例上配置 -- 在206,207,208上操作
mysql> grant replication slave on *.* to fabric@'10.1.1.206' identified by 'fabric';
mysql> grant replication slave on *.* to fabric@'10.1.1.207' identified by 'fabric';
mysql> grant replication slave on *.* to fabric@'10.1.1.208' identified by 'fabric';
mysql> reset slave;
mysql> reset master;                                -- 由于GTIDs的主从是自动position 所以刚刚的授权会在建立主从后 在从再运行一次 这样会导致错误

选出master

-- 因为创建高可用组后,fabric没有意识到任何复制拓扑。需要提升一个为primary,降级剩余的服务器自动为secondaries(slaves)。
mysqlfabric group promote my_group --slave_id=10.1.1.206:3306                -- 指定10.1.1.206:3306提升为master
------------------- 命令解释 -------------------------------------

# mysqlfabric help group promote

group promote group_id [--slave_id=NONE] [--update_only] [--synchronous]

-- 如果只是想更新state store,跳过复制配置,使用--update_only参数。

-- 如果slave没有提供,将选择一个最好的候选者,候选者必须开启二进制日志,同时跟master属于同一个组,跟master延时小。进行故障切换操作,选择这个候选者,同时将其他slave指向到新的master,同时更新state store。

-- 执行同样的命名将设置不同的服务器为primary,同时降级当前primary并选取一个新的。如果当前primary错误,执行同样的命令能手动触发选取一个新的primary。

------------------ 把primary降级--------------------------------

mysqlfabric group demote my_group

-- 使用group demote降级在组中的任何primary,不会重新选取一个新master,千万不能在业务进行期间做此操作,同时也不会关闭故障检测。

--------------------------------------------------------------------

-- 查看提升情况
mysqlfabric group lookup_servers my_group
------------------------------------------------- 输出 ---------------------------------------------
9507aa71-9280-11e5-88d8-525400ef6331 10.1.1.207:3306 SECONDARY  READ_ONLY    1.0
e0424b22-9ee9-11e5-99c6-52540082b02e 10.1.1.208:3306 SECONDARY  READ_ONLY    1.0
f9d3f20e-9ee8-11e5-99c0-525400b3b967 10.1.1.206:3306   PRIMARY READ_WRITE    1.0                        -- 状态已变为 PRIMARY 表示主
-----------------------------------------------------------------------------------------------------
-- 查看slave的读写状态 在207 208上操作
show variables like 'read_only';
| read_only     | ON    |                                                -- fabric 会自动把slave设置为只读 这点非常好
show slave status\G;                                                  -- 查看从的情况 没有error则表示成功
-- 查看半同步状态
    show status like '%semi_sync%';
    Rpl_semi_sync_master_status                | ON                         -- 在206上此值为ON
    Rpl_semi_sync_slave_status                 | ON                            -- 在207上此值为ON
    -- 表示206和207之间的半同步已成功启用

启用故障检测( failover )

mysqlfabric group activate my_group
    --  mysqlfabric group deactivate my_group           #禁用自动故障转移

模拟故障

-- 把master关闭 
mysqladmin -predhat shutdown
-- 查看fabricHA组的角色状态
mysqlfabric group lookup_servers my_group
--------------- 输出如下 -------------------------------------
                         server_uuid         address    status       mode weight
------------------------------------ --------------- --------- ---------- ------
9507aa71-9280-11e5-88d8-525400ef6331 10.1.1.207:3306 SECONDARY  READ_ONLY    1.0
e0424b22-9ee9-11e5-99c6-52540082b02e 10.1.1.208:3306   PRIMARY READ_WRITE    1.0                    -- 自动把208提升为新主
f9d3f20e-9ee8-11e5-99c0-525400b3b967 10.1.1.206:3306    FAULTY READ_WRITE    1.0                        -- 关掉的master状态已变为FAULTY
----------------------------------------------------------------
-- 查看slave 207的情况
show slave status\G;
-- master指向新主208 而且没有任何error 则表示切换成功
-- 把原master 206恢复
service mysqld start
-- 此时虽然原master已经起来 但是fabric并没有把他自动恢复到主从里面 继续下面来验证
-- 查看原master恢复后的fabricHA组的角色状态
mysqlfabric group lookup_servers my_group
----------------------------- 输出如下 ----------------------------------------------
                         server_uuid         address    status       mode weight
------------------------------------ --------------- --------- ---------- ------
9507aa71-9280-11e5-88d8-525400ef6331 10.1.1.207:3306 SECONDARY  READ_ONLY    1.0
e0424b22-9ee9-11e5-99c6-52540082b02e 10.1.1.208:3306   PRIMARY READ_WRITE    1.0
f9d3f20e-9ee8-11e5-99c0-525400b3b967 10.1.1.206:3306    FAULTY READ_WRITE    1.0                    -- 原master状态依旧为FAULTY
---------------------------------------------------------------------------------------
-- 把原master恢复到集群里面
-- 一个标记位"faulty"状态的服务器不能提升为secondary或primary,需要先转换成"spare"状态。使用命令mysqlfabric server set_status <server-address> spare
---------------------相关命令 ----------------------------------------------

# mysqlfabric help server set_status

server set_status server_id status [--update_only] [--synchronous]

Set a server's status.

支持的状态值为primary,secondary,spare,faulty。

--------------------------------------------------------------------------------

-- 切换到spare
mysqlfabric server set_status f9d3f20e-9ee8-11e5-99c0-525400b3b967 spare                        -- 把206切换成spare角色,改变到spare,避免写和读访问,同时保证当故障切换时不会被选取。这里需要用206对应的uuid表示 注意要看清楚有没有搞错uuid 当然也可以使用10.1.1.206:3306 这样代替
------------------------------- mysqlfabric group lookup_servers my_group 查看角色状态 ---------------------
f9d3f20e-9ee8-11e5-99c0-525400b3b967 10.1.1.206:3306     SPARE    OFFLINE    1.0             -- 角色已变为SPARE 而且模式为OFFLINE 表示不会被应用访问到
---------------------------------------------------------------------------------------------------------------------------
-- 切换到secondary
mysqlfabric server set_status f9d3f20e-9ee8-11e5-99c0-525400b3b967 secondary                -- 把206切换成 secondary 角色 成功加入服务
----------------- mysqlfabric group lookup_servers my_group 查看角色状态 ---------
f9d3f20e-9ee8-11e5-99c0-525400b3b967 10.1.1.206:3306 SECONDARY  READ_ONLY    1.0        -- 角色已变为SECONDARY 模式为READ_ONLY
-----------------------------------------------------------------------------

使用python 测试连接数据库和插入数据时故障切换

-- 应用程序通过fabric-aware连接器连接到fabric,获取服务器、组信息。

-- 创建数据库和表和授权用户 -- 在master 206上操作

-- 创建库和表
-- 给执行python的机器赋予mysqld权限

-- 在210上编写脚本 

-- 脚本达到无限插入数据并插入失败重新提交

-- 执行脚本

模拟故障

-- 在脚本执行期间 模拟故障 把master关掉
-- 查看组状态

 

-- 查看日志文件

--------------------- 截取日志重点如下--------------------------

INSERT INTO t1 VALUES (172,"a")
insert ok                                                                                        -- 172插入成功
INSERT INTO t1 VALUES (173,"a")
Reported faulty server to Fabric (2003: Can't connect to MySQL server on '10.1.1.208:3306' (111 Connection refused))        -- 173插入失败 因为master关掉了
INSERT INTO t1 VALUES (173,"a")
Reported faulty server to Fabric (2003: Can't connect to MySQL server on '10.1.1.208:3306' (111 Connection refused))
INSERT INTO t1 VALUES (173,"a")
Reported faulty server to Fabric (2003: Can't connect to MySQL server on '10.1.1.208:3306' (111 Connection refused))
INSERT INTO t1 VALUES (173,"a")
Error getting connection: No MySQL server available for group 'my_group' mode=3                                                                    -- 可能正在failover 所以获取错误
INSERT INTO t1 VALUES (173,"a")
insert ok                                                                                                                                                                                                             -- 插入成功 仍然插入173 证明没有丢失数据
INSERT INTO t1 VALUES (174,"a")
insert ok
INSERT INTO t1 VALUES (175,"a")
--------------------------------------------------------------------

模拟mysqlfabric故障

-- 由于fabric state store和fabric note当前是单点,虽然fabric-aware连接器可以缓存路由信息(可以配置ttl值);

-- 模拟backing store 的mysqld故障

-- 先把HA组的所有mysqld恢复正常并正常建立主从关系
-- 执行脚本
-- 把backing store关掉 --210上的mysqld
-- 查看日志
--------------------------- 日志输出 -------------------------------------------
INSERT INTO t1 VALUES (274,"a")
insert ok                                                                                                        -- 把mysqld关掉后一段时间还是能正常插入 估计是TTL时间的设置
INSERT INTO t1 VALUES (275,"a")
Error getting connection: Connection with Fabric failed: <urlopen error [Errno 104] Connection reset by peer>            -- 然后就出错了  而且是即时把mysqld恢复 这里也没有恢复正常
INSERT INTO t1 VALUES (275,"a")
Error getting connection: Connection with Fabric failed: <urlopen error [Errno 104] Connection reset by peer>
------------------------------------------------------------------------------------
-- 但把python脚本关掉 重新跑 又可以了 其中的原因 暂时还不得知

-- 模拟fabric node( fabric进程 )故障

-- 先把HA组的所有mysqld恢复正常并正常建立主从关系
-- 执行脚本

-- 把fabric关掉


-- 查看日志

--------------------------- 日志输出 -----------------------------------------------
INSERT INTO t1 VALUES (270,"a")
insert ok                                                                                                        -- 也是能正常插入一段时间
INSERT INTO t1 VALUES (271,"a")
Error getting connection: Connection with Fabric failed: <urlopen error [Errno 111] Connection refused>            -- 然后就报错了 因为把fabric进程关了
INSERT INTO t1 VALUES (271,"a")
Error getting connection: Connection with Fabric failed: <urlopen error [Errno 111] Connection refused>
INSERT INTO t1 VALUES (271,"a")
insert ok
-- 把fabric重新启动之后 插入又正常了
--------------------------------------------------------------------------------------
测试总结:
-- 在测试过程中 backing store挂了 是致命伤(如果能在非常短时间内恢复则没有问题)  即使backint store恢复 也不能正常插入 不知到是脚本问题 还是确实如此
-- fabric进程挂了 在进程恢复后 就能恢复正常
-- 在backing store挂的期间 如果master也挂了 fabric也能正常处理failover
-- 在fabric进程挂了期间 (他压根不工作好吧 还怎么failover呢)
-- 调大TTL值

 

-- 重新测试上面2个单点故障

-- 结果一模一样 压根不是调大TTL值就能解决的 致命伤啊

组维护

1、找出哪些服务器在组中,查看组状态

2、从组中移除mysql实例

-- 有时需要将secondaries离线进行维护,在停止服务之前,需要先从组中移除它,避免fabric错误检查触发任何动作:

-- 如从my_group组中移除server_uuid为7bd52611-2d44-11e4-af5f-3ecad7c2f82a的实例:

-- 然后可以重新添加到组,将自动开启复制:

3、添加一个全新的Mysql实例(实例IP为172.17.0.51)到HA group组

-- 查看前面的创建过程即可

4、降级primary

-- primary不能从组中移除,使用group demote关闭在组中的任何primary,不会重新选取一个新master,同时也不会关闭故障检测。

 

5、手动提升一个服务组,选取一个master

6、移除组(使用group destroy)

-- 如果组没有服务器,是空的,能移除组

-- 也能强制的移除非空的组(使用--force):

 

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: