Mysql-JDBC配置Replication協議
這部分描述了Mysql-JDBC對於replication協議的一系列特性的支援。
mysql-jdbc-replication初始化於建立連線URL階段,和通常的jdbc URL類似,但也有些特殊性:
jdbc:mysql:replication://[master host][:port],[slave host 1][:port][,[slave host 2][:port]]...[/[database]] »
[?propertyName1=propertyValue1[&propertyName2=propertyValue2]...]
使用者需要指定allowMasterDownConnections=true 來允許即便沒有主庫,也能建立連線物件。這些連線物件是隻讀的,呼叫 isMasterConnection()將返回false,這些連線當Connection.setReadOnly(false)被呼叫時,會測試主節點的可用性,如果到主節點不可用,將丟擲一個SQLException,如果可用,則會在主節點執行操作。
對於mysql-jdbc 5.1.38 和更久之後,使用者需要具體指定allowSlavesDownConnections=true,來允許即便沒有從庫,也能建立連線物件。一個連線,那時候,在執行時,在Connection.setReadOnly(true)時,將測試連線的可用性,如果到從節點不可達(包括readFromMasterWhenNoSlaves=true時,主節點也不可達),將丟擲SQLException。
通過分發讀請求到從節點來實現負載均衡
mysql-jdbc 3.1.7和更高的版本,包括一系列的驅動來分發請求到讀/寫節點,提供failover的保障,和基於Connection.getReadOnly()實現的從節點負載均衡。
一個應用如果想通過Connection.setReadOnly(true)開啟一個只讀事務,驅動知道了應用要使用其中一個從節點,會隨機取一個。在一個事務中,所有操作會附著在一個連線上,知道這個事務提交或者回滾,或這個從節點被服務移除。在mysql-jdbc 5.1.38和更久之後,在呼叫Connection.setReadOnly(true),如果沒有從庫可用時,你想讓連線打到主節點那麼你需要設定readFromMasterWhenNoSlaves=true。
如果你有一個寫事務,或者你有個讀請求是時間敏感的(binlog同步有延遲),通過設定Connection.setReadOnly(false),驅動將會保證你的請求會到主庫。驅動負責維護事務的傳播等級,隔離級別,以及連線之間的關係和列表。
為了確保這個功能,在建立連線池,或者為單體應用建立JDBC連線時,請使用com.mysql.jdbc.ReplicationDriver 這個驅動,他也接受Mysql-JDBC的標準驅動,ReplicationDriver目前不能和基於java.sql.DriverManager建立的連線一起工作,除非是Mysql-JDBC官方的驅動註冊到DriverManager。
這裡有個ReplicationDriver的例子:
import java.sql.Connection; import java.sql.ResultSet; import java.util.Properties; import com.mysql.jdbc.ReplicationDriver; public class ReplicationDriverDemo { public static void main(String[] args) throws Exception { ReplicationDriver driver = new ReplicationDriver(); Properties props = new Properties(); // We want this for failover on the slaves props.put("autoReconnect", "true"); // We want to load balance between the slaves props.put("roundRobinLoadBalance", "true"); props.put("user", "foo"); props.put("password", "password"); // // Looks like a normal MySQL JDBC url, with a // comma-separated list of hosts, the first // being the 'master', the rest being any number // of slaves that the driver will load balance against // Connection conn = driver.connect("jdbc:mysql:replication://master,slave1,slave2,slave3/test", props); // // Perform read/write work on the master // by setting the read-only flag to "false" // conn.setReadOnly(false); conn.setAutoCommit(false); conn.createStatement().executeUpdate("UPDATE some_table ...."); conn.commit(); // // Now, do a query from a slave, the driver automatically picks one // from the list // conn.setReadOnly(true); ResultSet rs = conn.createStatement().executeQuery("SELECT a,b FROM alt_table"); ....... } }
可以考慮使用loadBalance JDBC連線池工具–lbpool:它在標準jdbc-driver的包裝器,包括失敗檢查,和負載分發,關於更多的資訊,請關注:https://code.google.com/archive/p/mysql-lbpool/
對於多主形式的支援
在mysql-jdbc 5.1.27後,開始支援多主replication驅動
連線模式如下:
jdbc:mysql:replication://address=(type=master)(host=master1host),address=(type=master)(host=master2host),address=(type=slave)(host=slave1host)/database
Replication的實時重構
自動mysql-jdbc 5.1.28後,提供了replication實時重構的功能,使用者可以在不停用java應用時,動態的新增,刪除節點。
replication主機連線在replication連線組下管理最有效,一個replication連線組,代表了被統一管理的一個邏輯組,在一個java應用,可能有一個或多個replication連線組,主類暴露出管理replication連線內主機的方法,replication物件註冊在自己的連線組內。每個連線組追蹤自己的連線,直至關閉,並且操作這些關聯的主機。
有一些重要的管理主機的方法:
- getMasterHosts()
- getSlaveHosts()
- addSlaveHost(String host)
- promoteSlaveToMaster(String host)
- removeSlaveHost(String host, boolean closeGently)
- removeMasterHost(String host, boolean closeGently)
有些有用的管理方法如下:
- getConnectionCountWithHostAsSlave(String host)
- getConnectionCountWithHostAsMaster(String host)
- getNumberOfSlavesAdded() --返回動態新增的從節點數量
- getNumberOfSlavesRemoved() --返回動態刪除的節點數量
- getNumberOfSlavePromotions() --動態升主次數
- getTotalConnectionCount() --註冊在這個組內的replication連線數
- getActiveConnectionCount() --正在被組內管理的replication連線數
Replication連線組管理器
com.mysql.jdbc.ReplicationConnectionGroupManager 提供了接入replication連線組的方法,和其他一些方法
- getConnectionGroup(String groupName) --根據組名返回組物件
在ReplicationConnectionGroupManager中的其他方法,反應了ReplicationConnectionGroup,除了第一次宣告為String型別的組名的組。(什麼鬼。。。)這些方法將會操作所有匹配的replication組,對移除應用中的組有用。
如果應用觸發了Replication模式的改變,這些方法對於JVM管理Replication主機也許會有用,對於JVM外管理主機配置,JMX也許會有用
使用JMX管理Replication主機
當Connector/J以replicationEnableJMX=true開頭,而且設定了replicationConnectionGroup屬性,JMX的MBean將會被註冊,允許通過JMX客戶端操作Replication主機,MBean的介面定義在com.mysql.jdbc.jmx.ReplicationGroupManagerMBean並且促使ReplicationConnectionGroupManager改變靜態方法。
public abstract void addSlaveHost(String groupFilter, String host) throws SQLException;
public abstract void removeSlaveHost(String groupFilter, String host) throws SQLException;
public abstract void promoteSlaveToMaster(String groupFilter, String host) throws SQLException;
public abstract void removeMasterHost(String groupFilter, String host) throws SQLException;
public abstract String getMasterHostsList(String group);
public abstract String getSlaveHostsList(String group);
public abstract String getRegisteredConnectionGroups();
public abstract int getActiveMasterHostCount(String group);
public abstract int getActiveSlaveHostCount(String group);
public abstract int getSlavePromotionCount(String group);
public abstract long getTotalLogicalConnectionCount(String group);
public abstract long getActiveLogicalConnectionCount(String group);