需求:mysql
分庫:按業務線business_id將不一樣業務線的訂單存儲在不一樣的數據庫上;算法
分表:按user_id字段將不一樣用戶的訂單存儲在不一樣的表上,爲方便直接用非分片字段order_id查詢,可以使用基因法;spring
讀寫分離:爲緩解主庫的壓力,讀操做訪問從庫;sql
-- 主庫 CREATE DATABASE `database_103`; CREATE DATABASE `database_112`; -- 從庫 CREATE DATABASE `database_slave_103`; CREATE DATABASE `database_slave_112`; --每一個庫上分別創建以下表 CREATE TABLE `t_order_0` ( `id` bigint(20) NOT NULL, `order_id` bigint(20) NOT NULL, `user_id` bigint(20) NOT NULL, `business_id` bigint(20) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `t_order_1` ( `id` bigint(20) NOT NULL, `order_id` bigint(20) NOT NULL, `user_id` bigint(20) NOT NULL, `business_id` bigint(20) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `t_order_2` ( `id` bigint(20) NOT NULL, `order_id` bigint(20) NOT NULL, `user_id` bigint(20) NOT NULL, `business_id` bigint(20) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `t_order` VALUES (1,1,112); CREATE TABLE `t_order_3` ( `id` bigint(20) NOT NULL, `order_id` bigint(20) NOT NULL, `user_id` bigint(20) NOT NULL, `business_id` bigint(20) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:rdb="http://www.dangdang.com/schema/ddframe/rdb" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.dangdang.com/schema/ddframe/rdb http://www.dangdang.com/schema/ddframe/rdb/rdb.xsd"> <bean id="database_112" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="${jdbc.url.112}"></property> <property name="username" value="${jdbc.username.112}"></property> <property name="password" value="${jdbc.password.112}"></property> <property name="maxActive" value="100"/> <property name="initialSize" value="50"/> <property name="maxWait" value="60000"/> <property name="minIdle" value="5"/> </bean> <bean id="database_slave_112" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="${jdbc.url.slave.112}"></property> <property name="username" value="${jdbc.username.slave.112}"></property> <property name="password" value="${jdbc.password.slave.112}"></property> <property name="maxActive" value="100"/> <property name="initialSize" value="50"/> <property name="maxWait" value="60000"/> <property name="minIdle" value="5"/> </bean> <bean id="database_103" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="${jdbc.url.103}"></property> <property name="username" value="${jdbc.username.103}"></property> <property name="password" value="${jdbc.password.103}"></property> <property name="maxActive" value="100"/> <property name="initialSize" value="50"/> <property name="maxWait" value="60000"/> <property name="minIdle" value="5"/> </bean> <bean id="database_slave_103" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="${jdbc.url.slave.103}"></property> <property name="username" value="${jdbc.username.slave.103}"></property> <property name="password" value="${jdbc.password.slave.103}"></property> <property name="maxActive" value="100"/> <property name="initialSize" value="50"/> <property name="maxWait" value="60000"/> <property name="minIdle" value="5"/> </bean> <!--mybatis--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="mapperLocations" value="classpath:xmlmapper/*.xml"/> <property name="dataSource" ref="shardingDataSource"/> <!-- 配置Mybatis配置文件 --> <property name="configLocation" value="classpath:/mybatis/mybatis-config.xml"/> </bean> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean> <!-- 註解Mapper scanner --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.lc.sharding.mybatismapper"/> <property name="sqlSessionTemplateBeanName" value="sqlSession"/> </bean> <!-- 事務--> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="shardingDataSource"/> </bean> <tx:annotation-driven transaction-manager="txManager"/> <!--讀寫分離--> <rdb:master-slave-data-source id="rbb_112" master-data-source-ref="database_112" slave-data-sources-ref="database_slave_112"/> <rdb:master-slave-data-source id="rbb_103" master-data-source-ref="database_103" slave-data-sources-ref="database_slave_103"/> <!--分庫策略--> <rdb:strategy id="databaseShardingStrategy" sharding-columns="business_id" algorithm-expression="rbb_${business_id.longValue()}"/> <!--分表策略--> <rdb:strategy id="tableShardingStrategy" sharding-columns="user_id,order_id" algorithm-class="com.lc.sharding.algorithm.MultipleKeysTableShardingAlgorithmImpl"/> <rdb:data-source id="shardingDataSource"> <rdb:sharding-rule data-sources="rbb_112,rbb_103"> <rdb:table-rules> <rdb:table-rule logic-table="t_order" actual-tables="t_order_${0..3}" database-strategy="databaseShardingStrategy" table-strategy="tableShardingStrategy"/> </rdb:table-rules> </rdb:sharding-rule> <rdb:props> <prop key="metrics.enable">true</prop> <prop key="sql.show">true</prop> </rdb:props> </rdb:data-source> </beans
public class MultipleKeysTableShardingAlgorithmImpl implements MultipleKeysTableShardingAlgorithm { public Collection<String> doSharding(Collection<String> tableNames, Collection<ShardingValue<?>> shardingValues) { List<String> shardingSuffix = new ArrayList<String>(); long partId = 0; for (ShardingValue value : shardingValues) { if (value.getColumnName().equals("user_id")) { partId = ((Long) value.getValue()) % 4; break; } else if (value.getColumnName().equals("order_id")) { partId = ((Long) value.getValue()) % 4; break; } } for (String name : tableNames) { if (name.endsWith(partId + "")) { shardingSuffix.add(name); return shardingSuffix; } } return shardingSuffix; } }
什麼是基因法分片?數據庫
在訂單數據oid生成時,order_id末端加入分片基因,讓同一個user_id下的全部訂單都含有相同基因,落在同一個表上。express
資料:https://mp.weixin.qq.com/s/PCzRAZa9n4aJwHOX-kAhtAmybatis
public long bulidOrderId(long userId) { //取用戶id後4位 userId = userId & 15; //先取60位惟一id long uniqueId = this.nextId(); //惟一id左移4位、拼接userId後4位 return (uniqueId << 4) | userId; }
this.nextId();//使用雪花算法生成60位分佈式惟一id:1位符號位+41位時間戳+5位workId+5位datacenterId+6位序列號+4位基因片
數據分片:app
讀寫分離:分佈式
柔性事務:ui
分佈式治理:
引用:http://shardingsphere.io/