利用ShardingSphere-JDBC实现分库分表

1. ShardingSphere概述

1.1 概述

业务发展到一定程度,分库分表是一种必然的要求,分库可以实现资源隔离,分表则可以降低单表数据量,提高访问效率。

分库分表的技术方案,很久以来都有两种理念:

  • 集中式的Proxy,实现MySQL客户端协议,使用户无感知
  • 分布式的Proxy,在代码层面进行增强,实现一个路由程序

这两种方式是各有利弊的,集中式Proxy的好处是业务没有感知,一切交给DBA把控,分布式的Proxy其支持的语言有限,比如本文要提及的ShardingShpere-JDBC就只支持Java。

我们需要了解一点,集中式的Proxy其实现非常复杂,这要从MySQL处理SQL语句的原理说起,因为不是本文要论述的重点,因此只是简单的提及几点:

  1. SQL语句要被Parser解析成抽象语法树
  2. SQL要被优化器解析出执行计划
  3. SQL语句完成解析后,发给存储引擎

因此大部分的中间件都选择了自己实现SQL的解析器和查询优化器,下面是著名的中间件dble的实现示意图:

只要有解析的过程,其性能损耗就是比较可观的,我们也可以认为这是一种重量级的解决方案。

与之形成对比的是ShardingSphere-JDBC,其原理示意图如下:

每一个服务都持有一个Sharing-JDBC,这个JDBC以Jar包的形式提供,基本上可以认为是一个增强版的jdbc驱动,需要一些分库分表的配置,业务开发人员不需要去对代码进行任何的修改。可以很轻松的移植到SpringBoot,ORM等框架上。

但是这个中结构也不是完美的,每一个服务持有一个proxy意味着会在MySQL服务端新建大量的连接,维持连接会增加MySQL服务器的负载,虽然这种负载提升一般无法察觉。

1.2 概念

逻辑表
**
即水平拆分的表的总称。比如订单业务会被拆分成t_order0,t_order1两张表,但是他们同属于一个逻辑表:t_order

绑定表

分片规则一直的主表和子表。比如还是上面的t_order表,其分片键是order_id,其子表t_order_item的分片键也是order_id。在规则配置时将两个表配置成绑定关系,就不会在查询时出现笛卡尔积。

