Sharding JDBC-分庫分表

本文作者:梁開權颠毙,叩丁狼高級講師顺囊。原創(chuàng)文章肌索,轉載請注明出處。

環(huán)境準備

pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.3.RELEASE</version>
</parent>

<properties>
    <java.version>1.8</java.version>
    <sharding.version>3.1.0</sharding.version>
</properties>

<dependencies>
    <dependency>
        <groupId>io.shardingsphere</groupId>
        <artifactId>sharding-jdbc-core</artifactId>
        <version>${sharding.version}</version>
    </dependency>

    <dependency>
        <groupId>io.shardingsphere</groupId>
        <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
        <version>${sharding.version}</version>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.10</version>
    </dependency>

    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>

    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.3.1</version>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.46</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

domain

// 建立domain
@Setter@Getter@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
    private Long id;
    private String name;
}

配置類

@SpringBootApplication
@MapperScan("cn.wolfcode.sharding.mapper")
public class ShardingApplication { }

分庫分表

案例模型

把數(shù)據(jù)分別存放在兩臺服務器的兩個數(shù)據(jù)庫中表特碳,通過分片算法來決定當前的數(shù)據(jù)存放在哪個數(shù)據(jù)庫的哪個表中诚亚,由于一個連接池只能連接一個特定的數(shù)據(jù)庫,所以這里需要創(chuàng)建多個連接池對象

建表

-- 分別在2臺服務器中建立數(shù)據(jù)庫sharding午乓,并且建表employee_0和employee_1
CREATE TABLE `employee_0` (
  `id` bigint(20) PRIMARY KEY AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ###################################
CREATE TABLE `employee_1` (
  `id` bigint(20) PRIMARY KEY AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

application.properties

# 定義連接池
sharding.jdbc.datasource.names=db0,db1

# 格式sharding.jdbc.datasource.連接池名.xxx:設置4要素信息
sharding.jdbc.datasource.db0.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.db0.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.db0.url=jdbc:mysql://db0Ip:port/sharing
sharding.jdbc.datasource.db0.username=xxx
sharding.jdbc.datasource.db0.password=xxx

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

# 設置分庫規(guī)則
# sharding.jdbc.config.sharding.default-database-strategy.inline.sharding-column:分庫列
# sharding.jdbc.config.sharding.default-database-strategy.inline.algorithm-expression:分庫算法
sharding.jdbc.config.sharding.default-database-strategy.inline.sharding-column=id
sharding.jdbc.config.sharding.default-database-strategy.inline.algorithm-expression=db$->{id % 2}

# 綁定邏輯表
sharding.jdbc.config.sharding.binding-tables=employee

# 設置分表規(guī)則
# sharding.jdbc.config.sharding.tables.邏輯表.actual-data-nodes:邏輯表對應的真實表
# sharding.jdbc.config.sharding.tables.邏輯表.table-strategy.inline.sharding-column:分表列
# sharding.jdbc.config.sharding.tables.邏輯表.table-strategy.inline.algorithm-expression:分表算法
# sharding.jdbc.config.sharding.tables.邏輯表.key-generator-column-name:主鍵列
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.props.sql.show=true

mapper

/**
 * 這里寫的employee表是上面所配置的邏輯表
 * 底層會根據(jù)分片規(guī)則站宗,把我們寫的邏輯表改寫為數(shù)據(jù)庫中的真實表
 */
@Mapper
public interface EmployeeMapper {
    @Select("select * from employee")
    List<Employee> selectAll();

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

測試

@RunWith(SpringRunner.class)
@SpringBootTest(classes=ShardingApplication.class)
public class ShardingApplicationTests {

    @Autowired
    private EmployeeMapper employeeMapper;

    @Test
    public void save() {
        for (int i = 0; i < 10; i++) {
            Employee employee = new Employee();
            employee.setName("xx"+i);
            employeeMapper.inser(employee);
        }
    }

    @Test
    public void list() {
        employeeMapper.selectAll().forEach(System.out::println);
    }
}

優(yōu)缺點

  • 拆分后單表數(shù)據(jù)量比較小,單表大數(shù)據(jù)被拆分,解決了單表大數(shù)據(jù)訪問問題
  • 分表以什么切分如果弄的不好,導致多次查詢,而且有時候要跨庫操作,甚至導致join無法使用,對排序分組等有性能影響
  • 之前的原子操作被拆分成多個操作,事務處理變得復雜
  • 多個DB維護成本增加
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市益愈,隨后出現(xiàn)的幾起案子梢灭,更是在濱河造成了極大的恐慌,老刑警劉巖蒸其,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件敏释,死亡現(xiàn)場離奇詭異,居然都是意外死亡摸袁,警方通過查閱死者的電腦和手機钥顽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來靠汁,“玉大人蜂大,你說我怎么就攤上這事闽铐。” “怎么了奶浦?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵兄墅,是天一觀的道長。 經常有香客問我财喳,道長,這世上最難降的妖魔是什么斩狱? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任耳高,我火速辦了婚禮,結果婚禮上所踊,老公的妹妹穿的比我還像新娘泌枪。我一直安慰自己,他們只是感情好秕岛,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布碌燕。 她就那樣靜靜地躺著,像睡著了一般继薛。 火紅的嫁衣襯著肌膚如雪修壕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天遏考,我揣著相機與錄音慈鸠,去河邊找鬼。 笑死灌具,一個胖子當著我的面吹牛青团,可吹牛的內容都是我干的。 我是一名探鬼主播咖楣,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼督笆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了诱贿?” 一聲冷哼從身側響起娃肿,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎珠十,沒想到半個月后咸作,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡宵睦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年记罚,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壳嚎。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡桐智,死狀恐怖末早,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情说庭,我是刑警寧澤然磷,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站刊驴,受9級特大地震影響姿搜,放射性物質發(fā)生泄漏。R本人自食惡果不足惜捆憎,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一舅柜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧躲惰,春花似錦致份、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至诡宗,卻和暖如春滔蝉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背塔沃。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工锰提, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人芳悲。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓立肘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親名扛。 傳聞我的和親對象是個殘疾皇子谅年,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內容