TDDL实践
使用入门-数据源配置
- 数据源配置,tddl的入口,从datasource切入
- <bean id="tddlDataSource" class="com.taobao.tddl.client.jdbc.TDataSource" init-method="init">
- <property name="appName" value="tddl_sample" />
- <property name="dynamicRule" value="true"/>
- </bean>
- Sequence生成器
- <bean id="seqStudent" class="com.taobao.tddl.client.sequence.impl.GroupSequence" init-method="init">
- <property name="sequenceDao" ref="idSequenceDao" />
- <property name="name" value="seq_Student" />
- </bean>
- 指定静态文件,3.0以后支持动态推送
- <bean id="myDataSource" class="com.taobao.tddl.client.jdbc.TDataSource" init-method="init">
- <property name="appName" value="tddl_sample"/>
- <property name="appRuleFile" value="classpath:tddl-rule.xml"/>
- <property name="useLocalConfig" value="true"/>
- </bean>
myDataSource--分库分表数据源
appName--数据库代号从dba获得
appRuleFile--分库分表配置文件
useLocalConfig--使用本地配置
- Sequence配置: tddl-sequence.xml
- <bean id="sequenceDao" class="com.taobao.tddl.client.sequence.impl.GroupSequenceDao" init-method="init">
- <!-- appName,必填 -->
- <property name="appName" value="CUNTAO_SUPPLIER_APP" />
- <!-- 数据源的个数 -->
- <property name="dscount" value="1" />
- <!-- dbGroupKeys 必填 -->
- <!-- 如果在末尾插入"-OFF",该源将被关掉,该源占据的SQL段会被保留" -->
- <!-- 当dbGroupKeys中配置的个数小于dbcount的值的时候,默认配置了"-OFF"的源 -->
- <property name="dbGroupKeys">
- <list>
- <value>CUNTAO_SUPPLIER_BODY00_GROUP</value>
- </list>
- </property>
- <!-- 内步长 ,默认为1000,取值在1-100000之间 -->
- <property name="innerStep" value="500" />
- <!-- 重试次数,在多个groupDataSource的场景下,建议设置成1-2次。默认为2次 -->
- <property name="retryTimes" value="2" />
- <!-- sequence表的表名 -->
- <property name="tableName" value="cuntao_supplier_sequence" />
- <!-- 自适应开关 ,默认为false -->
- <property name="adjust" value="true" />
- </bean>
TDDL分库分表配置bean
tddl-rule.xml
- <?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:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
- <bean id="vtabroot" class="com.taobao.tddl.interact.rule.VirtualTableRoot" init-method="init">
- <property name="defaultDbIndex" value="CUNTAO_SUPPLIER_GROUP"/>
- <property name="dbType" value="MYSQL"/>
- <property name="tableRules">
- <map>
- <entry key="cuntao_purchase_order" value-ref="cuntao_purchase_order_bean"/>
- <entry key="cuntao_sub_purchase_order" value-ref="cuntao_sub_purchase_order_bean"/>
- <entry key="cuntao_logistics_order" value-ref="cuntao_logistics_order_bean"/>
- <entry key="cuntao_sub_logistics_order" value-ref="cuntao_sub_logistics_order_bean"/>
- </map>
- </property>
- </bean>
- <bean id="cuntao_purchase_order_bean" class="com.taobao.tddl.interact.rule.TableRule">
- <property name="dbNamePattern" value="CUNTAO_SUPPLIER_BODY{00}_GROUP"/>
- <property name="dbRuleArray">
- <value>(#supplier_id,1,256#.longValue() % 10000 % 256).intdiv(32)</value>
- </property>
- <property name="tbNamePattern" value="cuntao_purchase_order_{0000}" />
- <property name="tbRuleArray">
- <value>#supplier_id,1,256#.longValue() % 10000 % 256</value>
- </property>
- </bean>
- </beans>
配置项说明
分表总配置VirtualTableRoot:
其中,defaultDbIndex是appgroup,从DBA获取;dbType,数据库类型;tableRules引入各个表的配置
分库分表配置TableRule;其中,dbNamePattern分库规则,大括号会替换成dbRuleArray中的值.
dbRuleArray,分库计算方法,(#supplier_id,1,256#.longValue() % 10000 % 256).intdiv(32)表示以supplier_id为分表键,256张表,8个库所以除以32,我们计算规则取后四位计算所以先模10000.
tbNamePattern分表规则,大括号会替换成tbRuleArray中的值。
dbRuleArray,分表计算方法,#supplier_id,1,256#.longValue() % 10000 % 256 就是分库计算方法不除以32.
sequence生成bean
我们用的sequence是一个单库单表的数据库,即每次使用GroupSequence获取新的seq值来计算id,保证全局各个表不会发生id冲突。
appName,从DBA获得。
dbGroupKeys,所在库名称
tableName,sequence表名,可以使用一个sequence表来计算多个表的id,因为每个表实际只占用一行数据。
name,目标表在sequence表中的key,一般取表名,其实是任意的。
- DefaultSequenceDao源码
- public class DefaultSequenceDao implements SequenceDao
- {
- private static final Log log = LogFactory.getLog(DefaultSequenceDao.class);
- private static final int MIN_STEP = 1;
- private static final int MAX_STEP = 100000;
- private static final int DEFAULT_STEP = 1000;
- private static final int DEFAULT_RETRY_TIMES = 150;
- private static final String DEFAULT_TABLE_NAME = "sequence";
- private static final String DEFAULT_NAME_COLUMN_NAME = "name";
- private static final String DEFAULT_VALUE_COLUMN_NAME = "value";
- private static final String DEFAULT_GMT_MODIFIED_COLUMN_NAME = "gmt_modified";
- private static final long DELTA = 100000000L;
- private DataSource dataSource;
- private int retryTimes = 150;
- private int step = 1000;
- private String tableName = "sequence";
- private String nameColumnName = "name";
- private String valueColumnName = "value";
- private String gmtModifiedColumnName = "gmt_modified";
- private volatile String selectSql;
- private volatile String updateSql;
- public SequenceRange nextRange(String name)
- throws SequenceException
- {
- if (name == null) {
- throw new IllegalArgumentException("序列名称不能为空");
- }
- Connection conn = null;
- PreparedStatement stmt = null;
- ResultSet rs = null;
- for (int i = 0; i < this.retryTimes + 1; i++) { long oldValue;
- long newValue;
- try { conn = this.dataSource.getConnection();
- stmt = conn.prepareStatement(getSelectSql());
- stmt.setString(1, name);
- rs = stmt.executeQuery();
- rs.next();
- oldValue = rs.getLong(1);
- if (oldValue < 0L) {
- StringBuilder message = new StringBuilder();
- message.append("Sequence value cannot be less than zero, value = ").append(oldValue);
- message.append(", please check table ").append(getTableName());
- throw new SequenceException(message.toString());
- }
- if (oldValue > 9223372036754775807L) {
- StringBuilder message = new StringBuilder();
- message.append("Sequence value overflow, value = ").append(oldValue);
- message.append(", please check table ").append(getTableName());
- throw new SequenceException(message.toString());
- }
- newValue = oldValue + getStep();
- } catch (SQLException e) {
- throw new SequenceException(e);
- } finally {
- closeResultSet(rs);
- rs = null;
- closeStatement(stmt);
- stmt = null;
- closeConnection(conn);
- conn = null;
- }
- try
- {
- conn = this.dataSource.getConnection();
- stmt = conn.prepareStatement(getUpdateSql());
- stmt.setLong(1, newValue);
- stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
- stmt.setString(3, name);
- stmt.setLong(4, oldValue);
- int affectedRows = stmt.executeUpdate();
- if (affectedRows == 0)
- {
- closeStatement(stmt);
- stmt = null;
- closeConnection(conn);
- conn = null;
- }
- else
- {
- return new SequenceRange(oldValue + 1L, newValue);
- }
- } catch (SQLException e) { throw new SequenceException(e);
- } finally {
- closeStatement(stmt);
- stmt = null;
- closeConnection(conn);
- conn = null;
- }
- }
- throw new SequenceException("Retried too many times, retryTimes = " + this.retryTimes);
- }
- private String getSelectSql() {
- if (this.selectSql == null) {
- synchronized (this) {
- if (this.selectSql == null) {
- StringBuilder buffer = new StringBuilder();
- buffer.append("select ").append(getValueColumnName());
- buffer.append(" from ").append(getTableName());
- buffer.append(" where ").append(getNameColumnName()).append(" = ?");
- this.selectSql = buffer.toString();
- }
- }
- }
- return this.selectSql;
- }
- private String getUpdateSql() {
- if (this.updateSql == null) {
- synchronized (this) {
- if (this.updateSql == null) {
- StringBuilder buffer = new StringBuilder();
- buffer.append("update ").append(getTableName());
- buffer.append(" set ").append(getValueColumnName()).append(" = ?, ");
- buffer.append(getGmtModifiedColumnName()).append(" = ? where ");
- buffer.append(getNameColumnName()).append(" = ? and ");
- buffer.append(getValueColumnName()).append(" = ?");
- this.updateSql = buffer.toString();
- }
- }
- }
- return this.updateSql;
- }
- private static void closeResultSet(ResultSet rs) {
- if (rs != null)
- try {
- rs.close();
- } catch (SQLException e) {
- log.debug("Could not close JDBC ResultSet", e);
- } catch (Throwable e) {
- log.debug("Unexpected exception on closing JDBC ResultSet", e);
- }
- }
- private static void closeStatement(Statement stmt)
- {
- if (stmt != null)
- try {
- stmt.close();
- } catch (SQLException e) {
- log.debug("Could not close JDBC Statement", e);
- } catch (Throwable e) {
- log.debug("Unexpected exception on closing JDBC Statement", e);
- }
- }
- private static void closeConnection(Connection conn)
- {
- if (conn != null)
- try {
- conn.close();
- } catch (SQLException e) {
- log.debug("Could not close JDBC Connection", e);
- } catch (Throwable e) {
- log.debug("Unexpected exception on closing JDBC Connection", e);
- }
- }
- ...
- GroupSequenceDao源码
- public class GroupSequenceDao implements SequenceDao
- {
- private static final Log log = LogFactory.getLog(GroupSequenceDao.class);
- private static final int MIN_STEP = 1;
- private static final int MAX_STEP = 100000;
- private static final int DEFAULT_INNER_STEP = 1000;
- private static final int DEFAULT_RETRY_TIMES = 2;
- private static final String DEFAULT_TABLE_NAME = "sequence";
- private static final String DEFAULT_NAME_COLUMN_NAME = "name";
- private static final String DEFAULT_VALUE_COLUMN_NAME = "value";
- private static final String DEFAULT_GMT_MODIFIED_COLUMN_NAME = "gmt_modified";
- private static final int DEFAULT_DSCOUNT = 2;
- private static final Boolean DEFAULT_ADJUST = Boolean.valueOf(false);
- private static final long DELTA = 100000000L;
- private String appName;
- private List<String> dbGroupKeys;
- private Map<String, DataSource> dataSourceMap;
- private boolean adjust = DEFAULT_ADJUST.booleanValue();
- private int retryTimes = 2;
- private int dscount = 2;
- private int innerStep = 1000;
- private int outStep = 1000;
- private String tableName = "sequence";
- private String nameColumnName = "name";
- private String valueColumnName = "value";
- private String gmtModifiedColumnName = "gmt_modified";
- private volatile String selectSql;
- private volatile String updateSql;
- private volatile String insertSql;
- private ConcurrentHashMap<Integer, AtomicInteger> excludedKeyCount = new ConcurrentHashMap(this.dscount);
- private int maxSkipCount = 10000;
- private boolean useSlowProtect = false;
- private int protectMilliseconds = 50;
- private ExecutorService exec = Executors.newFixedThreadPool(1);
- public void init()
- throws SequenceException
- {
- if (StringUtils.isEmpty(this.appName)) {
- SequenceException sequenceException = new SequenceException("appName is Null ");
- log.error("没有配置appName", sequenceException);
- throw sequenceException;
- }
- if ((this.dbGroupKeys == null) || (this.dbGroupKeys.size() == 0)) {
- log.error("没有配置dbgroupKeys");
- throw new SequenceException("dbgroupKeys为空!");
- }
- this.dataSourceMap = new HashMap();
- for (String dbGroupKey : this.dbGroupKeys)
- if (!dbGroupKey.toUpperCase().endsWith("-OFF"))
- {
- TGroupDataSource tGroupDataSource = new TGroupDataSource(dbGroupKey, this.appName);
- tGroupDataSource.init();
- this.dataSourceMap.put(dbGroupKey, tGroupDataSource);
- }
- if (this.dbGroupKeys.size() >= this.dscount)
- this.dscount = this.dbGroupKeys.size();
- else {
- for (int ii = this.dbGroupKeys.size(); ii < this.dscount; ii++) {
- this.dbGroupKeys.add(new StringBuilder().append(this.dscount).append("-OFF").toString());
- }
- }
- this.outStep = (this.innerStep * this.dscount);
- StringBuilder sb = new StringBuilder();
- sb.append("GroupSequenceDao初始化完成:\r\n ");
- sb.append("appName:").append(this.appName).append("\r\n");
- sb.append("innerStep:").append(this.innerStep).append("\r\n");
- sb.append("dataSource:").append(this.dscount).append("个:");
- for (String str : this.dbGroupKeys) {
- sb.append("[").append(str).append("]、");
- }
- sb.append("\r\n");
- sb.append("adjust:").append(this.adjust).append("\r\n");
- sb.append("retryTimes:").append(this.retryTimes).append("\r\n");
- sb.append("tableName:").append(this.tableName).append("\r\n");
- sb.append("nameColumnName:").append(this.nameColumnName).append("\r\n");
- sb.append("valueColumnName:").append(this.valueColumnName).append("\r\n");
- sb.append("gmtModifiedColumnName:").append(this.gmtModifiedColumnName).append("\r\n");
- log.info(sb.toString());
- }
- private boolean check(int index, long value)
- {
- return value % this.outStep == index * this.innerStep;
- }
- public void adjust(String name)
- throws SequenceException, SQLException
- {
- Connection conn = null;
- PreparedStatement stmt = null;
- ResultSet rs = null;
- for (int i = 0; i < this.dbGroupKeys.size(); i++)
- if (!((String)this.dbGroupKeys.get(i)).toUpperCase().endsWith("-OFF"))
- {
- TGroupDataSource tGroupDataSource = (TGroupDataSource)this.dataSourceMap.get(this.dbGroupKeys.get(i));
- try
- {
- conn = tGroupDataSource.getConnection();
- stmt = conn.prepareStatement(getSelectSql());
- stmt.setString(1, name);
- GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
- rs = stmt.executeQuery();
- int item = 0;
- while (rs.next()) {
- item++;
- long val = rs.getLong(getValueColumnName());
- if (!check(i, val))
- {
- if (isAdjust()) {
- adjustUpdate(i, val, name);
- } else {
- log.error("数据库中配置的初值出错!请调整你的数据库,或者启动adjust开关");
- throw new SequenceException("数据库中配置的初值出错!请调整你的数据库,或者启动adjust开关");
- }
- }
- }
- if (item == 0)
- {
- if (isAdjust()) {
- adjustInsert(i, name);
- } else {
- log.error("数据库中未配置该sequence!请往数据库中插入sequence记录,或者启动adjust开关");
- throw new SequenceException("数据库中未配置该sequence!请往数据库中插入sequence记录,或者启动adjust开关");
- }
- }
- }
- catch (SQLException e) {
- log.error("初值校验和自适应过程中出错.", e);
- throw e;
- } finally {
- closeResultSet(rs);
- rs = null;
- closeStatement(stmt);
- stmt = null;
- closeConnection(conn);
- conn = null;
- }
- }
- }
- private void adjustUpdate(int index, long value, String name)
- throws SequenceException, SQLException
- {
- long newValue = value - value % this.outStep + this.outStep + index * this.innerStep;
- TGroupDataSource tGroupDataSource = (TGroupDataSource)this.dataSourceMap.get(this.dbGroupKeys.get(index));
- Connection conn = null;
- PreparedStatement stmt = null;
- ResultSet rs = null;
- try {
- conn = tGroupDataSource.getConnection();
- stmt = conn.prepareStatement(getUpdateSql());
- stmt.setLong(1, newValue);
- stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
- stmt.setString(3, name);
- stmt.setLong(4, value);
- GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
- int affectedRows = stmt.executeUpdate();
- if (affectedRows == 0) {
- throw new SequenceException(new StringBuilder().append("faild to auto adjust init value at ").append(name).append(" update affectedRow =0").toString());
- }
- log.info(new StringBuilder().append((String)this.dbGroupKeys.get(index)).append("更新初值成功!").append("sequence Name:").append(name).append("更新过程:").append(value).append("-->").append(newValue).toString());
- }
- catch (SQLException e) {
- log.error(new StringBuilder().append("由于SQLException,更新初值自适应失败!dbGroupIndex:").append((String)this.dbGroupKeys.get(index)).append(",sequence Name:").append(name).append("更新过程:").append(value).append("-->").append(newValue).toString(), e);
- throw new SequenceException(new StringBuilder().append("由于SQLException,更新初值自适应失败!dbGroupIndex:").append((String)this.dbGroupKeys.get(index)).append(",sequence Name:").append(name).append("更新过程:").append(value).append("-->").append(newValue).toString(), e);
- }
- finally
- {
- closeStatement(stmt);
- stmt = null;
- closeConnection(conn);
- conn = null;
- }
- }
- private void adjustInsert(int index, String name)
- throws SequenceException, SQLException
- {
- TGroupDataSource tGroupDataSource = (TGroupDataSource)this.dataSourceMap.get(this.dbGroupKeys.get(index));
- long newValue = index * this.innerStep;
- Connection conn = null;
- PreparedStatement stmt = null;
- ResultSet rs = null;
- try {
- conn = tGroupDataSource.getConnection();
- stmt = conn.prepareStatement(getInsertSql());
- stmt.setString(1, name);
- stmt.setLong(2, newValue);
- stmt.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
- GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
- int affectedRows = stmt.executeUpdate();
- if (affectedRows == 0) {
- throw new SequenceException(new StringBuilder().append("faild to auto adjust init value at ").append(name).append(" update affectedRow =0").toString());
- }
- log.info(new StringBuilder().append((String)this.dbGroupKeys.get(index)).append(" name:").append(name).append("插入初值:").append(name).append("value:").append(newValue).toString());
- }
- catch (SQLException e)
- {
- log.error(new StringBuilder().append("由于SQLException,插入初值自适应失败!dbGroupIndex:").append((String)this.dbGroupKeys.get(index)).append(",sequence Name:").append(name).append(" value:").append(newValue).toString(), e);
- throw new SequenceException(new StringBuilder().append("由于SQLException,插入初值自适应失败!dbGroupIndex:").append((String)this.dbGroupKeys.get(index)).append(",sequence Name:").append(name).append(" value:").append(newValue).toString(), e);
- }
- finally
- {
- closeResultSet(rs);
- rs = null;
- closeStatement(stmt);
- stmt = null;
- closeConnection(conn);
- conn = null;
- }
- }
- public SequenceRange nextRange(final String name)
- throws SequenceException
- {
- if (name == null) {
- log.error("序列名为空!");
- throw new IllegalArgumentException("序列名称不能为空");
- }
- Connection conn = null;
- PreparedStatement stmt = null;
- ResultSet rs = null;
- int[] randomIntSequence = RandomSequence.randomIntSequence(this.dscount);
- for (int i = 0; i < this.retryTimes; i++) {
- for (int j = 0; j < this.dscount; j++) {
- boolean readSuccess = false;
- boolean writeSuccess = false;
- int index = randomIntSequence[j];
- if (!((String)this.dbGroupKeys.get(index)).toUpperCase().endsWith("-OFF"))
- {
- if (this.excludedKeyCount.get(Integer.valueOf(index)) != null) {
- if (((AtomicInteger)this.excludedKeyCount.get(Integer.valueOf(index))).incrementAndGet() > this.maxSkipCount) {
- this.excludedKeyCount.remove(Integer.valueOf(index));
- log.error(new StringBuilder().append(this.maxSkipCount).append("次数已过,index为").append(index).append("的数据源后续重新尝试取序列").toString());
- }
- }
- else
- {
- final TGroupDataSource tGroupDataSource = (TGroupDataSource)this.dataSourceMap.get(this.dbGroupKeys.get(index));
- long oldValue;
- long newValue;
- try
- {
- long oldValue;
- if ((!this.useSlowProtect) || (this.excludedKeyCount.size() >= this.dscount - 1)) {
- conn = tGroupDataSource.getConnection();
- stmt = conn.prepareStatement(getSelectSql());
- stmt.setString(1, name);
- GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
- rs = stmt.executeQuery();
- rs.next();
- oldValue = rs.getLong(1);
- } else {
- FutureTask future = new FutureTask(new Callable()
- {
- public Long call() throws Exception
- {
- Connection fconn = null;
- PreparedStatement fstmt = null;
- ResultSet frs = null;
- try {
- fconn = tGroupDataSource.getConnection();
- fstmt = fconn.prepareStatement(GroupSequenceDao.this.getSelectSql());
- fstmt.setString(1, name);
- GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
- frs = fstmt.executeQuery();
- frs.next();
- return Long.valueOf(frs.getLong(1));
- } finally {
- GroupSequenceDao.closeResultSet(frs);
- frs = null;
- GroupSequenceDao.closeStatement(fstmt);
- fstmt = null;
- GroupSequenceDao.closeConnection(fconn);
- fconn = null;
- }
- }
- });
- try
- {
- this.exec.submit(future);
- oldValue = ((Long)future.get(this.protectMilliseconds, TimeUnit.MILLISECONDS)).longValue();
- } catch (InterruptedException e) {
- throw new SQLException("[SEQUENCE SLOW-PROTECTED MODE]:InterruptedException", e);
- } catch (ExecutionException e) {
- throw new SQLException("[SEQUENCE SLOW-PROTECTED MODE]:ExecutionException", e);
- } catch (TimeoutException e) {
- throw new SQLException(new StringBuilder().append("[SEQUENCE SLOW-PROTECTED MODE]:TimeoutException,当前设置超时时间为").append(this.protectMilliseconds).toString(), e);
- }
- }
- if (oldValue < 0L) {
- StringBuilder message = new StringBuilder();
- message.append("Sequence value cannot be less than zero, value = ").append(oldValue);
- message.append(", please check table ").append(getTableName());
- log.info(message);
- closeResultSet(rs);
- rs = null;
- closeStatement(stmt);
- stmt = null;
- closeConnection(conn);
- conn = null; continue;
- }
- if (oldValue > 9223372036754775807L) {
- StringBuilder message = new StringBuilder();
- message.append("Sequence value overflow, value = ").append(oldValue);
- message.append(", please check table ").append(getTableName());
- log.info(message);
- closeResultSet(rs);
- rs = null;
- closeStatement(stmt);
- stmt = null;
- closeConnection(conn);
- conn = null; continue;
- }
- newValue = oldValue + this.outStep;
- if (!check(index, newValue))
- {
- if (isAdjust()) {
- newValue = newValue - newValue % this.outStep + this.outStep + index * this.innerStep;
- }
- else {
- SequenceException sequenceException = new SequenceException(new StringBuilder().append((String)this.dbGroupKeys.get(index)).append(":").append(name).append("的值得错误,覆盖到其他范围段了!请修改数据库,或者开启adjust开关!").toString());
- log.error(new StringBuilder().append((String)this.dbGroupKeys.get(index)).append(":").append(name).append("的值得错误,覆盖到其他范围段了!请修改数据库,或者开启adjust开关!").toString(), sequenceException);
- throw sequenceException;
- }
- }
- closeResultSet(rs);
- rs = null;
- closeStatement(stmt);
- stmt = null;
- closeConnection(conn);
- conn = null;
- }
- catch (SQLException e)
- {
- log.error(new StringBuilder().append("取范围过程中--查询出错!").append((String)this.dbGroupKeys.get(index)).append(":").append(name).toString(), e);
- if (this.excludedKeyCount.size() < this.dscount - 1) {
- this.excludedKeyCount.put(Integer.valueOf(index), new AtomicInteger(0));
- log.error(new StringBuilder().append("暂时踢除index为").append(index).append("的数据源,").append(this.maxSkipCount).append("次后重新尝试").toString());
- }
- }
- finally
- {
- closeResultSet(rs);
- rs = null;
- closeStatement(stmt);
- stmt = null;
- closeConnection(conn);
- conn = null;
- }
- try
- {
- conn = tGroupDataSource.getConnection();
- stmt = conn.prepareStatement(getUpdateSql());
- stmt.setLong(1, newValue);
- stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
- stmt.setString(3, name);
- stmt.setLong(4, oldValue);
- GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
- int affectedRows = stmt.executeUpdate();
- if (affectedRows == 0)
- {
- closeStatement(stmt);
- stmt = null;
- closeConnection(conn);
- conn = null;
- }
- else
- {
- closeStatement(stmt);
- stmt = null;
- closeConnection(conn);
- conn = null;
- }
- }
- catch (SQLException e)
- {
- log.error(new StringBuilder().append("取范围过程中--更新出错!").append((String)this.dbGroupKeys.get(index)).append(":").append(name).toString(), e);
- }
- finally
- {
- closeStatement(stmt);
- stmt = null;
- closeConnection(conn);
- conn = null;
- }
- }
- }
- }
- if (i == this.retryTimes - 2) {
- this.excludedKeyCount.clear();
- }
- }
- log.error(new StringBuilder().append("所有数据源都不可用!且重试").append(this.retryTimes).append("次后,仍然失败!").toString());
- throw new SequenceException("All dataSource faild to get value!");
- }
- private String getInsertSql() {
- if (this.insertSql == null) {
- synchronized (this) {
- if (this.insertSql == null) {
- StringBuilder buffer = new StringBuilder();
- buffer.append("insert into ").append(getTableName()).append("(");
- buffer.append(getNameColumnName()).append(",");
- buffer.append(getValueColumnName()).append(",");
- buffer.append(getGmtModifiedColumnName()).append(") values(?,?,?);");
- this.insertSql = buffer.toString();
- }
- }
- }
- return this.insertSql;
- }
- private String getSelectSql() {
- if (this.selectSql == null) {
- synchronized (this) {
- if (this.selectSql == null) {
- StringBuilder buffer = new StringBuilder();
- buffer.append("select ").append(getValueColumnName());
- buffer.append(" from ").append(getTableName());
- buffer.append(" where ").append(getNameColumnName()).append(" = ?");
- this.selectSql = buffer.toString();
- }
- }
- }
- return this.selectSql;
- }
- private String getUpdateSql() {
- if (this.updateSql == null) {
- synchronized (this) {
- if (this.updateSql == null) {
- StringBuilder buffer = new StringBuilder();
- buffer.append("update ").append(getTableName());
- buffer.append(" set ").append(getValueColumnName()).append(" = ?, ");
- buffer.append(getGmtModifiedColumnName()).append(" = ? where ");
- buffer.append(getNameColumnName()).append(" = ? and ");
- buffer.append(getValueColumnName()).append(" = ?");
- this.updateSql = buffer.toString();
- }
- }
- }
- return this.updateSql;
- }
- private static void closeResultSet(ResultSet rs) {
- if (rs != null)
- try {
- rs.close();
- } catch (SQLException e) {
- log.debug("Could not close JDBC ResultSet", e);
- } catch (Throwable e) {
- log.debug("Unexpected exception on closing JDBC ResultSet", e);
- }
- }
- private static void closeStatement(Statement stmt)
- {
- if (stmt != null)
- try {
- stmt.close();
- } catch (SQLException e) {
- log.debug("Could not close JDBC Statement", e);
- } catch (Throwable e) {
- log.debug("Unexpected exception on closing JDBC Statement", e);
- }
- }
- private static void closeConnection(Connection conn)
- {
- if (conn != null)
- try {
- conn.close();
- } catch (SQLException e) {
- log.debug("Could not close JDBC Connection", e);
- } catch (Throwable e) {
- log.debug("Unexpected exception on closing JDBC Connection", e);
- }
- }
TDDL实践的更多相关文章
- mongodb 最佳实践
MongoDB功能预览:http://pan.baidu.com/s/1k2UfW MongoDB在赶集网的应用:http://pan.baidu.com/s/1bngxgLp MongoDB在京东的 ...
- 【大数据和云计算技术社区】分库分表技术演进&最佳实践笔记
1.需求背景 移动互联网时代,海量的用户每天产生海量的数量,这些海量数据远不是一张表能Hold住的.比如 用户表:支付宝8亿,微信10亿.CITIC对公140万,对私8700万. 订单表:美团每天几千 ...
- TDDL调研笔记
一,TDDL是什么 Taobao Distributed Data Layer,即淘宝分布式数据层,简称TDDL .它是一套分布式数据访问引擎 淘宝一个基于客户端的数据库中间件产品 基于JDBC规范, ...
- 分库分表技术演进&最佳实践
每个优秀的程序员和架构师都应该掌握分库分表,这是我的观点. 移动互联网时代,海量的用户每天产生海量的数量,比如: 用户表 订单表 交易流水表 以支付宝用户为例,8亿:微信用户更是10亿.订单表更夸张, ...
- webp图片实践之路
最近,我们在项目中实践了webp图片,并且抽离出了工具模块,整合到了项目的基础模板中.传闻IOS10也将要支持webp,那么使用webp带来的性能提升将更加明显.估计在不久的将来,webp会成为标配. ...
- Hangfire项目实践分享
Hangfire项目实践分享 目录 Hangfire项目实践分享 目录 什么是Hangfire Hangfire基础 基于队列的任务处理(Fire-and-forget jobs) 延迟任务执行(De ...
- TDD在Unity3D游戏项目开发中的实践
0x00 前言 关于TDD测试驱动开发的文章已经有很多了,但是在游戏开发尤其是使用Unity3D开发游戏时,却听不到特别多关于TDD的声音.那么本文就来简单聊一聊TDD如何在U3D项目中使用以及如何使 ...
- Logstash实践: 分布式系统的日志监控
文/赵杰 2015.11.04 1. 前言 服务端日志你有多重视? 我们没有日志 有日志,但基本不去控制需要输出的内容 经常微调日志,只输出我们想看和有用的 经常监控日志,一方面帮助日志微调,一方面及 ...
- 【大型网站技术实践】初级篇:借助Nginx搭建反向代理服务器
一.反向代理:Web服务器的“经纪人” 1.1 反向代理初印象 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从 ...
随机推荐
- UART学习之路(一)基本概念
第一篇博客,首先记录一下这一个多星期来的学习内容. UART学习之路第一篇,是UART的基本概念介绍.后续会用STM32F103的串口与PC机通信.最后使用Verilog HDL写出串口发送模块和接收 ...
- Win10系统下VirtualBox虚拟机初体验
在接触本次的VirtualBox之前,我在大一下学期参加李冬冬老师的选修课中学习过VMware,并使用VMware进行过一些计算机病毒之类的实验.但是,使用虚拟机模拟其他不同操作系统这次是第一次,因此 ...
- 【CF908G】New Year and Original Order
[CF908G]New Year and Original Order 题面 洛谷 题解 设\(f[i][j][k][l]\)表示当前在第\(i\)位有\(j\)位大于等于\(k\),当前有没有卡上界 ...
- git clone的时候报error: RPC failed; result=18错误
因业务需求,需要把内网gitlab仓库的地址对外网访问,在gitlab前端配置了一个nginx代理服务器,来实现需求,可以在git clone的时候报error: RPC failed错误 [root ...
- crontab练习题
Crontab练习题 每周一到周六的凌晨3点20分,运行tar命令对/etc/目录进行存档另存,存储位置为/backups/etc-YYYY-MM-DD.tar.gz 20 3 * * 1-6 /us ...
- unity图形圆形展开
脚本如下: using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngi ...
- 用反射或委托优化switch太长的方法
在代码进行优化的时候,发现了switch case太长,有的竟然长达30个远远超过一屏这样在代码的可读性来说很差.特别在我们看代码的时候要拉下拉框我个人觉得这是不合理的.但是我不建议有switch就进 ...
- WebGL中使用window.requestAnimationFrame创建主循环
今天总结记录一下WebGL中主循环的创建和作用.我先说明什么是主循环,其实单纯的webgl不存在主循环这个概念,这个概念是由渲染引擎引入的,主循环就是利用一个死循环或无截止条件的递归达到定时刷新can ...
- application/x-www-urlencoded与multipart/form-data
学习ajax时,学到了GET与POST两种HTTP方法,于是去W3C看了二者的区别,里面提到了二者的编码类型不同,就在网上查阅了相关资料, 在这里把我查阅到的相关结果记录在此,方便以后学习,详细了解一 ...
- Linux内核学习笔记(3)-- 进程的创建和终结
一. 进程创建: Unix 下的进程创建很特别,与许多其他操作系统不同,它分两步操作来创建和执行进程: fork() 和 exec() .首先,fork() 通过拷贝当前进程创建一个子进程:然后,ex ...