在关联查询时,如果没有绑定关系,则t_order和t_order_item的关联会出现这样一种场景:

  1. select * from t_order0 inner join t_order_item0 on order_id = order_id where order_id in (0, 1);
  2. select * from t_order0 inner join t_order_item1 on order_id = order_id where order_id in (0, 1;
  3. select * from t_order1 inner join t_order_item0 on order_id = order_id where order_id in (0, 1;
  4. select * from t_order1 inner join t_order_item1 on order_id = order_id where order_id in (0, 1;

如果配置了绑定关系,则会精确地定位到order_id所在的表,消除笛卡尔积。

广播表

有一些表是没有分片的必要的,比如省份信息表,全国也就30多条数据,这种表在每一个节点上都是一样的,这种表叫做广播表。

2. 利用SpringBoot实现分库分表

要分库分表首先需要有不同的数据源,我们启动两个mysqld进行,监听3306和3307两个端口,以多实例的形式模拟多数据源。

我们的分库是以用户ID为依据的,分表是以表本身的主键为依据的。下面是一张示意表:

  1. -- 注意,这是逻辑表,实际不存在
  2. create table t_order
  3. (
  4. order_id bigint not null auto_increment primary key,
  5. user_id bigint not null,
  6. name varchar(100)
  7. );
  8. CREATE TABLE `t_order_item` (
  9. `order_id` bigint(20) NOT NULL,
  10. `item` varchar(100) DEFAULT NULL,
  11. `user_id` bigint(20) NOT NULL,
  12. PRIMARY KEY (`order_id`)
  13. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我现在有两个数据源,每个数据源上根据order_id分成2两表,也就是说每个实例上都应该有这两张表:

  1. create table t_order0
  2. (
  3. order_id bigint not null auto_increment primary key,
  4. user_id bigint not null,
  5. name varchar(100)
  6. );
  7. create table t_order1
  8. (
  9. order_id bigint not null auto_increment primary key,
  10. user_id bigint not null,
  11. name varchar(100)
  12. );
  13. -- 这是广播表,新建在其中一个节点上就可以
  14. CREATE TABLE `t_config` (
  15. `id` int(11) NOT NULL AUTO_INCREMENT,
  16. `user_id` bigint(20) DEFAULT NULL,
  17. `config` varchar(100) DEFAULT NULL,
  18. PRIMARY KEY (`id`)
  19. ) ENGINE=InnoDB;
  20. CREATE TABLE `t_order_item0` (
  21. `order_id` bigint(20) NOT NULL,
  22. `item` varchar(100) DEFAULT NULL,
  23. `user_id` bigint(20) NOT NULL,
  24. PRIMARY KEY (`order_id`)
  25. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  26. CREATE TABLE `t_order_item1` (
  27. `order_id` bigint(20) NOT NULL,
  28. `item` varchar(100) DEFAULT NULL,
  29. `user_id` bigint(20) NOT NULL,
  30. PRIMARY KEY (`order_id`)
  31. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

利用SpringBoot技术可以很快的构建一个RESTful的Web服务,下面是application.properties的内容:

  1. # 这里要注册所有的数据源
  2. spring.shardingsphere.datasource.names=ds0,ds1
  3. # 这是数据源0的配置
  4. spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
  5. spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8
  6. spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
  7. spring.shardingsphere.datasource.ds0.username=root
  8. spring.shardingsphere.datasource.ds0.password=
  9. # 这是数据源1的配置
  10. spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
  11. spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://localhost:3307/test?serverTimezone=GMT%2B8
  12. spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
  13. spring.shardingsphere.datasource.ds1.username=root
  14. spring.shardingsphere.datasource.ds1.password=
  15. # 分库策略
  16. # 分库的列是user_id
  17. spring.shardingsphere.sharding.default-database-strategy.standard.sharding-column=user_id
  18. spring.shardingsphere.sharding.default-database-strategy.standard.precise-algorithm-class-name=com.sinosun.demo.sharding.PreciseShardingAlgorithmImpl
  19. # 分表策略
  20. spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds$->{0..1}.t_order$->{0..1}
  21. spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
  22. spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order$->{order_id % 2}
  23. spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
  24. spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
  25. spring.shardingsphere.sharding.tables.t_order_item.actual-data-nodes=ds$->{0..1}.t_order_item$->{0..1}
  26. spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.sharding-column=order_id
  27. spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.algorithm-expression=t_order_item$->{order_id % 2}
  28. spring.shardingsphere.sharding.binding-tables=t_order, t_order_item
  29. # 广播表, 其主节点是ds0
  30. spring.shardingsphere.sharding.broadcast-tables=t_config
  31. spring.shardingsphere.sharding.tables.t_config.actual-data-nodes=ds$->{0}.t_config
  32. spring.jpa.show-sql=true
  33. server.address=10.1.20.96
  34. server.port=8080

这是buid.gradle内容,只列举ShardingSphere相关的:

  1. dependencies {
  2. compile group: 'org.apache.shardingsphere', name: 'sharding-jdbc-spring-boot-starter', version: '4.0.0-RC1'
  3. compile group: 'org.apache.shardingsphere', name: 'sharding-jdbc-spring-namespace', version: '4.0.0-RC1'
  4. }

下图是工程的代码结构,供参考:

现在开始列举代码:

Order.java:
**

  1. package com.example.demo.entity;
  2. import javax.persistence.Column;
  3. import javax.persistence.Entity;
  4. import javax.persistence.GeneratedValue;
  5. import javax.persistence.GenerationType;
  6. import javax.persistence.Id;
  7. import javax.persistence.Table;
  8. import java.util.StringJoiner;
  9. @Entity
  10. @Table(name = "t_order")
  11. public class Order {
  12. @Id
  13. @GeneratedValue(strategy = GenerationType.IDENTITY)
  14. private long orderId;
  15. @Column(name = "user_id")
  16. private long userId;
  17. @Column(name = "name")
  18. private String name;
  19. public long getOrderId() {
  20. return orderId;
  21. }
  22. public void setOrderId(long orderId) {
  23. this.orderId = orderId;
  24. }
  25. public String getName() {
  26. return name;
  27. }
  28. public void setName(String name) {
  29. this.name = name;
  30. }
  31. public long getUserId() {
  32. return userId;
  33. }
  34. public void setUserId(long userId) {
  35. this.userId = userId;
  36. }
  37. @Override
  38. public String toString() {
  39. return new StringJoiner(", ", Order.class.getSimpleName() + "[", "]")
  40. .add("orderId=" + orderId)
  41. .add("userId=" + userId)
  42. .add("name='" + name + "'")
  43. .toString();
  44. }
  45. }

OrderItem.java:
**

  1. package com.example.demo.entity;
  2. import com.google.common.base.MoreObjects;
  3. import javax.persistence.Column;
  4. import javax.persistence.Entity;
  5. import javax.persistence.Id;
  6. import javax.persistence.Table;
  7. @Entity
  8. @Table(name = "t_order_item")
  9. public class OrderItem {
  10. @Id
  11. @Column(name = "order_id")
  12. private long orderId;
  13. @Column(name = "user_id")
  14. private long userId;
  15. @Column(name = "item")
  16. private String item;
  17. public long getOrderId() {
  18. return orderId;
  19. }
  20. public void setOrderId(long orderId) {
  21. this.orderId = orderId;
  22. }
  23. public long getUserId() {
  24. return userId;
  25. }
  26. public void setUserId(long userId) {
  27. this.userId = userId;
  28. }
  29. public String getItem() {
  30. return item;
  31. }
  32. public void setItem(String item) {
  33. this.item = item;
  34. }
  35. @Override
  36. public String toString() {
  37. return MoreObjects.toStringHelper(this)
  38. .add("orderId", orderId)
  39. .add("userId", userId)
  40. .add("item", item)
  41. .toString();
  42. }
  43. }

TConfig.java:
**

  1. package com.example.demo.entity;
  2. import com.google.common.base.MoreObjects;
  3. import javax.persistence.Column;
  4. import javax.persistence.Entity;
  5. import javax.persistence.GeneratedValue;
  6. import javax.persistence.GenerationType;
  7. import javax.persistence.Id;
  8. import javax.persistence.Table;
  9. @Entity
  10. @Table(name = "t_config")
  11. public class TConfig {
  12. @Id
  13. @GeneratedValue(strategy = GenerationType.IDENTITY)
  14. private int id;
  15. @Column(name = "user_id")
  16. private long userId;
  17. @Column(name = "config")
  18. private String config;
  19. public int getId() {
  20. return id;
  21. }
  22. public void setId(int id) {
  23. this.id = id;
  24. }
  25. public long getUserId() {
  26. return userId;
  27. }
  28. public void setUserId(long userId) {
  29. this.userId = userId;
  30. }
  31. public String getConfig() {
  32. return config;
  33. }
  34. public void setConfig(String config) {
  35. this.config = config;
  36. }
  37. @Override
  38. public String toString() {
  39. return MoreObjects.toStringHelper(this)
  40. .add("id", id)
  41. .add("userId", userId)
  42. .add("config", config)
  43. .toString();
  44. }
  45. }

OrderDao.java:
**

  1. package com.example.demo.dao;
  2. import com.example.demo.entity.Order;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. public interface OrderDao extends JpaRepository<Order, Long> {
  5. }

OrderItemDao.java:
**

  1. package com.example.demo.dao;
  2. import com.example.demo.entity.OrderItem;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. import org.springframework.data.jpa.repository.Query;
  5. import org.springframework.data.repository.query.Param;
  6. import java.util.Optional;
  7. public interface OrderItemDao extends JpaRepository<OrderItem, Long> {
  8. //为了测试绑定表
  9. @Query(value = "select n from Order t inner join OrderItem n on t.orderId = n.orderId where n.orderId=:orderId")
  10. Optional<OrderItem> getOrderItemByOrderId(@Param("orderId") Long orderId);
  11. }

ConfigDao.java:
**

  1. package com.example.demo.dao;
  2. import com.sinosun.demo.entity.TConfig;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. public interface ConfigDao extends JpaRepository<TConfig, Integer> {
  5. }

OrderController.java:
**

  1. package com.example.demo.controller;
  2. import com.example.demo.dao.OrderDao;
  3. import com.example.demo.entity.Order;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RequestMethod;
  7. import org.springframework.web.bind.annotation.RequestParam;
  8. import org.springframework.web.bind.annotation.RestController;
  9. import java.util.Optional;
  10. @RestController
  11. public class OrderController {
  12. @Autowired
  13. private OrderDao orderDao;
  14. @RequestMapping(value = "/order", method = RequestMethod.GET)
  15. public Optional<Order> getOrderById(@RequestParam("id") Long id) {
  16. return this.orderDao.findById(id);
  17. }
  18. @RequestMapping(value = "/order/save", method = RequestMethod.POST)
  19. public Order saveOrder(@RequestParam("name") String name, @RequestParam("userid") Long userId) {
  20. Order order = new Order();
  21. order.setName(name);
  22. order.setUserId(userId);
  23. return this.orderDao.save(order);
  24. }
  25. }

OrderItemController.java:
**

  1. package com.example.demo.controller;
  2. import com.example.demo.dao.OrderItemDao;
  3. import com.example.demo.entity.OrderItem;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RequestMethod;
  7. import org.springframework.web.bind.annotation.RequestParam;
  8. import org.springframework.web.bind.annotation.RestController;
  9. import java.util.Optional;
  10. @RestController
  11. public class OrderItemController {
  12. @Autowired
  13. private OrderItemDao orderItemDao;
  14. @RequestMapping(value = "/orderItem", method = RequestMethod.GET)
  15. public Optional<OrderItem> getOrderItemById(@RequestParam(name = "id") Long id) {
  16. return this.orderItemDao.findById(id);
  17. }
  18. @RequestMapping(value = "/orderItem/save", method = RequestMethod.POST)
  19. public OrderItem saveOrderItem(@RequestParam("item") String item, @RequestParam("userid") Long userId, @RequestParam("orderid") Long orderId) {
  20. OrderItem orderItem = new OrderItem();
  21. orderItem.setUserId(userId);
  22. orderItem.setItem(item);
  23. orderItem.setOrderId(orderId);
  24. return this.orderItemDao.save(orderItem);
  25. }
  26. @RequestMapping(value = "/orderItem/query", method = RequestMethod.GET)
  27. public Optional<OrderItem> getOrderItemByOrderId(@RequestParam(name = "orderid") Long orderId) {
  28. return this.orderItemDao.getOrderItemByOrderId(orderId);
  29. }
  30. }

ConfigController.java:
**

  1. package com.example.demo.controller;
  2. import com.example.demo.dao.ConfigDao;
  3. import com.example.demo.entity.TConfig;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RequestMethod;
  7. import org.springframework.web.bind.annotation.RestController;
  8. import java.util.List;
  9. @RestController
  10. public class ConfigController {
  11. @Autowired
  12. private ConfigDao configDao;
  13. @RequestMapping(value = "/listConfig", method = RequestMethod.GET)
  14. public List<TConfig> getConfig() {
  15. return this.configDao.findAll();
  16. }
  17. }

这三段代码写完基本的功能就完备了,但是刚才配置的时候提过,我们的目的是按照user_id进行分库,比如user_id=0则分配这条数据到ds0去,如果为1则将数据分配到ds1去,这就要求我们自己实现分库的算法,ShardingSphere提供了接口,只需要去实现就可以了:

  1. package com.example.demo.sharding;
  2. import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
  3. import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
  4. import java.util.Collection;
  5. public class PreciseShardingAlgorithmImpl implements PreciseShardingAlgorithm<Long> {
  6. @Override
  7. public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
  8. String dbName = "ds";
  9. Long val = shardingValue.getValue();
  10. dbName += val;
  11. for (String each : availableTargetNames) {
  12. if (each.equals(dbName)) {
  13. return each;
  14. }
  15. }
  16. throw new IllegalArgumentException();
  17. }
  18. }

这段代码很简单,其中有几个地方只需要讲明白了就可以。

  • availableTargetNames:这是datasource的名字列表,在这里应该是ds0和ds1;
  • shardingValue:这是分片列的值,我们只要其value部分就可以。

之后用一个循环遍历["ds0", "ds1"]集合,当我们的dbName和其中一个相等时,就能的到正确的数据源。这就简单的实现了根据user_id精确分配数据的目的。

这是实测例子中,shardingValue和availableTargetNames的实际值:

本次测试的请求是:

  1. curl -X POST \
  2. 'http://10.1.20.96:8080/order/save?name=LiLei&userid=0' \
  3. -H 'Postman-Token: d5e15e85-c760-4252-a7d4-ef57b5e95c2e' \
  4. -H 'cache-control: no-cache'

下面看看实际效果,这是ds0的数据:

这是ds1的数据:

可以看到,所有的数据都根据user_id分布到了不同的库中,所有的数据都根据order_id的奇偶分布到了不同的表中。

记录下保存t_order请求返回的order_id,组装一条POST请求写t_order_item表:

  1. curl -X POST \
  2. 'http://10.1.20.96:8080/orderItem/save?item=pen&userid=0&orderid=371698107924086785' \
  3. -H 'Accept: */*' \
  4. -H 'Cache-Control: no-cache' \
  5. -H 'Connection: keep-alive' \
  6. -H 'Host: 10.1.20.96:8080' \
  7. -H 'Postman-Token: 347b6c4d-0e2c-474f-b53e-6f0994db5871,24b362da-e77e-4b04-94e1-fa20dcb15845' \
  8. -H 'User-Agent: PostmanRuntime/7.15.0' \
  9. -H 'accept-encoding: gzip, deflate' \
  10. -H 'cache-control: no-cache' \
  11. -H 'content-length: '

得到结果如下:

使用这个order_id去进行联合查询:

  1. curl -X GET \
  2. 'http://10.1.20.96:8080/orderItem/query?orderid=371698107924086785' \
  3. -H 'Accept: */*' \
  4. -H 'Cache-Control: no-cache' \
  5. -H 'Connection: keep-alive' \
  6. -H 'Host: 10.1.20.96:8080' \
  7. -H 'Postman-Token: d0da0523-d46e-429f-a8db-9f844cd77fe6,b61c6089-253d-4535-b473-158c037850be' \
  8. -H 'User-Agent: PostmanRuntime/7.15.0' \
  9. -H 'accept-encoding: gzip, deflate' \
  10. -H 'cache-control: no-cache'

得到返回如下:

测试广播表,可以用下面的请求:

  1. curl -X GET \
  2. http://10.1.20.96:8080/listConfig \
  3. -H 'Accept: */*' \
  4. -H 'Cache-Control: no-cache' \
  5. -H 'Connection: keep-alive' \
  6. -H 'Host: 10.1.20.96:8080' \
  7. -H 'Postman-Token: 1c9d0349-4b6d-4a2c-834f-4e2f94194649,3dff68f4-2e10-4e96-926a-344faa5f0a19' \
  8. -H 'User-Agent: PostmanRuntime/7.15.0' \
  9. -H 'accept-encoding: gzip, deflate' \
  10. -H 'cache-control: no-cache'

得到的结果:

3. 利用SpringBoot实现读写分离

上一小节中展示了如何利用SharingSphere+SpringBoot进行数据的分片,这一小节着重描述一下如何进行读写分离,下一小节计划展示如何将读写分离和分片结合起来。

首先还是会利用多实例来模拟,为了简单,我没有配置复制,而是预置了几条数据进去,判断能否将读写请求分发到不同的节点上。

首先我们新建一张表:

  1. create table t_order
  2. (
  3. order_id bigint not null auto_increment primary key,
  4. user_id bigint not null,
  5. name varchar(100)
  6. );
  7. -- master
  8. insert into t_order(user_id, name) values (0, 'zhiquan');
  9. -- slave
  10. insert into t_order(user_id, name) values (1, 'LiLei');

我会配置slave为读数据源,那么读出的数据一定是user_id=1这一条。

数据是这样的,首先是master:

然后是slave:

接下来开始粘贴代码,首先是配置:

application.properties:
**

  1. spring.shardingsphere.datasource.names=ds0,ds1
  2. spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
  3. spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8
  4. spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
  5. spring.shardingsphere.datasource.ds0.username=root
  6. spring.shardingsphere.datasource.ds0.password=
  7. spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
  8. spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://localhost:3307/test?serverTimezone=GMT%2B8
  9. spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
  10. spring.shardingsphere.datasource.ds1.username=root
  11. spring.shardingsphere.datasource.ds1.password=
  12. spring.shardingsphere.masterslave.name=ms
  13. spring.shardingsphere.masterslave.master-data-source-name=ds0
  14. spring.shardingsphere.masterslave.slave-data-source-names=ds1
  15. server.port=8080
  16. spring.jpa.show-sql=true

具体的实现代码就不粘贴了,和之前的小节没有什么区别。下面开始测试,首先是一个GET请求:

  1. curl -X GET \
  2. 'http://localhost:8080/getOrder?orderId=2' \
  3. -H 'Accept: */*' \
  4. -H 'Accept-Encoding: gzip, deflate' \
  5. -H 'Cache-Control: no-cache' \
  6. -H 'Connection: keep-alive' \
  7. -H 'Host: localhost:8080' \
  8. -H 'Postman-Token: 028a4539-a727-47f2-8862-2eed637883d0,ffbe396f-5c33-4266-a00e-d2a0246283f3' \
  9. -H 'User-Agent: PostmanRuntime/7.15.2' \
  10. -H 'cache-control: no-cache'

如上图,和预期是一样的,读取到了slave上的数据,那么现在看看写操作:

  1. curl -X POST \
  2. 'http://localhost:8080/saveOrder?userId=123&name=HanMeimei' \
  3. -H 'Accept: */*' \
  4. -H 'Accept-Encoding: gzip, deflate' \
  5. -H 'Cache-Control: no-cache' \
  6. -H 'Connection: keep-alive' \
  7. -H 'Content-Length: ' \
  8. -H 'Host: localhost:8080' \
  9. -H 'Postman-Token: f0497259-a82a-4dcf-9849-3dcdae431742,77fd1308-b5e8-4882-be07-fa128e6efc4d' \
  10. -H 'User-Agent: PostmanRuntime/7.15.2' \
  11. -H 'cache-control: no-cache'

现在看看主节点的表:

如上图,这条数据已经成功的写入了master。

利用ShardingSphere-JDBC实现分库分表的更多相关文章

  1. 分库分表之ShardingSphere

    目录 分库分表诞生的前景 分库分表的方式(垂直拆分,水平复制) 1.垂直拆分 1.1 垂直分库 1.2 垂直分表 2.水平拆分 2.1 水平分库 2.2 水平分表 分库分库中间件 ShardingSp ...

  2. sharding-jdbc之——分库分表实例

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/79368021 一.概述 之前,我们介绍了利用Mycat进行分库分表操作,Mycat ...

  3. mycat+mysql集群:实现读写分离,分库分表

    1.mycat文档:https://github.com/MyCATApache/Mycat-doc       官方网站:http://www.mycat.org.cn/ 2.mycat的优点: 配 ...

  4. mysql 分库分表 ~ ShardingSphere生态圈

    一  简介   Apache ShardingSphere是一款开源的分布式数据库中间件组成的生态圈二 成员包含   Sharding-JDBC是一款轻量级的Java框架,在JDBC层提供上述核心功能 ...

  5. 分库分表利器——sharding-sphere

    背景 得不到的东西让你彻夜难眠,没有尝试过的技术让我跃跃欲试. 本着杀鸡焉用牛刀的准则,我们倡导够用就行,不跟风,不盲从. 所以,结果就是我们一直没有真正使用分库分表.曾经好几次,感觉没有分库分表(起 ...

  6. 利用ShardingSphere-JDBC实现分库分表--配置中心的实现

    在之前的文章中我详细描述了如何利用ShardingSphere-JDBC进行分库分表,同时也实现了简单的精确分库算法接口,详情见下面的链接: 利用ShardingSphere-JDBC实现分库分表 但 ...

  7. 分库分表(3) ---SpringBoot + ShardingSphere 实现读写分离

    分库分表(3)---ShardingSphere实现读写分离 有关ShardingSphere概念前面写了两篇博客: 1.分库分表(1) --- 理论 2. 分库分表(2) --- ShardingS ...

  8. 分库分表(4) ---SpringBoot + ShardingSphere 实现分表

    分库分表(4)--- ShardingSphere实现分表 有关分库分表前面写了三篇博客: 1.分库分表(1) --- 理论 2.分库分表(2) --- ShardingSphere(理论) 3.分库 ...

  9. 分库分表(5) ---SpringBoot + ShardingSphere 实现分库分表

    分库分表(5)--- ShardingSphere实现分库分表 有关分库分表前面写了四篇博客: 1.分库分表(1) --- 理论 2.分库分表(2) --- ShardingSphere(理论) 3. ...

随机推荐

  1. iconfontのsymbol的使用

    iconfontのsymbol的使用 iconfont三种方式的优缺点 unicode 优点: 1.兼容性最好,支持ie6+ 2.支持按字体的方式去动态调整图标大小,颜色等等 缺点: 1.不支持多色图 ...

  2. 判断list集合不为空

    在java开发中新手容易将判断一个list集合是否为空,只以If(list!=null)去判断,且容易和isEmpty()混淆,但是,list集合为空还是为null,是有区别的. 先看一下下面的例子, ...

  3. Kafka集群部署以及使用

    Kafka集群部署 部署步骤 hadoop102 hadoop103 hadoop104 zk zk zk kafka kafka kafka http://kafka.apache.org/down ...

  4. [小米OJ] 5. 找出旋转有序数列的中间值

    排序,输出 #include <bits/stdc++.h> using namespace std; int main() { string input; while (cin > ...

  5. Java EE.JavaBean

    JavaBean是一组可移植.可重用.并可以组装到应用程序中的Java类.一个Model类(属性+构造函数).

  6. 解读Android MediaPlayer 详细使用方法

        MediaPlayer具有非常强大的功能,对音视频的播放均提供了支持,为了保证播放期间系统的正常工作,需要设置"android.permission.WAKE_LOCK"权 ...

  7. [NLP] 相对位置编码(二) Relative Positional Encodings - Transformer-XL

    参考: 1. Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context https://arxiv.org/pdf ...

  8. GStreamer基础教程06 - 获取媒体信息

    摘要 在常见的媒体文件中,通常包含一些数据(例如:歌手,专辑,编码类型等),用于描述媒体文件.通常称这些数据为元数据(Metadata:data that provides information a ...

  9. poj2909 欧拉素数筛选

    刚刚学了一种新的素数筛选法,效率比原先的要高一些,据说当n趋近于无穷大时这个的时间复杂度趋近O(n).本人水平有限,无法证明. 这是道水题,贴代码出来重点是欧拉筛选法.我把原来普通的筛选法贴出来. / ...

  10. OI/ACM最全卡常大招

    NO.10: 循环展开: 在缓存和寄存器允许的情况下一条语句内大量的展开运算会刺激 CPU 并发(蛤?这是个什么原理,算了,反正写了没坏处就这么写吧) NO.9: 特殊运算优化:(或许这真的没用) 取 ...