分散式資料庫(查詢建構器20)


分散式支援

資料存取層支援分散式資料庫,包括讀寫分離,要啟用分散式資料庫,需要開啟資料庫設定檔中的deploy參數:

return [
    // 启用分布式数据库
    'deploy'    =>  1,
    // 数据库类型
    'type'        => 'mysql',
    // 服务器地址
    'hostname'    => '192.168.1.1,192.168.1.2',
    // 数据库名
    'database'    => 'demo',
    // 数据库用户名
    'username'    => 'root',
    // 数据库密码
    'password'    => '',
    // 数据库连接端口
    'hostport'    => '',
];

啟用分散式資料庫後,hostname參數是關鍵,hostname的數量決定了分散式資料庫的數量,預設情況下第一個位址就是主伺服器。

主從伺服器支援設定不同的連線參數,包括:

usernamepassword#hostportdatabasedsncharset
#連線參數
##########

如果主從伺服器的上述參數一致的話,只需要設置一個,對於不同的參數,可以分別設置,例如:

return [
    // 启用分布式数据库
    'deploy'   => 1,
    // 数据库类型
    'type'     => 'mysql',
    // 服务器地址
    'hostname' => '192.168.1.1,192.168.1.2,192.168.1.3',
    // 数据库名
    'database' => 'demo',
    // 数据库用户名
    'username' => 'root,slave,slave',
    // 数据库密码
    'password' => '123456',
    // 数据库连接端口
    'hostport' => '',
    // 数据库字符集
    'charset'  => 'utf8',
];

記住,要么相同,要么每個都要設定.

分散式的資料庫參數支援使用陣列定義(通常為了避免多個帳號和密碼的誤解析),例如:

return [
    // 启用分布式数据库
    'deploy'   => 1,
    // 数据库类型
    'type'     => 'mysql',
    // 服务器地址
    'hostname' =>[ '192.168.1.1','192.168.1.2','192.168.1.3'],
    // 数据库名
    'database' => 'demo',
    // 数据库用户名
    'username' => 'root,slave,slave',
    // 数据库密码
    'password' => ['123456','abc,def','hello']
    // 数据库连接端口
    'hostport' => '',
    // 数据库字符集
    'charset'  => 'utf8',
];

讀寫分離

還可以設定分散式資料庫的讀寫是否分離,預設的情況下讀寫不分離,也就是每台伺服器都可以進行讀寫操作,對於主從式資料庫而言,需要設定讀寫分離,透過下面的設定就可以:

    'rw_separate' => true,

在讀寫分離的情況下,預設第一個資料庫配置是主伺服器的配置信息,負責寫入數據,如果設定了master_num參數,則可以支援多個主伺服器寫入(每次隨機連接其中一個主伺服器)。其它的位址都是從資料庫,負責讀取數據,數量不限制。每次連接從伺服器並且進行讀取操作的時候,系統會隨機進行在從伺服器中選擇。同一個資料庫連線的每次要求只會連接一次主伺服器和從伺服器,如果某次要求的從伺服器連線不上,會自動切換到主伺服器進行查詢操作。

如果不希望隨機讀取,或者某種情況下其它從伺服器暫時不可用,還可以設定slave_no 指定固定伺服器進行讀取操作,slave_no指定的序號表示hostname中資料庫位址的序號,從0開始。

呼叫查詢類別或模型的CURD操作的話,系統會自動判斷目前執行的方法是讀取操作還是寫入操作並自動連接主從伺服器,如果你用的是原生SQL,那麼需要注意系統的預設規則: 寫入操作必須用資料庫的execute方法,讀取操作必須用資料庫的query方法,否則會發生主從讀取和寫入錯亂的情況。

發生下列情況的話,會自動連接主伺服器:

1.使用了資料庫的寫入操作方法(execute/insert/update/delete以及衍生方法);

#2.如果呼叫了資料庫事務方法的話,會自動連接主伺服器;

3.從伺服器連線失敗,會自動連接主伺服器;

4.呼叫了查詢建構器的lock方法;

5.呼叫了查詢建構器的master/readMaster方法

主從資料庫的資料同步工作不在框架實現,需要資料庫考慮自身的同步或複製機制。如果在大數據量或特殊的情況下寫入資料後可能會存在同步延遲的情況,可以呼叫master()方法進行主函式庫查詢操作。

在實際生產環境中,許多雲端主機的資料庫分散式實作機制和本地開發會有所區別,但通常會採下面用兩種方式:

第一種:提供了寫入IP和讀取IP(一般是虛擬IP),進行資料庫的讀寫分離操作;

第二種:始終保持同一個IP連接資料庫,內部會進行讀寫分離IP調度(阿里雲就是採用該方式)。

主庫讀取

有些情況下,需要直接從主庫讀取數據,例如剛寫入數據之後,從庫數據還來不及同步完成,你可以使用

Db::name('user')
    ->where('id', 1)
    ->update(['name' => 'thinkphp']);
Db::name('user')
    ->master(true)
    ->find(1);

不過,實際情況遠比這個要複雜,因為你不清楚後續的方法裡面是否還存在相關查詢操作,這時候我們可以設定開啟資料庫的read_master設定參數。

// 开启自动主库读取
'read_master' => true,

開啟後,一旦我們對某個資料表進行了寫入操作,那麼當前請求的後續所有對該表的查詢都會使用主庫讀取。