高可用
- 状态机里配置参数
- 状态机常用api--Server.instance.getFsm().xxx
- isMaster(String dbname)是否为主
- get的各种属性
- getMaster(String dbname)同组下的主库节点名称
- getMiddleDbNameInSameGroup(String dbName)拿到同组 下的中间节点
- getGrandSonDbNamesInSameGroup(String dbName)拿到同组 下的孙子节点
- getBrokenDbNamesInSameGroup(String dbName)同组下的故障节点
- getCurrSlaveCount拿到从的数目
- getSemiSlaveDbNamesInSameGroup(String dbName)同组下的所有半同步结点
- getRunningConnParamsInSameGroupWithoutSelfBySon(String dbname)
- deploy的类型
- 更新
- modifyMiddleDb(String dbname,String dbnameNew)更新状态机的中间节点
- removeDBFromDBGroupInfoListInSameGroup(String removeName) 将从DB2Group里删除
- removeSlaveFromBrokenDBNamesInSameGroup(String dbName)从brokenDB里删除
- removeSlaveFromSemiSlaveDbNamesInSameGroup(String dbName)从半同步从库删除
- removeSlaveFromGrandsonDBNamesInSameGroup(dbName)从孙子从库中删除
- dbRelation-api
- SwitchDBHandler高度封装接口
- 数据库对外接口
状态机里配置参数
状态机常用api–Server.instance.getFsm().xxx
isMaster(String dbname)是否为主
get的各种属性
套路都是dbname通过db2Group拿到group 然后拿到clusterInfoMap(String group)拿到相应的属性
getMaster(String dbname)同组下的主库节点名称
getMiddleDbNameInSameGroup(String dbName)拿到同组 下的中间节点
getGrandSonDbNamesInSameGroup(String dbName)拿到同组 下的孙子节点
getBrokenDbNamesInSameGroup(String dbName)同组下的故障节点
getCurrSlaveCount拿到从的数目
不包括故障节点,不包括孙子节点,不包括主节点
getSemiSlaveDbNamesInSameGroup(String dbName)同组下的所有半同步结点
应该包括了 中间节点 与 普通的儿子节点
getRunningConnParamsInSameGroupWithoutSelfBySon(String dbname)
拿到除了自己之外的 所有儿子节点的集合,判断逻辑为
该节点不是自己,并且是中间节点或者为儿子节点的从节点
并且 不是故障节点 这个接口一般用于选顶替故障节点,比如中间节点故障时,选出顶替的故障节点
deploy的类型
getDeployTypeInSameGroup(String name)
其实就是最终的 clusterInfoDb.getDeployType();
更新
modifyMiddleDb(String dbname,String dbnameNew)更新状态机的中间节点
removeDBFromDBGroupInfoListInSameGroup(String removeName) 将从DB2Group里删除
removeSlaveFromBrokenDBNamesInSameGroup(String dbName)从brokenDB里删除
Set brokenDbNames = clusterDbInfo.getBrokenNames();
brokenDbNames.remove(dbname);
removeSlaveFromSemiSlaveDbNamesInSameGroup(String dbName)从半同步从库删除
removeSlaveFromGrandsonDBNamesInSameGroup(dbName)从孙子从库中删除
dbRelation-api
calculateWaitCountByDeploy(String dbname)计算主的应答数
这个接口为 计算集群中主库的理论的应答数,入参dbname可以为主,也可以为从,最终走的是拿到clusteInfoMap的deployType拿到 getCurrSlaveCount 后根据deployType来返回最后的应答数
accordingToDeployTypeSetCandidateDb(String candidateDB,int waitSlaveCount) 设置应答数
给主或新主执行 set global rpl_semi_sync_master_wait_for_slave_count=?
chooseSonToBeMiddleDB(String oldMiddleDB)选择新的中间节点
选中一个新的中间节点,入参必须是一个旧的中间节点里面内部是通过调用
getRunningConnParamsInSameGroupWithoutSelfBySon(oldMiddleDB)除了自己之外的儿子节点,得到是一个Map集合,然后从这个集合中得到一个做为新的中间节点
changRelation(ConnParam slaveConnParam,String dbName,String masterDbName) 修改新的主从(孙子与中间节点)关系
核心业务就是 拿到从节点后,在从节点上执行
CHANGE MASTER TO MASTER_HOST=’%S’ ,MASTER_PORT=%d ,MASTER_AUTO_POSITION=1;
然后修改完关系后会检查IO的同步状态
SHOW SLAVE STATUS 后关注这两个参数
Slave_IO_Running YES 表示已经同步
Slave_SQL_Running Y
setCandidateDBPropery()设置新主属性
stop slave #停止从
reset slave all #重置从的所有信息
set global read_only=0 #读写开关打开
set global sync_binlog=1 #设置双一操作
set global innodb_flush_log_at_trx_commit=1
SwitchDBHandler高度封装接口
changeRelation4GrandSonDBArrangeDB(grandSons,middleNewName)孙子节点指向中间节点
数据库对外接口
removeSlaveDb(String removeDbName,String arrangeMiddleDbName)
判断是否不主库,如果是主库抛异常
- 如果为孙子
如果为孙子则 将clusterMapInfo里面的grandSon去掉这个孙子,然后将db2Group里去掉该节点 - 如果为"儿子"
a.修改主的应答数dbRelation.accordingToDeployTypeSetCandidateDb(String candidateDB,int waitSlaveCount) 即给主执行 set global rpl_semi_sync_master_wait_for_slave_count=?
b.如果为中间节点,并且没有传顶替的中间节点,则自动算出中间节点,孙子节点指向新的中间节点 具体见 dbRelation.changRelation 最后从db2Group里删除
c.如果为中间节点,并且传了顶替的中间节点,则通过状态机的getSemiSlaveDbNamesInSameGroup方法查看该顶替的中间节点是否合法,如果合法再执行dbRelation.changRelation,最后从db2Group里删除
d.如果为故障节点,则将其从从clusterInfoDb的BrokenDbNames里去除,
然后将其从 db2Group 里的集合去除
AddSlaveNode
- 所需要录入的参数
ConnParam 从的连接属性信息
dbName 从的库的名称 程序会校验dbName是否被占用
masterDbName 主的库的名称 不能为空,并且如果校验对应的group是存在的 - 更新状态机配置
如果传的master与状态机里的master一致,status=HALF 则将dbName添加到半同步集合semiSlaveDbNames (添加普通儿子节点)
如果传的master与状态机里的middle一致,status=ASYNC ,则将dbName添加到grandsonDbames (添加孙子节点)
设置中间节点 当状态机里没有中间节点时,此时可以添加 孙子从节点 ,并且status=ASYNC 此时这里master就为即将指定为 中间节点,
即 中间节点的设置是通过–>添加孙子节点设置的 - 计算理论应答数,并设置应答数
calculateWaitCountByDeploy(String dbname)计算主的应答数
accordingToDeployTypeSetCandidateDb(String candidateDB,int waitSlaveCount) 设置应答数 - 添加监控
addMonitorWork
addStatusCheckWork
RecoveryBrokenDb恢复故障节点
- 所需要录入参数
BrokenDbName 故障从节点 会校验是否存在
MasterDbName 对应的主节点 会校验是主节点,还是中节点
syncStatus 状态HALF ASYNC - updateDbConfig4BrokenDB
如果masterName为状态机中的主库,并且status=HALF时,semiSlave增加brokenDBName
如果masterNaem为状态机中的中间节点时,并且status=ASYNC时,grandSon增加brokenDbName
否则报错 - 如果masterName是状态机中的主为
calculateWaitCountByDeploy(String dbname)计算主的应答数
accordingToDeployTypeSetCandidateDb(String candidateDB,int waitSlaveCount) 设置应答数 - 添加监控
addMonitorWork
addStatusCheckWork
ManualSwitch手动切接口
标记故障节点场景
brokenDb值必传,即传的故障节点
检查故障节点brokenDb是否存在group
将故障节点加入clusterDBInfo.addBrokenDBNames
查看该故障节点是否为主库,如果不是主库,则执行slaveBrokenDeal故障节点处理
slaveBrokenDeal
如果是孙子节点则执行 grandSonBrokenDeal(brokenDBName),即从clusterDBInfo的grandSonDbNames里面删除
如果是儿子节点则执行sonBrokenDeal()具体的逻辑为
-
removeSlaveFromSemiSlaveDbNamesInSameGroup(String dbName)从半同步从库删除
-
判断是否为中间节点,如果是则往clusterDBInfo里modifyMiddleDb修改新的中间节点
a. 选择新的中间节点 middleDBNameNew = **dbRelation.chooseSonToBeMiddleDB(**oldMiddleDb)—>**这里主要是通过fsm.getRunningConnParamsInSameGroupWithoutSelfBySon(oldMiddleDb);b. changeRelation4GrandSonDBArangeDB(grandsonDBNames,middleDBNameNew); 主要逻辑为 dbRelation.changeRelation()–>Change master to MASTER_HOST=…
然后调用状态机fsm.modifyMiddleDB修改状态机的中间节点
如果是主故障场景
dbBrokenHandler选出新主即replaceDB
getRunningConnParamsInSameGroupWithoutSelfBySon(brokenDBName)
拿到除自己之外的儿子节点
chooseSonDBTableCandidateMasterDB(brokenDBName,forcewitch,slavesInMasterConnMap);
通过位点比较选出最大的那个从库
- 对于新主
设置新主属性 dbRelation.setCandidateDBPropery();
设置新主应答数 dbRelation.accordingToDeployTypeSetCandidateDB()
如果新主曾经为中间节点,那么孙子节点还是挂在新主上 (这个确认了是这样) - 对于其它从库
设置从库的指向主库的关系即dbRelation.changeRelation(); 即改关系