└── shardingDataSource ├── .classpath ├── .gitignore ├── .project ├── .settings ├── org.eclipse.core.resources.prefs ├── org.eclipse.jdt.core.prefs ├── org.eclipse.m2e.core.prefs ├── org.eclipse.wst.common.component ├── org.eclipse.wst.common.project.facet.core.xml └── org.eclipse.wst.validation.prefs ├── pom.xml └── src └── main └── java └── org └── darwin └── shardingDataSource ├── dataSource ├── DataSourceConstants.java ├── ReadWriteSplitingDataSource.java ├── ShardingDataSource.java └── rule │ ├── ShardingRule.java │ ├── SlaveSelector.java │ └── impl │ ├── ByOrderSelector.java │ ├── ByWeightSelector.java │ ├── ModShardingRule.java │ └── RandomSelector.java └── transaction └── ShardingTransactionManager.java /shardingDataSource/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /shardingDataSource/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /shardingDataSource/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | shardingDataSource 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.common.project.facet.core.builder 10 | 11 | 12 | 13 | 14 | org.eclipse.jdt.core.javabuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.wst.validation.validationbuilder 20 | 21 | 22 | 23 | 24 | org.eclipse.m2e.core.maven2Builder 25 | 26 | 27 | 28 | 29 | 30 | org.eclipse.jem.workbench.JavaEMFNature 31 | org.eclipse.wst.common.modulecore.ModuleCoreNature 32 | org.eclipse.jdt.core.javanature 33 | org.eclipse.m2e.core.maven2Nature 34 | org.eclipse.wst.common.project.facet.core.nature 35 | 36 | 37 | -------------------------------------------------------------------------------- /shardingDataSource/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/test/java=UTF-8 4 | -------------------------------------------------------------------------------- /shardingDataSource/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 4 | org.eclipse.jdt.core.compiler.compliance=1.5 5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 7 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 8 | org.eclipse.jdt.core.compiler.source=1.5 9 | -------------------------------------------------------------------------------- /shardingDataSource/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /shardingDataSource/.settings/org.eclipse.wst.common.component: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /shardingDataSource/.settings/org.eclipse.wst.common.project.facet.core.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /shardingDataSource/.settings/org.eclipse.wst.validation.prefs: -------------------------------------------------------------------------------- 1 | disabled=06target 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /shardingDataSource/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | org.darwin 5 | shardingDataSource 6 | 0.0.3-SNAPSHOT 7 | shardingDataSource 8 | 数据库分库中的动态数据源组件,可以实现读写分离、数据切片 9 | 10 | 11 | 12 | com.springsource.repository.bundles.release 13 | EBR Spring Release Repository 14 | http://repository.springsource.com/maven/bundles/release 15 | 16 | 17 | com.springsource.repository.bundles.external 18 | EBR External Release Repository 19 | http://repository.springsource.com/maven/bundles/external 20 | 21 | 22 | 23 | 3.2.6.RELEASE 24 | 1.7.6 25 | 26 | 27 | 28 | nexus-snapshots 29 | http://mynexus.com:8081/nexus/content/repositories/snapshots/ 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.darwin 37 | commons 38 | 0.0.3-SNAPSHOT 39 | 40 | 41 | 42 | org.springframework 43 | spring-jdbc 44 | ${org.springframework.version} 45 | 46 | 47 | 48 | org.slf4j 49 | slf4j-api 50 | ${slf4j.version} 51 | 52 | 53 | 54 | 55 | package 56 | ${project.artifactId} 57 | target/classes 58 | 59 | 60 | 61 | org.apache.maven.plugins 62 | maven-compiler-plugin 63 | 64 | UTF-8 65 | 66 | 67 | 68 | 69 | org.apache.maven.plugins 70 | maven-jar-plugin 71 | 72 | 73 | *.properties 74 | 75 | 76 | 77 | 78 | make-jar 79 | package 80 | 81 | jar 82 | 83 | 84 | 85 | make-sdk-jar 86 | package 87 | 88 | jar 89 | 90 | 91 | sdk 92 | 93 | **/bo/* 94 | 95 | 96 | 97 | 98 | 99 | 100 | maven-source-plugin 101 | 2.1 102 | 103 | true 104 | 105 | 106 | 107 | compile 108 | 109 | jar 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | online 120 | 121 | 122 | 123 | ${project.build.online.sourceDir} 124 | 125 | *.properties 126 | 127 | 128 | 129 | 130 | ${project.build.sourceDirectory} 131 | 132 | **/*.java 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /shardingDataSource/src/main/java/org/darwin/shardingDataSource/dataSource/DataSourceConstants.java: -------------------------------------------------------------------------------- 1 | /** 2 | * org.darwin.shardingDataSource.dataSource.DataSourceConstants.java 3 | * created by Tianxin(tianjige@163.com) on 2015年6月8日 上午10:43:35 4 | */ 5 | package org.darwin.shardingDataSource.dataSource; 6 | 7 | /** 8 | * 数据源中的常量 9 | * created by Tianxin on 2015年6月8日 上午10:43:35 10 | */ 11 | public interface DataSourceConstants { 12 | 13 | public final static String READ = "read"; 14 | public final static String WRITE = "write"; 15 | 16 | /** 17 | * 数据库的操作类型 18 | */ 19 | public final static String DB_OPT_TYPE = "dbOperationType"; 20 | } 21 | -------------------------------------------------------------------------------- /shardingDataSource/src/main/java/org/darwin/shardingDataSource/dataSource/ReadWriteSplitingDataSource.java: -------------------------------------------------------------------------------- 1 | /** 2 | * org.darwin.shardingDataSource.dataSource.ReadWriteSplitingDataSource.java 3 | * created by Tianxin(tianjige@163.com) on 2015年6月8日 上午10:13:58 4 | */ 5 | package org.darwin.shardingDataSource.dataSource; 6 | 7 | import java.sql.Connection; 8 | import java.sql.SQLException; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import javax.sql.DataSource; 13 | 14 | import org.darwin.common.ThreadContext; 15 | import org.darwin.shardingDataSource.dataSource.rule.SlaveSelector; 16 | import org.darwin.shardingDataSource.dataSource.rule.impl.ByOrderSelector; 17 | import org.darwin.shardingDataSource.dataSource.rule.impl.ByWeightSelector; 18 | import org.darwin.shardingDataSource.dataSource.rule.impl.RandomSelector; 19 | import org.springframework.jdbc.datasource.AbstractDataSource; 20 | 21 | /** 22 | * 数据库作为读写分离的数据源 23 | * created by Tianxin on 2015年6月8日 上午10:13:58 24 | */ 25 | public class ReadWriteSplitingDataSource extends AbstractDataSource { 26 | 27 | public Connection getConnection() throws SQLException { 28 | return chooseSuitableDataSource().getConnection(); 29 | } 30 | 31 | public Connection getConnection(String username, String password) throws SQLException { 32 | return chooseSuitableDataSource().getConnection(username, password); 33 | } 34 | 35 | /** 36 | * 选择合适的数据源,该方法确保返回不为空 37 | * @return 38 | * created by Tianxin on 2015年6月8日 上午10:28:05 39 | */ 40 | private final DataSource chooseSuitableDataSource() { 41 | boolean isWrite = (slaveDataSources == null || isWriteOperation()); 42 | if (isWrite) { 43 | return masterDataSource; 44 | } 45 | 46 | //如果是读操作,则获取相应的读库 47 | return getOneSlaveDataSource(); 48 | } 49 | 50 | 51 | /** 52 | * 获取一个读库.程序里面基本都不会关心用哪个从库,只是有时候需要按照权重进行分离,所以这里考虑到权重的问题即可. 53 | * @return 54 | * created by Tianxin on 2015年6月8日 上午10:49:22 55 | */ 56 | private DataSource getOneSlaveDataSource() { 57 | 58 | int currentIndex = getCurrentIndex(); 59 | return slaveDataSources.get(currentIndex); 60 | } 61 | 62 | 63 | /** 64 | * 获取本次要使用的数据源的index 65 | * @return 66 | * created by Tianxin on 2015年6月8日 上午10:52:46 67 | */ 68 | private int getCurrentIndex() { 69 | if (selector == null) { 70 | 71 | switch (slaveRoundType) { 72 | case RANDOM: 73 | selector = new RandomSelector(slaveDataSources.size()); 74 | break; 75 | case BY_ORDER: 76 | selector = new ByOrderSelector(slaveDataSources.size()); 77 | break; 78 | case BY_WEIGHT: 79 | selector = new ByWeightSelector(weights); 80 | break; 81 | default: 82 | selector = new RandomSelector(slaveDataSources.size()); 83 | break; 84 | } 85 | 86 | } 87 | return selector.getCurrentIndex(); 88 | } 89 | 90 | /** 91 | * 主库的数据源 92 | */ 93 | private DataSource masterDataSource; 94 | 95 | /** 96 | * 从库的数据源列表。 97 | */ 98 | private List slaveDataSources; 99 | 100 | /** 101 | * 从库的选取策略 102 | */ 103 | private int slaveRoundType; 104 | 105 | /** 106 | * 权重的数组 107 | */ 108 | private int[] weights; 109 | 110 | /** 111 | * 从库的选取策略 112 | */ 113 | private SlaveSelector selector = null; 114 | 115 | public void setMasterDataSource(DataSource masterDataSource) { 116 | this.masterDataSource = masterDataSource; 117 | } 118 | 119 | public void setSlaveDataSources(List slaveDataSources) { 120 | this.slaveDataSources = new ArrayList(slaveDataSources); 121 | } 122 | 123 | /** 124 | * 判断当前是否是写操作 125 | * @return 126 | * created by Tianxin on 2015年6月8日 上午10:41:02 127 | */ 128 | private final static boolean isWriteOperation() { 129 | String optType = ThreadContext.get(DataSourceConstants.DB_OPT_TYPE); 130 | 131 | //无type时,默认走主库 132 | if (optType == null) { 133 | return true; 134 | } 135 | 136 | //根据上下文中的类型判断是读库还是写库 137 | return DataSourceConstants.WRITE.equals(optType.toLowerCase()); 138 | } 139 | 140 | /** 141 | * 设置从库的轮转策略.三种轮转策略:0为随机,1为顺序,2为按权重 142 | * @param type 143 | * created by Tianxin on 2015年6月8日 上午11:41:46 144 | */ 145 | public void setSlaveRoundType(int type) { 146 | this.slaveRoundType = type; 147 | } 148 | 149 | /** 150 | * 设置从库的权重。以逗号进行分隔,如:1,2,3 151 | * @param type 152 | * created by Tianxin on 2015年6月8日 上午11:41:46 153 | */ 154 | public void setSlaveWeights(String weights) { 155 | 156 | if (weights == null || weights.length() == 0) { 157 | return; 158 | } 159 | 160 | weights = weights.replace(',', ','); 161 | String[] sArray = weights.split(","); 162 | 163 | //将其转换为权重数组 164 | int[] iArray = new int[sArray.length]; 165 | for (int i = 0; i < sArray.length; i++) { 166 | iArray[i] = Integer.parseInt(sArray[i].trim()); 167 | } 168 | this.weights = iArray; 169 | } 170 | 171 | private final static int RANDOM = 0; 172 | private final static int BY_ORDER = 1; 173 | private final static int BY_WEIGHT = 2; 174 | } 175 | -------------------------------------------------------------------------------- /shardingDataSource/src/main/java/org/darwin/shardingDataSource/dataSource/ShardingDataSource.java: -------------------------------------------------------------------------------- 1 | /** 2 | * org.darwin.shardingDataSource.dataSource.ShardingDataSource.java 3 | * created by Tianxin(tianjige@163.com) on 2015年6月8日 上午10:13:07 4 | */ 5 | package org.darwin.shardingDataSource.dataSource; 6 | 7 | import java.sql.Connection; 8 | import java.sql.SQLException; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import javax.sql.DataSource; 13 | 14 | import org.darwin.shardingDataSource.dataSource.rule.ShardingRule; 15 | import org.springframework.jdbc.datasource.AbstractDataSource; 16 | 17 | /** 18 | * 数据库分shard的数据源 19 | * created by Tianxin on 2015年6月8日 上午10:13:07 20 | */ 21 | public class ShardingDataSource extends AbstractDataSource { 22 | 23 | public Connection getConnection() throws SQLException { 24 | return chooseSuitableDataSource().getConnection(); 25 | } 26 | 27 | public Connection getConnection(String username, String password) throws SQLException { 28 | return chooseSuitableDataSource().getConnection(username, password); 29 | } 30 | 31 | /** 32 | * 数据源列表 33 | */ 34 | private List shardingDataSources = null; 35 | 36 | private int shardCount = 0; 37 | 38 | public void setShardingDataSources(List shardingDataSources) { 39 | 40 | if (shardingDataSources == null || shardingDataSources.size() <= 1) { 41 | throw new RuntimeException("不能使用切片的数据源,数据源个数比需要大于1! it is " + (shardingDataSources == null ? "null" : shardingDataSources.size())); 42 | } 43 | 44 | this.shardingDataSources = new ArrayList(shardingDataSources); 45 | this.shardCount = shardingDataSources.size(); 46 | checkShardingConfig(); 47 | } 48 | 49 | /** 50 | * 选择合适的数据源,该方法确保返回不为空 51 | * @return 52 | * created by Tianxin on 2015年6月8日 上午10:28:05 53 | */ 54 | private final DataSource chooseSuitableDataSource() { 55 | 56 | int index = shardingRule.getCurrentShardingIndex(); 57 | if (index >= shardCount || index < 0) { 58 | throw new RuntimeException("shardingRule返回的当前切片index不合法:" + index); 59 | } 60 | return shardingDataSources.get(index); 61 | } 62 | 63 | /** 64 | * sharding的规则 65 | */ 66 | private ShardingRule shardingRule = null; 67 | 68 | public void setShardingRule(ShardingRule shardingRule) { 69 | this.shardingRule = shardingRule; 70 | checkShardingConfig(); 71 | } 72 | 73 | /** 74 | * 校验sharding的配置是否合法 75 | * created by Tianxin on 2015年6月8日 下午12:20:26 76 | */ 77 | private void checkShardingConfig() { 78 | 79 | //可能是中间状态,还没完成初始化 80 | if (shardingDataSources == null || shardingRule == null) { 81 | return; 82 | } 83 | 84 | int ruleCount = shardingRule.getShardCount(); 85 | if (ruleCount != shardCount) { 86 | throw new RuntimeException("规则配置的切片数量与数据源中的切片数量不匹配!"); 87 | } 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /shardingDataSource/src/main/java/org/darwin/shardingDataSource/dataSource/rule/ShardingRule.java: -------------------------------------------------------------------------------- 1 | /** 2 | * org.darwin.shardingDataSource.dataSource.rule.ShardingRule.java 3 | * created by Tianxin(tianjige@163.com) on 2015年6月8日 下午12:03:55 4 | */ 5 | package org.darwin.shardingDataSource.dataSource.rule; 6 | 7 | /** 8 | * 数据库的切片规则 9 | * created by Tianxin on 2015年6月8日 下午12:03:55 10 | */ 11 | public interface ShardingRule { 12 | 13 | /** 14 | * 获取本次操作的数据库切片号 15 | * @return 16 | * created by Tianxin on 2015年6月8日 下午12:04:19 17 | */ 18 | int getCurrentShardingIndex(); 19 | 20 | /** 21 | * 获取配置的切片数量 22 | * @return 23 | * created by Tianxin on 2015年6月8日 下午12:23:44 24 | */ 25 | int getShardCount(); 26 | } 27 | -------------------------------------------------------------------------------- /shardingDataSource/src/main/java/org/darwin/shardingDataSource/dataSource/rule/SlaveSelector.java: -------------------------------------------------------------------------------- 1 | /** 2 | * org.darwin.shardingDataSource.dataSource.rule.SlaveSelector.java 3 | * created by Tianxin(tianjige@163.com) on 2015年6月8日 上午10:58:48 4 | */ 5 | package org.darwin.shardingDataSource.dataSource.rule; 6 | 7 | /** 8 | * 从库的选取规则 9 | * created by Tianxin on 2015年6月8日 上午10:58:48 10 | */ 11 | public interface SlaveSelector { 12 | 13 | /** 14 | * 获取本次选取的从库的index 15 | * @return 16 | * created by Tianxin on 2015年6月8日 上午10:59:15 17 | */ 18 | int getCurrentIndex(); 19 | } 20 | -------------------------------------------------------------------------------- /shardingDataSource/src/main/java/org/darwin/shardingDataSource/dataSource/rule/impl/ByOrderSelector.java: -------------------------------------------------------------------------------- 1 | /** 2 | * org.darwin.shardingDataSource.dataSource.rule.ByOrderSelector.java 3 | * created by Tianxin(tianjige@163.com) on 2015年6月8日 上午11:11:01 4 | */ 5 | package org.darwin.shardingDataSource.dataSource.rule.impl; 6 | 7 | import org.darwin.shardingDataSource.dataSource.rule.SlaveSelector; 8 | 9 | /** 10 | * 顺序选取的选取器 created by Tianxin on 2015年6月8日 上午11:11:01 11 | */ 12 | public class ByOrderSelector implements SlaveSelector { 13 | 14 | private ByOrderSelector() {} 15 | 16 | /** 17 | * @param slaveCount 18 | */ 19 | public ByOrderSelector(int slaveCount) { 20 | this(); 21 | this.slaveCount = slaveCount; 22 | } 23 | 24 | /** 25 | * 从库的数量 26 | */ 27 | private int slaveCount; 28 | 29 | /** 30 | * 上一次的index 31 | */ 32 | private int lastIndex = 0; 33 | 34 | /* 35 | * 由于这个顺序不会影响到正确性,所以不做synchronized的限定,高并发时允许有重复 36 | */ 37 | public int getCurrentIndex() { 38 | if (lastIndex == Integer.MAX_VALUE) { 39 | lastIndex = 0; 40 | } else { 41 | lastIndex += 1; 42 | } 43 | return lastIndex % slaveCount; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /shardingDataSource/src/main/java/org/darwin/shardingDataSource/dataSource/rule/impl/ByWeightSelector.java: -------------------------------------------------------------------------------- 1 | /** 2 | * org.darwin.shardingDataSource.dataSource.rule.ByWeightSelector.java 3 | * created by Tianxin(tianjige@163.com) on 2015年6月8日 上午11:15:10 4 | */ 5 | package org.darwin.shardingDataSource.dataSource.rule.impl; 6 | 7 | import org.darwin.shardingDataSource.dataSource.rule.SlaveSelector; 8 | 9 | /** 10 | * 根据权重的选择器。这里的权重选择比较简单,目前是折合成整数后依次将每一个数据源的配额耗光以后再进行一轮消耗。 11 | * 如果权重配置为100,200,300,则会依次使用1次,2次,3次。但同一个数据源的几次选取是连续的 12 | * created by Tianxin on 2015年6月8日 上午11:15:10 13 | */ 14 | public class ByWeightSelector implements SlaveSelector { 15 | 16 | private ByWeightSelector() { 17 | } 18 | 19 | public ByWeightSelector(int[] weights) { 20 | this(); 21 | this.weights = weights; 22 | this.slaveCount = weights.length; 23 | 24 | //获取最小公约数,避免连续过多 25 | int maxDevide = getMaxDevideByOujilide(weights); 26 | if(maxDevide != 1){ 27 | for(int i = 0 ; i < weights.length ; i ++){ 28 | weights[i] = weights[i] / maxDevide; 29 | } 30 | } 31 | } 32 | 33 | /** 34 | * 对数据源的描述 35 | */ 36 | private int[] weights; 37 | 38 | /** 39 | * 数据源的个数 40 | */ 41 | private int slaveCount = 0; 42 | 43 | /** 44 | * 指针当前指向的数据源 45 | */ 46 | private int currentIndex = 0; 47 | 48 | /** 49 | * 当前节点的权重已经消耗了多少 50 | */ 51 | private int weightCost = 0; 52 | 53 | public int getCurrentIndex() { 54 | 55 | // 当前节点的权重大小,将要达到的使用次数 56 | int top = weights[currentIndex]; 57 | weightCost += 1; 58 | 59 | // 如果达到了top,则轮转下一个节点 60 | if (weightCost == top) { 61 | weightCost = 0; 62 | if (currentIndex == slaveCount) { 63 | currentIndex = 0; 64 | } else { 65 | currentIndex += 1; 66 | } 67 | } 68 | return currentIndex; 69 | } 70 | 71 | /** 72 | * 获取两个数的最大公约数 73 | * 74 | * @param a 75 | * @param b 76 | * @return created by Tianxin on 2015年6月8日 上午11:30:53 77 | */ 78 | public static int getMaxDevideByOujilide(int a, int b) { 79 | if (a < b) { 80 | int temp; 81 | temp = a; 82 | a = b; 83 | b = temp; 84 | } 85 | if (0 == b) { 86 | return a; 87 | } 88 | return getMaxDevideByOujilide(b, a % b); 89 | } 90 | 91 | /** 92 | * 获取多个数的最大公约数 93 | * 94 | * @param a 95 | * @param b 96 | * @return created by Tianxin on 2015年6月8日 上午11:30:53 97 | */ 98 | public static int getMaxDevideByOujilide(int[] is) { 99 | int maxDevide = 0; 100 | for(int i = 0; i < is.length; i ++){ 101 | maxDevide = getMaxDevideByOujilide(maxDevide, is[i]); 102 | } 103 | return maxDevide; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /shardingDataSource/src/main/java/org/darwin/shardingDataSource/dataSource/rule/impl/ModShardingRule.java: -------------------------------------------------------------------------------- 1 | /** 2 | * org.darwin.shardingDataSource.dataSource.rule.impl.ModShardingRule.java 3 | * created by Tianxin(tianjige@163.com) on 2015年6月8日 下午12:09:31 4 | */ 5 | package org.darwin.shardingDataSource.dataSource.rule.impl; 6 | 7 | import org.darwin.common.ThreadContext; 8 | import org.darwin.shardingDataSource.dataSource.rule.ShardingRule; 9 | 10 | /** 11 | * 根据shardKey取模的拆库规则 12 | * created by Tianxin on 2015年6月8日 下午12:09:31 13 | */ 14 | public class ModShardingRule implements ShardingRule { 15 | 16 | public int getCurrentShardingIndex() { 17 | 18 | if (shardCount <= 1) { 19 | throw new RuntimeException("切片数量小于2,不能使用切片数据源"); 20 | } 21 | 22 | int iShardingKey = 0; 23 | if (shardingKey == null) { 24 | iShardingKey = ThreadContext.getShardingKey(); 25 | } else { 26 | iShardingKey = ThreadContext.get(shardingKey); 27 | } 28 | 29 | return iShardingKey % shardCount; 30 | } 31 | 32 | /** 33 | * 切片key在上下文中的存储的key 34 | */ 35 | private String shardingKey = "shardingKey"; 36 | 37 | /** 38 | * 数据库的切片数量 39 | */ 40 | private int shardCount = 0; 41 | 42 | public void setShardingKey(String shardingKey) { 43 | this.shardingKey = shardingKey; 44 | } 45 | 46 | public void setShardCount(int shardCount) { 47 | this.shardCount = shardCount; 48 | } 49 | 50 | public int getShardCount() { 51 | return shardCount; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /shardingDataSource/src/main/java/org/darwin/shardingDataSource/dataSource/rule/impl/RandomSelector.java: -------------------------------------------------------------------------------- 1 | /** 2 | * org.darwin.shardingDataSource.dataSource.rule.RandomSelector.java 3 | * created by Tianxin(tianjige@163.com) on 2015年6月8日 上午11:06:38 4 | */ 5 | package org.darwin.shardingDataSource.dataSource.rule.impl; 6 | 7 | import java.util.Random; 8 | 9 | import org.darwin.shardingDataSource.dataSource.rule.SlaveSelector; 10 | 11 | /** 12 | * 从库的随机选择器 13 | * created by Tianxin on 2015年6月8日 上午11:06:38 14 | */ 15 | public class RandomSelector implements SlaveSelector { 16 | 17 | private RandomSelector() { 18 | } 19 | 20 | /** 21 | * @param slaveCount 22 | */ 23 | public RandomSelector(int slaveCount) { 24 | this(); 25 | this.slaveCount = slaveCount; 26 | } 27 | 28 | /** 29 | * 从库的数量 30 | */ 31 | private int slaveCount; 32 | 33 | /** 34 | * 随机选取器 35 | */ 36 | private Random random = new Random(); 37 | 38 | public int getCurrentIndex() { 39 | return random.nextInt(slaveCount); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /shardingDataSource/src/main/java/org/darwin/shardingDataSource/transaction/ShardingTransactionManager.java: -------------------------------------------------------------------------------- 1 | /** 2 | * org.darwin.shardingDataSource.transaction.ShardingTransactionManger.java 3 | * created by Tianxin(tianjige@163.com) on 2015年6月15日 下午1:39:43 4 | */ 5 | package org.darwin.shardingDataSource.transaction; 6 | 7 | import javax.sql.DataSource; 8 | 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 12 | 13 | /** 14 | * 15 | * created by Tianxin on 2015年6月15日 下午1:39:43 16 | */ 17 | public class ShardingTransactionManager extends DataSourceTransactionManager { 18 | /** 19 | * 20 | * created by Tianxin on 2015年6月15日 下午1:41:36 21 | */ 22 | private static final long serialVersionUID = 1L; 23 | /** 24 | * 默认生成的该类的LOG记录器,使用slf4j组件。避免产生编译警告,使用protected修饰符。 25 | */ 26 | protected final static Logger LOG = LoggerFactory.getLogger(ShardingTransactionManager.class); 27 | 28 | @Override 29 | public void setDataSource(DataSource dataSource) { 30 | super.setDataSource(dataSource); 31 | } 32 | } 33 | --------------------------------------------------------------------------------