使用入门-数据源配置

  • 数据源配置,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实践的更多相关文章

  1. mongodb 最佳实践

    MongoDB功能预览:http://pan.baidu.com/s/1k2UfW MongoDB在赶集网的应用:http://pan.baidu.com/s/1bngxgLp MongoDB在京东的 ...

  2. 【大数据和云计算技术社区】分库分表技术演进&最佳实践笔记

    1.需求背景 移动互联网时代,海量的用户每天产生海量的数量,这些海量数据远不是一张表能Hold住的.比如 用户表:支付宝8亿,微信10亿.CITIC对公140万,对私8700万. 订单表:美团每天几千 ...

  3. TDDL调研笔记

    一,TDDL是什么 Taobao Distributed Data Layer,即淘宝分布式数据层,简称TDDL .它是一套分布式数据访问引擎 淘宝一个基于客户端的数据库中间件产品 基于JDBC规范, ...

  4. 分库分表技术演进&最佳实践

    每个优秀的程序员和架构师都应该掌握分库分表,这是我的观点. 移动互联网时代,海量的用户每天产生海量的数量,比如: 用户表 订单表 交易流水表 以支付宝用户为例,8亿:微信用户更是10亿.订单表更夸张, ...

  5. webp图片实践之路

    最近,我们在项目中实践了webp图片,并且抽离出了工具模块,整合到了项目的基础模板中.传闻IOS10也将要支持webp,那么使用webp带来的性能提升将更加明显.估计在不久的将来,webp会成为标配. ...

  6. Hangfire项目实践分享

    Hangfire项目实践分享 目录 Hangfire项目实践分享 目录 什么是Hangfire Hangfire基础 基于队列的任务处理(Fire-and-forget jobs) 延迟任务执行(De ...

  7. TDD在Unity3D游戏项目开发中的实践

    0x00 前言 关于TDD测试驱动开发的文章已经有很多了,但是在游戏开发尤其是使用Unity3D开发游戏时,却听不到特别多关于TDD的声音.那么本文就来简单聊一聊TDD如何在U3D项目中使用以及如何使 ...

  8. Logstash实践: 分布式系统的日志监控

    文/赵杰 2015.11.04 1. 前言 服务端日志你有多重视? 我们没有日志 有日志,但基本不去控制需要输出的内容 经常微调日志,只输出我们想看和有用的 经常监控日志,一方面帮助日志微调,一方面及 ...

  9. 【大型网站技术实践】初级篇:借助Nginx搭建反向代理服务器

    一.反向代理:Web服务器的“经纪人” 1.1 反向代理初印象 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从 ...

随机推荐

  1. 加分项——C语言实现Linux的pwd命令

    加分项--C语言实现Linux的pwd命令 实现要求 1 学习pwd命令 2 研究pwd实现需要的系统调用(man -k; grep),写出伪代码 3 实现mypwd 4 测试mypwd pwd pw ...

  2. 20155338 2016-2017-2 《Java程序设计》第3周学习总结

    20155338 2016-2017-2 <Java程序设计>第3周学习总结 教材学习内容总结 本周学习量比较多,但是知识点并不是特别难,学习了书本的第四五章,其中个人重点学习了数组对象. ...

  3. 优步UBER司机全国各地奖励政策汇总 (4月18日-4月24日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  4. 【转载】Direct3D纹理映射

    原文:Direct3D纹理映射 更详细的文章:DirectX中的纹理映射相关技术 (转)   创建纹理对象 1: HRESULT CreateTexture( 2:   UINT Width,//宽度 ...

  5. Azkaban 工作流调度器

    Azkaban 工作流调度器 1 概述 1.1 为什么需要工作流调度系统 a)一个完整的数据分析系统通常都是由大量任务单元组成,shell脚本程序,java程序,mapreduce程序.hive脚本等 ...

  6. Windows网络通信(二):socket异步编程

    简述 这里使用的API和同步编程的API是差不多的,只多了一个ioctlsocket和select函数.这里面涉及一个很重要的结构体fd_set.这里用到的API大部分都是windows和linux通 ...

  7. Ubuntu 16.04 主题美化及常用软件安装

    一.主题美化 系统清理 系统更新: 安装完系统之后,需要更新一些补丁.Ctrl+Alt+T调出终端,执行一下代码: sudo apt-get update sudo apt-get upgrade 卸 ...

  8. 高可用Kubernetes集群-10. 部署kube-proxy

    十二.部署kube-proxy 1. 创建kube-proxy证书 1)创建kube-proxy证书签名请求 # kube-proxy提取CN作为客户端的用户名,即system:kube-proxy. ...

  9. Python基础灬异常

    异常&异常处理 异常!=错误 在程序运行过程中,总会遇到各种各样的错误. 有的错误是程序编写有问题造成的,比如本来应该输出整数结果输出了字符串,这种错误我们通常称之为bug,bug是必须修复的 ...

  10. java运行时内存分类

    主要有java栈(虚拟机栈), 堆 ,方法区. 线程私有: 栈: 每个方法执行的时候 都会同时创建一个栈桢 Stack Frame 用于存储  局部变量表, 操作数栈,动态链接, 方法出口等信息 线程 ...