Sharding JDBC-讀寫分離

本文作者:樑開權,叩丁狼高級講師。原創文章,轉載請註明出處。

讀寫分離

接着上一篇的分表分庫我們繼續來說讀寫分離

案例模型

讓數據庫的讀和寫功能分開,其中master負責所有的寫操作以及在特殊情況下負責少量的讀操作,slave在任何情況下都負責所有的讀操作,不負責任何寫操作,同樣完成這個操作我們需要至少需要2個連接池,具體選擇哪個連接池來操作取決於內部的一個叫路由的組件,該組件具有SQL的識別功能

注意:該功能需要依靠數據庫的主從同步才能實現,具體怎麼配置請參考之前的筆記

建表

-- 分別在主和從服務器中建立數據庫sharding,並且建表employee
CREATE TABLE `employee` (
  `id` bigint(20) PRIMARY KEY AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ###################################
CREATE TABLE `employee` (
  `id` bigint(20) PRIMARY KEY AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

application.properties

# 定義連接池
sharding.jdbc.datasource.names=master,slave

# 主庫連接池
sharding.jdbc.datasource.master.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.master.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.master.url=jdbc:mysql://masterIp:port/sharing
sharding.jdbc.datasource.master.username=xxx
sharding.jdbc.datasource.master.password=xxx

# 從庫連接池
sharding.jdbc.datasource.slave.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.slave.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.slave.url=jdbc:mysql://slaveIp:port/sharing
sharding.jdbc.datasource.slave.username=xxx
sharding.jdbc.datasource.slave.password=xxx

# 主從路由連接池名稱,叫dataSource爲了方便MyBatis注入
sharding.jdbc.config.masterslave.name=dataSource
# 管理主庫連接池
sharding.jdbc.config.masterslave.master-data-source-name=master
# 管理從庫連接池
sharding.jdbc.config.masterslave.slave-data-source-names=slave
# 從庫負載均衡算法類型:round_robin(輪詢),random(隨機)
sharding.jdbc.config.masterslave.load-balance-algorithm-type=round_robin

# 打印日誌
sharding.jdbc.config.props.sql.show=true

mapper

/**
 * 這裏寫的employee表是數據庫中的真實表
 */
@Mapper
public interface EmployeeMapper {
    @Select("select * from employee")
    List<Employee> selectAll();

    @Insert("insert into employee (name) values (#{name})")
    void inser(Employee entity);
}

測試

跟上面的完全一致,直接運行然後看效果即可

優缺點

  • 增加冗餘
  • 增加了機器的處理能力
  • 對於讀操作爲主的應用,使用讀寫分離是最好的場景,因爲可以確保寫的服務器壓力更小,而讀又可以接受點時間上的延遲

分庫分表 + 讀寫分離

案例模型

做數據分片 + 讀寫分離,最少需要2主2從,然後再結合前面講過的數據分片

application.properties

# 數據分片 + 讀寫分離
sharding.jdbc.datasource.names=master0,master0Slave,master1,master1Slave

sharding.jdbc.datasource.master0.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.master0.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.master0.url=jdbc:mysql://master0Ip:port/sharing
sharding.jdbc.datasource.master0.username=xxx
sharding.jdbc.datasource.master0.password=xxx

sharding.jdbc.datasource.master0Slave.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.master0Slave.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.master0Slave.url=jdbc:mysql://master0Ip:port/sharing
sharding.jdbc.datasource.master0Slave.username=xxx
sharding.jdbc.datasource.master0Slave.password=xxx

sharding.jdbc.datasource.master1.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.master1.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.master1.url=jdbc:mysql://master1Ip:port/sharing
sharding.jdbc.datasource.master1.username=xxx
sharding.jdbc.datasource.master1.password=xxx

sharding.jdbc.datasource.master1Slave.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.master1Slave.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.master1Slave.url=jdbc:mysql://master1SlaveIp:port/sharing
sharding.jdbc.datasource.master1Slave.username=xxx
sharding.jdbc.datasource.master1Slave.password=xxx

# 分庫規則
sharding.jdbc.config.sharding.default-database-strategy.inline.sharding-column=id
sharding.jdbc.config.sharding.default-database-strategy.inline.algorithm-expression=master$->{id % 2}

# 綁定邏輯表
sharding.jdbc.config.sharding.binding-tables=employee
# 分表規則
sharding.jdbc.config.sharding.tables.employee.actual-data-nodes=db$->{0..1}.employee_$->{0..1}
sharding.jdbc.config.sharding.tables.employee.table-strategy.inline.sharding-column=id
sharding.jdbc.config.sharding.tables.employee.table-strategy.inline.algorithm-expression=employee_$->{id % 2}
sharding.jdbc.config.sharding.tables.employee.key-generator-column-name=id

# 管理主從連接池
sharding.jdbc.config.sharding.master-slave-rules.db0.master-data-source-name=master0
sharding.jdbc.config.sharding.master-slave-rules.db0.slave-data-source-names=master0slave
sharding.jdbc.config.sharding.master-slave-rules.db1.master-data-source-name=master1
sharding.jdbc.config.sharding.master-slave-rules.db1.slave-data-source-names=master1slave

mapper

/**
 * 這裏寫的employee表是邏輯表
 */
@Mapper
public interface EmployeeMapper {
    @Select("select * from employee")
    List<Employee> selectAll();

    @Insert("insert into employee (name) values (#{name})")
    void inser(Employee entity);
}

測試

跟上面的完全一致,直接運行然後看效果即可

===============================================

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章