mysql zookeeper 切换_zookeeper在mysql主库选举切换中的应用
為了保證可用性,傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)(mysql)通常采用一主多備的方式,當(dāng)主宕機(jī)后,切換到備機(jī)。
有多種方式可以做到主備自動(dòng)失效檢測(cè)切換,比如傳統(tǒng)的HA軟件heartbeat,keepalived等等,采取虛擬IP的方式對(duì)客戶(hù)端透明;
這里主備自動(dòng)切換方案沒(méi)有采取VIP的方式,而是用zookeeper對(duì)數(shù)據(jù)庫(kù)集群進(jìn)行管理,可以做到主備失效檢測(cè)切換,主庫(kù)的選舉,
比如考慮到mysql對(duì)多核利用率不高而一個(gè)節(jié)點(diǎn)部署多個(gè)mysql實(shí)例,如果采用VIP的方式是不可行的。
基本做法是,每個(gè)mysql實(shí)例上部署一個(gè)agent節(jié)點(diǎn),agent負(fù)責(zé)對(duì)該mysql實(shí)例定時(shí)進(jìn)行ping操作,agent在zookeeper上注冊(cè)臨時(shí)節(jié)點(diǎn),
如果agent或者該agent代理的mysql宕掉,注冊(cè)在zookeeper上的節(jié)點(diǎn)就會(huì)發(fā)生變化,利用zookeeper watch功能實(shí)現(xiàn)mysq實(shí)例失效后的主庫(kù)的選舉操作,
讀節(jié)點(diǎn)也通過(guò)watch master節(jié)點(diǎn)的功能實(shí)現(xiàn)指向新的master。
如上圖所示,zookeeper上的master節(jié)點(diǎn)存儲(chǔ)當(dāng)前主節(jié)點(diǎn)名稱(chēng);
servers下面保存在線的節(jié)點(diǎn),命名規(guī)則一般為ip:port_序列號(hào);
nodeid為當(dāng)前的序列號(hào),每當(dāng)節(jié)點(diǎn)獲取一個(gè)序列號(hào)時(shí),該節(jié)點(diǎn)值自就增,以便于分配給下一個(gè)節(jié)點(diǎn)。
過(guò)程如下:
a、初始化階段,創(chuàng)建servers,master,nodeid節(jié)點(diǎn)
b、每個(gè)client創(chuàng)建servers子節(jié)點(diǎn),zoo_create("/servers/xxx",EPHEMERAL)
c、zoo_get_child(/servers,NULL)
d、若當(dāng)前client的序列號(hào)id是當(dāng)前最小的節(jié)點(diǎn),則當(dāng)前節(jié)點(diǎn)是master,設(shè)置master節(jié)點(diǎn)退出
e、否則,zoo_exsists(lastid before id,watcher)//當(dāng)前節(jié)點(diǎn)watch比當(dāng)前節(jié)點(diǎn)id次小的那個(gè)節(jié)點(diǎn)的狀態(tài)
如果id不存在,那么退出
否則等待watch觸發(fā),重新選舉master
相關(guān)偽代碼參考示例如下:
try {
ProposoWatcher wc = new ProposoWatcher();
final ZooKeeper zk = new ZooKeeper("10.1.1.24:2181", 60000, wc);
wc.setZk(zk);
if (zk.exists("/master", false) == null) {
zk.create("/master", null, Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
}
zk.create("/servers/" + nodeName, new byte[0], Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
List list = zk.getChildren("/servers", false);
String[] nodes = list.toArray(new String[list.size()]);
Arrays.sort(nodes);
if (nodeName.equals(nodes[0])) {//初次
System.out.println("this is master" + nodes[0]);
zk.setData("/master", nodeName.getBytes(), -1);
} else {
// 監(jiān)控比自己次小的Node
String lower = "";
for (int i = 0; i < nodes.length; i++) {
if (nodeName.equals(nodes[i])) {
lower = nodes[i - 1];
break;
}
}
zk.exists("/servers/" + lower, true);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//watcher
public static class ProposoWatcher implements Watcher {
private ZooKeeper zk;
public ZooKeeper getZk() {
return zk;
}
public void setZk(ZooKeeper zk) {
this.zk = zk;
}
@Override
public void process(WatchedEvent event) {
// TODO Auto-generated method stub
switch (event.getType()) {
case None: {
// connectionEvent(event);
break;
}
case NodeDeleted: {
// servers.remove(event.getPath());
System.out.println("node? removed**" + event.getPath());
String delName = event.getPath().substring(
event.getPath().lastIndexOf("/"));
// final ZooKeeper zk1 = zk;
List children = new ArrayList();
try {
children = zk.getChildren("/servers", false);
} catch (KeeperException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String[] nodes = children.toArray(new String[children.size()]);
Arrays.sort(nodes);
for (int i = 0; i < nodes.length; i++) {
if (nodes[i].compareTo(delName) > 0) {
// TODO:curr Node become master
System.out.println("this is master" + nodes[i]);
try {
zk.setData("/master", nodes[i].getBytes(), -1);
} catch (KeeperException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
break;
}
}
}
}
總結(jié)
以上是生活随笔為你收集整理的mysql zookeeper 切换_zookeeper在mysql主库选举切换中的应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: abb变频器电机过热保护怎么复位_变频器
- 下一篇: Java创建MySQL句柄_MySQL创