提交 d8227795 编写于 作者: G gaohongtao 提交者: gaohongtao

update example and doc

上级 14a7e40a
......@@ -94,7 +94,7 @@ public final class ShardingRule {
*/
public Optional<TableRule> tryFindTableRule(final String logicTableName) {
for (TableRule each : tableRules) {
if (each.getLogicTable().equals(logicTableName)) {
if (each.getLogicTable().equalsIgnoreCase(logicTableName)) {
return Optional.of(each);
}
}
......
+++
date = "2016-11-16T15:07:10+08:00"
draft = false
title = "Id生成器"
weight = 13
+++
# 分布式Id生成器
## 实现动机
传统数据库软件开发中,主键自动生成技术是基本需求。而各大数据库对于该需求也提供了相应的支持,比如`MySQL`的自增键。
对于`MySQL`而言,分库分表之后,不同表生成全局唯一的Id是非常棘手的问题。因为同一个逻辑表内的不同实际表之间的自增键是无法互相感知的,
这样会造成重复Id的生成。我们当然可以通过约束表生成键的规则来达到数据的不重复,但是这需要引入额外的运维力量来解决重复性问题,并使框架缺乏扩展性。
目前有许多第三方解决方案可以完美解决这个问题,比如UUID等依靠特定算法自生成不重复键,或者通过引入Id生成服务等。
但也正因为这种多样性导致了`Sharding-JDBC`如果强依赖于任何一种方案就会限制其自身的发展。
基于以上的原因,最终采用了以`JDBC`接口来实现对于生成Id的访问,而将底层具体的Id生成实现分离出来.
## 使用方法
使用方法分为设置自动生成键和获取生成键两部分
### 设置自动生成键
配置自增列:
```java
TableRule.builder("t_order").autoIncrementColumns("order_id");
```
设置Id生成器的实现类,该类必须实现`com.dangdang.ddframe.rdb.sharding.id.generator.IdGenerator`接口。
配置全局生成器(`com.x.x.AIdGenerator`):
```java
ShardingRule.builder().idGenerator(com.x.x.AIdGenerator.class);
```
有时候我们希望部分表的Id生成器与全局Id生成器不同,比如`t_order_item`表希望使用`com.x.x.BIdGenerator`来生成Id:
```java
TableRule.builder("t_order_item").autoIncrementColumns("order_item_id", com.x.x.BIdGenerator.class);
```
这样`t_order`就使用`com.x.x.AIdGenerator`生成Id,而`t_order_item`使用`com.x.x.BIdGenerator`生成Id。
### 获取自动生成键
通过`JDBC`提供的API来获取。对于Statement来说调用```statement.execute("INSERT ...", Statement.RETURN_GENERATED_KEYS)```
来通知需要返回的生成的键值。对于PreparedStatement则是```connection.prepareStatement("INSERT ...", Statement.RETURN_GENERATED_KEYS)```
调用```statement.getGeneratedKeys()```来获取键值的`ResultSet`
### 其他框架配置
关于`Spring``Yaml``MyBatis``JPA``Hibernate`)的配置请参考
[示例工程](https://github.com/dangdangdotcom/sharding-jdbc/tree/master/sharding-jdbc-example)
# 通用的分布式Id生成器
需要引入以下依赖
```xml
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-self-id-generator</artifactId>
<version>${sharding-jdbc.version}</version>
</dependency>
```
类名称:`com.dangdang.ddframe.rdb.sharding.id.generator.self.CommonSelfIdGenerator`
该生成器作为默认的生成器实现提供,生成的数据为64bit的long型数据。
在数据库中应该用大于等于64bit的数字类型的字段来保存该值,比如在`MySQL`中应该使用`BIGINT`
其二进制表示形式包含四部分,从高位到低位分表为:1bit符号位(为0),41bit时间位,10bit工作进程位,12bit序列位。
## 时间位(41bit)
从2016年11月1日零点到现在的毫秒数
## 工作进程位(10bit)
该标志在Java进程内是唯一的,如果是分布式应用部署应保证每个进程的工作进程Id是不同的。该值默认为0,目前可以通过三种方式设置。
1. 调用静态方法`CommonSelfIdGenerator.setWorkerId("xxxx")`设置。
1. 设置Java的系统变量,也就是再启动命令行中设置`-Dsjdbc.self.id.generator.worker.id=xxx`设置。
1. 设置系统环境变量,通过`SJDBC_SELF_ID_GENERATOR_WORKER_ID=xxx`设置。
## 序列位(12bit)
该序列是用来在同一个毫秒内生成不同的Id。如果在这个毫秒内生成的数量超过4096(2的12次方),那么生成器会等待到下个毫秒继续生成。
## 总结
从Id的组成部分看,不同进程的Id肯定是不同的,同一个进程首先是通过时间位保证不重复,如果时间相同则是通过序列位保证。
同时由于时间位是单调递增的,且各个服务器如果大体做了时间同步,那么生成的Id在分布式环境可以认为是总体有序的。
这就保证了对索引字段的插入的高效性。例如`MySQL``Innodb`存储引擎的主键。
\ No newline at end of file
......@@ -10,14 +10,22 @@ weight = 1
# Release Notes
## 1.4.0-SNAPSHOT
### 功能提升
1. 自动生成键实现,包含
[ISSUE #162](https://github.com/dangdangdotcom/sharding-jdbc/issues/162)
[ISSUE #163](https://github.com/dangdangdotcom/sharding-jdbc/issues/163)
[ISSUE #171](https://github.com/dangdangdotcom/sharding-jdbc/issues/171)
[ISSUE #172](https://github.com/dangdangdotcom/sharding-jdbc/issues/172)
## 1.3.3
### 缺陷修正
1. [ISSUE #166](https://github.com/dangdangdotcom/sharding-jdbc/issues/166) druid数据源stat过滤器多线程报错
## 1.3.3
### 功能提升
1. [ISSUE #59](https://github.com/dangdangdotcom/sharding-jdbc/issues/59) PreparedStatement设置参数时可以根据参数类型调用正确的底层set方法
......
......@@ -14,7 +14,7 @@
<link href="{{ .Site.BaseURL }}css/landing-page.css" rel="stylesheet">
<!-- Custom Fonts -->
<link href='http://fonts.useso.com/css?family=Open+Sans:300,400,600&subset=latin,latin-ext' rel='stylesheet'>
<!--<link href='http://fonts.useso.com/css?family=Open+Sans:300,400,600&subset=latin,latin-ext' rel='stylesheet'>-->
<style>
{{ printf "%v" (partial "template.css" . ) | safeCSS }}
......
......@@ -63,6 +63,11 @@
<artifactId>sharding-jdbc-config-spring</artifactId>
<version>${sharding-jdbc.version}</version>
</dependency>
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-self-id-generator</artifactId>
<version>${sharding-jdbc.version}</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
......
......@@ -15,12 +15,16 @@ dataSource:
username: root
password:
idGeneratorClass: com.dangdang.ddframe.rdb.sharding.id.generator.self.CommonSelfIdGenerator
tables:
t_config:
actualTables: ds_config.t_config
t_order:
actualTables: ds_${0..1}.t_order_${0..1}
autoIncrementColumns:
order_id:
tableStrategy:
shardingColumns: order_id
algorithmExpression: t_order_${order_id.longValue() % 2}
......
......@@ -2,17 +2,17 @@ CREATE SCHEMA IF NOT EXISTS `ds_config`;
CREATE SCHEMA IF NOT EXISTS `ds_0`;
CREATE SCHEMA IF NOT EXISTS `ds_1`;
CREATE TABLE IF NOT EXISTS `ds_config`.`t_config`(`id` INT NOT NULL, `name` VARCHAR(20), `value` VARCHAR(50));
CREATE TABLE IF NOT EXISTS `ds_config`.`t_config`(`id` BIGINT NOT NULL, `name` VARCHAR(20), `value` VARCHAR(50));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_0` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_1` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_item_0` (`item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_item_1` (`item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_0` (`order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_1` (`order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_item_0` (`item_id` BIGINT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_item_1` (`item_id` BIGINT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_0` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_1` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_item_0` (`item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_item_1` (`item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_0` (`order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_1` (`order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_item_0` (`item_id` BIGINT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_item_1` (`item_id` BIGINT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
INSERT INTO `ds_config`.`t_config` VALUES (1, 'config_key', 'config_value');
......
......@@ -17,10 +17,13 @@
package com.dangdang.ddframe.rdb.sharding.example.jdbc;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.dangdang.ddframe.rdb.sharding.example.jdbc.entity.Order;
import com.dangdang.ddframe.rdb.sharding.example.jdbc.repository.OrderRepository;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.ArrayList;
import java.util.List;
// CHECKSTYLE:OFF
public final class Main {
......@@ -37,17 +40,18 @@ public final class Main {
System.out.println(orderRepository.selectOrderBy());
System.out.println("--------------");
for (int i = 10000; i < 10010; i++) {
List<Long> orderIds = new ArrayList<>(10);
for (int i = 0; i < 10; i++) {
Order order = new Order();
order.setOrderId(i);
order.setUserId(51);
order.setStatus("INSERT_TEST");
orderRepository.create(order);
System.out.println(orderRepository.selectById(i));
orderIds.add(order.getOrderId());
System.out.println(orderRepository.selectById(order.getOrderId()));
System.out.println("--------------");
order.setStatus("UPDATE_TEST");
orderRepository.update(order);
System.out.println(orderRepository.selectById(i));
System.out.println(orderRepository.selectById(order.getOrderId()));
System.out.println("--------------");
}
......@@ -57,8 +61,8 @@ public final class Main {
System.out.println(orderRepository.selectOrderBy());
System.out.println("--------------");
for (int i = 10000; i < 10010; i++) {
orderRepository.delete(i);
for (Long each : orderIds) {
orderRepository.delete(each);
}
applicationContext.close();
}
......
......@@ -17,17 +17,17 @@
package com.dangdang.ddframe.rdb.sharding.example.jdbc.algorithm;
import java.util.Collection;
import java.util.LinkedHashSet;
import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.SingleKeyTableShardingAlgorithm;
import com.google.common.collect.Range;
public final class SingleKeyModuloTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Integer> {
import java.util.Collection;
import java.util.LinkedHashSet;
public final class SingleKeyModuloTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Long> {
@Override
public String doEqualSharding(final Collection<String> availableTargetNames, final ShardingValue<Integer> shardingValue) {
public String doEqualSharding(final Collection<String> availableTargetNames, final ShardingValue<Long> shardingValue) {
for (String each : availableTargetNames) {
if (each.endsWith(shardingValue.getValue() % 2 + "")) {
return each;
......@@ -37,10 +37,10 @@ public final class SingleKeyModuloTableShardingAlgorithm implements SingleKeyTab
}
@Override
public Collection<String> doInSharding(final Collection<String> availableTargetNames, final ShardingValue<Integer> shardingValue) {
public Collection<String> doInSharding(final Collection<String> availableTargetNames, final ShardingValue<Long> shardingValue) {
Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
Collection<Integer> values = shardingValue.getValues();
for (Integer value : values) {
Collection<Long> values = shardingValue.getValues();
for (Long value : values) {
for (String tableNames : availableTargetNames) {
if (tableNames.endsWith(value % 2 + "")) {
result.add(tableNames);
......@@ -51,10 +51,10 @@ public final class SingleKeyModuloTableShardingAlgorithm implements SingleKeyTab
}
@Override
public Collection<String> doBetweenSharding(final Collection<String> availableTargetNames, final ShardingValue<Integer> shardingValue) {
public Collection<String> doBetweenSharding(final Collection<String> availableTargetNames, final ShardingValue<Long> shardingValue) {
Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
Range<Integer> range = shardingValue.getValueRange();
for (Integer i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
Range<Long> range = shardingValue.getValueRange();
for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
for (String each : availableTargetNames) {
if (each.endsWith(i % 2 + "")) {
result.add(each);
......
......@@ -17,12 +17,13 @@
package com.dangdang.ddframe.rdb.sharding.example.jdbc.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
@Entity
@Table(name = "t_order")
......@@ -32,7 +33,8 @@ public class Order implements Serializable {
@Id
@Column(name = "order_id")
private int orderId;
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long orderId;
@Column(name = "user_id")
private int userId;
......@@ -40,11 +42,11 @@ public class Order implements Serializable {
@Column(name = "status")
private String status;
public int getOrderId() {
public long getOrderId() {
return orderId;
}
public void setOrderId(final int orderId) {
public void setOrderId(final long orderId) {
this.orderId = orderId;
}
......
......@@ -17,13 +17,13 @@
package com.dangdang.ddframe.rdb.sharding.example.jdbc.repository;
import java.util.List;
import com.dangdang.ddframe.rdb.sharding.example.jdbc.entity.Order;
import java.util.List;
public interface OrderRepository {
Order selectById(int orderId);
Order selectById(long orderId);
List<Order> selectAll();
......@@ -33,5 +33,5 @@ public interface OrderRepository {
void update(Order order);
void delete(int orderId);
void delete(long orderId);
}
......@@ -17,15 +17,14 @@
package com.dangdang.ddframe.rdb.sharding.example.jdbc.repository;
import java.util.List;
import com.dangdang.ddframe.rdb.sharding.example.jdbc.entity.Order;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;
import org.springframework.stereotype.Repository;
import com.dangdang.ddframe.rdb.sharding.example.jdbc.entity.Order;
import java.util.List;
@Repository
@Transactional
......@@ -35,7 +34,7 @@ public class OrderRepositoryImpl implements OrderRepository {
private EntityManager entityManager;
@Override
public Order selectById(final int orderId) {
public Order selectById(final long orderId) {
return entityManager.find(Order.class, orderId);
}
......@@ -58,11 +57,17 @@ public class OrderRepositoryImpl implements OrderRepository {
@Override
public void update(final Order order) {
entityManager.merge(order);
Query query = entityManager.createQuery("UPDATE Order o SET o.status = ?1 WHERE o.orderId = ?2 AND o.userId = ?3");
query.setParameter(1, order.getStatus());
query.setParameter(2, order.getOrderId());
query.setParameter(3, order.getUserId());
query.executeUpdate();
}
@Override
public void delete(final int orderId) {
entityManager.remove(selectById(orderId));
public void delete(final long orderId) {
Query query = entityManager.createQuery("DELETE FROM Order o WHERE o.orderId = ?1 AND o.userId = 51");
query.setParameter(1, orderId);
query.executeUpdate();
}
}
......@@ -8,25 +8,27 @@
http://www.dangdang.com/schema/ddframe/rdb/rdb.xsd">
<bean id="ds_0" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ds_0"/>
<property name="url" value="jdbc:mysql://example.sharding-jdbc.dangdang.com:3306/ds_0"/>
<property name="username" value="root"/>
<property name="password" value=""/>
<property name="password" value="java"/>
</bean>
<bean id="ds_1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ds_1"/>
<property name="url" value="jdbc:mysql://example.sharding-jdbc.dangdang.com:3306/ds_1"/>
<property name="username" value="root"/>
<property name="password" value=""/>
<property name="password" value="java"/>
</bean>
<rdb:strategy id="databaseShardingStrategy" sharding-columns="user_id" algorithm-class="com.dangdang.ddframe.rdb.sharding.example.jdbc.algorithm.SingleKeyModuloDatabaseShardingAlgorithm"/>
<rdb:strategy id="tableShardingStrategy" sharding-columns="order_id" algorithm-class="com.dangdang.ddframe.rdb.sharding.example.jdbc.algorithm.SingleKeyModuloTableShardingAlgorithm"/>
<rdb:data-source id="shardingDataSource">
<rdb:sharding-rule data-sources="ds_0, ds_1">
<rdb:sharding-rule data-sources="ds_0, ds_1" id-generator-class="com.dangdang.ddframe.rdb.sharding.id.generator.self.CommonSelfIdGenerator">
<rdb:table-rules>
<rdb:table-rule logic-table="t_order" actual-tables="t_order_${0..1}" database-strategy="databaseShardingStrategy" table-strategy="tableShardingStrategy"/>
<rdb:table-rule logic-table="t_order" actual-tables="t_order_${0..1}" database-strategy="databaseShardingStrategy" table-strategy="tableShardingStrategy">
<rdb:auto-increment-column column-name="order_id"/>
</rdb:table-rule>
</rdb:table-rules>
</rdb:sharding-rule>
</rdb:data-source>
......
CREATE SCHEMA IF NOT EXISTS `ds_0`;
CREATE SCHEMA IF NOT EXISTS `ds_1`;
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_0` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_1` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_item_0` (`item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_item_1` (`item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_0` (`order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_1` (`order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_item_0` (`item_id` BIGINT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_item_1` (`item_id` BIGINT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_0` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_1` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_item_0` (`item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_item_1` (`item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_0` (`order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_1` (`order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_item_0` (`item_id` BIGINT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_item_1` (`item_id` BIGINT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
INSERT INTO `ds_0`.`t_order_0` VALUES (1000, 10, 'INIT');
INSERT INTO `ds_0`.`t_order_0` VALUES (1002, 10, 'INIT');
......
......@@ -35,7 +35,7 @@ public class Main {
orderService.fooService();
orderService.select();
//[order_id: 1, user_id: 10, status: UPDATED, order_id: 1, user_id: 11, status: UPDATED]
//[order_id: , user_id: 10, status: UPDATED, order_id: , user_id: 11, status: UPDATED]
orderService.clear();
try {
orderService.fooServiceWithFailure();
......
......@@ -17,17 +17,17 @@
package com.dangdang.ddframe.rdb.sharding.example.jdbc.algorithm;
import java.util.Collection;
import java.util.LinkedHashSet;
import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.SingleKeyTableShardingAlgorithm;
import com.google.common.collect.Range;
public final class SingleKeyModuloTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Integer> {
import java.util.Collection;
import java.util.LinkedHashSet;
public final class SingleKeyModuloTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Long> {
@Override
public String doEqualSharding(final Collection<String> availableTargetNames, final ShardingValue<Integer> shardingValue) {
public String doEqualSharding(final Collection<String> availableTargetNames, final ShardingValue<Long> shardingValue) {
for (String each : availableTargetNames) {
if (each.endsWith(shardingValue.getValue() % 2 + "")) {
return each;
......@@ -37,10 +37,10 @@ public final class SingleKeyModuloTableShardingAlgorithm implements SingleKeyTab
}
@Override
public Collection<String> doInSharding(final Collection<String> availableTargetNames, final ShardingValue<Integer> shardingValue) {
public Collection<String> doInSharding(final Collection<String> availableTargetNames, final ShardingValue<Long> shardingValue) {
Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
Collection<Integer> values = shardingValue.getValues();
for (Integer value : values) {
Collection<Long> values = shardingValue.getValues();
for (Long value : values) {
for (String tableNames : availableTargetNames) {
if (tableNames.endsWith(value % 2 + "")) {
result.add(tableNames);
......@@ -51,10 +51,10 @@ public final class SingleKeyModuloTableShardingAlgorithm implements SingleKeyTab
}
@Override
public Collection<String> doBetweenSharding(final Collection<String> availableTargetNames, final ShardingValue<Integer> shardingValue) {
public Collection<String> doBetweenSharding(final Collection<String> availableTargetNames, final ShardingValue<Long> shardingValue) {
Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
Range<Integer> range = shardingValue.getValueRange();
for (Integer i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
Range<Long> range = shardingValue.getValueRange();
for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
for (String each : availableTargetNames) {
if (each.endsWith(i % 2 + "")) {
result.add(each);
......
......@@ -19,17 +19,17 @@ package com.dangdang.ddframe.rdb.sharding.example.jdbc.entity;
public final class Order {
private int orderId;
private long orderId;
private int userId;
private String status;
public int getOrderId() {
public long getOrderId() {
return orderId;
}
public void setOrderId(final int orderId) {
public void setOrderId(final long orderId) {
this.orderId = orderId;
}
......
......@@ -17,14 +17,14 @@
package com.dangdang.ddframe.rdb.sharding.example.jdbc.service;
import javax.annotation.Resource;
import com.dangdang.ddframe.rdb.sharding.example.jdbc.entity.Order;
import com.dangdang.ddframe.rdb.sharding.example.jdbc.repository.OrderRepository;
import com.google.common.collect.Lists;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
/**
* Order 服务对象.
*
......@@ -48,14 +48,14 @@ public class OrderService {
public void fooService() {
Order criteria = new Order();
criteria.setUserId(10);
criteria.setOrderId(1);
criteria.setStatus("INSERT");
orderRepository.insert(criteria);
System.out.println(criteria.getOrderId());
criteria.setUserId(11);
criteria.setOrderId(1);
criteria.setStatus("INSERT2");
orderRepository.insert(criteria);
System.out.println(criteria.getOrderId());
orderRepository.update(Lists.newArrayList(10, 11));
}
......
......@@ -2,7 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dangdang.ddframe.rdb.sharding.example.jdbc.repository.OrderRepository">
<resultMap id="baseResultMap" type="com.dangdang.ddframe.rdb.sharding.example.jdbc.entity.Order">
<result column="order_id" property="orderId" jdbcType="INTEGER"/>
<result column="order_id" property="orderId" jdbcType="BIGINT"/>
<result column="user_id" property="userId" jdbcType="INTEGER"/>
<result column="status" property="status" jdbcType="CLOB"/>
</resultMap>
......@@ -13,12 +13,11 @@
status
</sql>
<insert id="insert">
<insert id="insert" keyProperty="orderId" useGeneratedKeys="true" >
INSERT INTO `t_order`(
<include refid="baseColumnList"/>
`user_id`,`status`
)
VALUES (
#{orderId,jdbcType=INTEGER},
#{userId,jdbcType=INTEGER},
#{status,jdbcType=CLOB}
);
......@@ -27,7 +26,7 @@
<update id="update">
UPDATE `t_order`
SET `status` = 'UPDATED'
WHERE `order_id` = 1 AND `user_id` in
WHERE `user_id` in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
......
......@@ -32,9 +32,11 @@
<rdb:strategy id="tableShardingStrategy" sharding-columns="order_id" algorithm-class="com.dangdang.ddframe.rdb.sharding.example.jdbc.algorithm.SingleKeyModuloTableShardingAlgorithm"/>
<rdb:data-source id="shardingDataSource">
<rdb:sharding-rule data-sources="ds_0, ds_1">
<rdb:sharding-rule data-sources="ds_0, ds_1" id-generator-class="com.dangdang.ddframe.rdb.sharding.id.generator.self.CommonSelfIdGenerator">
<rdb:table-rules>
<rdb:table-rule logic-table="t_order" actual-tables="t_order_${0..1}" database-strategy="databaseShardingStrategy" table-strategy="tableShardingStrategy"/>
<rdb:table-rule logic-table="t_order" actual-tables="t_order_${0..1}" database-strategy="databaseShardingStrategy" table-strategy="tableShardingStrategy">
<rdb:auto-increment-column column-name="order_id"/>
</rdb:table-rule>
</rdb:table-rules>
</rdb:sharding-rule>
</rdb:data-source>
......
CREATE SCHEMA IF NOT EXISTS `ds_0`;
CREATE SCHEMA IF NOT EXISTS `ds_1`;
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_0` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_1` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_item_0` (`item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_item_1` (`item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_0` (`order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_1` (`order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_item_0` (`item_id` BIGINT NOT NULL, `order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_0`.`t_order_item_1` (`item_id` BIGINT NOT NULL, `order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_0` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_1` (`order_id` INT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_item_0` (`item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_item_1` (`item_id` INT NOT NULL, `order_id` INT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_0` (`order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_1` (`order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, `status` VARCHAR(50), PRIMARY KEY (`order_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_item_0` (`item_id` BIGINT NOT NULL, `order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
CREATE TABLE IF NOT EXISTS `ds_1`.`t_order_item_1` (`item_id` BIGINT NOT NULL, `order_id` BIGINT NOT NULL, `user_id` INT NOT NULL, PRIMARY KEY (`item_id`));
INSERT INTO `ds_0`.`t_order_0` VALUES (1000, 10, 'INIT');
INSERT INTO `ds_0`.`t_order_0` VALUES (1002, 10, 'INIT');
......
......@@ -23,6 +23,10 @@ import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 自生成Id生成器.
......@@ -43,6 +47,7 @@ import lombok.Setter;
* @author gaohongtao.
*/
@Getter
@Slf4j
public class CommonSelfIdGenerator implements IdGenerator {
public static final long SJDBC_EPOCH = 1477933200000L;
......@@ -90,6 +95,11 @@ public class CommonSelfIdGenerator implements IdGenerator {
setWorkerId(Long.valueOf(workerId));
}
/**
* 设置工作进程Id.
*
* @param workerId
*/
public static void setWorkerId(final Long workerId) {
Preconditions.checkArgument(workerId >= 0L && workerId < WORKER_ID_MAX_VALUE);
CommonSelfIdGenerator.workerId = workerId;
......@@ -124,6 +134,9 @@ public class CommonSelfIdGenerator implements IdGenerator {
sequence = 0;
}
lastTime = time;
if (log.isDebugEnabled()) {
log.debug("{}.{}:{}-{}-{}", tableName, columnName, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(lastTime)), workerId, sequence);
}
return ((time - SJDBC_EPOCH) << TIMESTAMP_LEFT_SHIFT_BITS) | (workerId << WORKER_ID_LEFT_SHIFT_BITS) | sequence;
}
......
......@@ -6,6 +6,9 @@
<pattern>[%-5level] %d{HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="com.dangdang.ddframe.rdb.sharding.id.generator" level="info" additivity="false">
<appender-ref ref="console"/>
</logger>
<logger name="com.dangdang" level="info" additivity="false">
<appender-ref ref="console"/>
</logger>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册