1. 程式人生 > >Mysql-JDBC配置Replication協議

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);