对于 Leaf——美团点评分布式ID生成系统 中介绍的 Leaf-segment数据库方案 生成唯一orderId的方案的一个实现。 在实现中使用双buffer优化,在第一个buffer使用50%的时候去加载另一个buffer的数据,这里分同步与异步两种方式,默认是同步加载。对于异步增加参数asynLoadingSegment 设为true. 在第一个buffer使用完毕之后,切换到另一个buffer,需要去验证该buffer是否加载完成数据,然后进行切换(对于异步加载出了异常则同步加载数据,然后再切换,此时会产生发号的阻塞)。
<bean id="idLeafService" class="com.zhuzhong.idleaf.support.MysqlIdLeafServiceImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
<property name="asynLoadingSegment" value="true" />
<property name="bizTag" value="order"></property>
</bean>
Long id=idLeafService.getId()
<bean id="parentIdLeafService" abstract="true" class="com.zhuzhong.idleaf.support.MysqlIdLeafServiceImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
<property name="asynLoadingSegment" value="true" />
</bean>
<bean id="productIdLeafService" parent="parentIdLeafService">
<property name="bizTag" value="product"></property>
</bean>
<bean id="orderIdLeafService" parent="parentIdLeafService">
<property name="bizTag" value="order"></property>
</bean>
Long orderId=orderIdLeafService.getId();
Long productId=productIdLeafService.getId();
spring 框架是无所不能,关于主键的生成它也提供了类似的功能,相应的类为org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer 但是这个类只保证单jvm的唯一性,在集群环中它会有并发更新的问题,所以我在此写了一个ExtendMySQLMaxValueIncrementer。思路还是沿袭上面的。
<bean id="extendMysqlMaxValueIncrementer" abstract="true"
class="com.zhuzhong.idleaf.support.ExtendMySQLMaxValueIncrementer">
<property name="dataSource" ref="testDataSource" />
<property name="asynLoadingSegment" value="true"></property>
<property name="incrementerName" value="id_segment" />
<property name="columnName" value="max_id" />
<property name="stepField" value="p_step" />
<property name="bizField" value="biz_tag"></property>
<property name="lastUpdateTimeField" value="last_update_time" />
<property name="updateTimeField" value="current_update_time" />
<property name="paddingLength" value="6"></property>
</bean>
<bean id="orderIncrementer" parent="extendMysqlMaxValueIncrementer">
<property name="bizTag" value="order" />
</bean>
<bean id="productNoIncrementer" parent="extendMysqlMaxValueIncrementer">
<property name="bizTag" value="productNo" />
</bean>
@Autowired
@Qualifier("productNoIncrementer")
private DataFieldMaxValueIncrementer incrementer;
@Test
public void test() {
int i = 0;
while (i < 10) {
System.out.println("long id=" + incrementer.nextLongValue());
System.out.println("int id=" + incrementer.nextIntValue());
System.out.println("string id=" + incrementer.nextStringValue());
i++;
}
}
spring 帮我们提供了三个接口,分别为获取int,long,string 三种数据类型。当然这种方式需要深度使用spring-jdbc框架.
基因法生成id,主要思路来自架构师之路 实现接口com.zhuzhong.idleaf.WithGeneIdLeafService 使用示例
<bean id="idLeafService" class="com.zhuzhong.idleaf.support.MysqlIdLeafServiceImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
<property name="asynLoadingSegment" value="true" />
<property name="bizTag" value="order"></property>
</bean>
<bean id="withGeneIdLeafService" class="com.zhuzhong.idleaf.support.WithGeneIdLeafServiceImpl">
<property name="idLeafService" ref="idLeafService" />
<property name="dbSize" value="32" />
</bean>
Long orderId=withGeneIdLeafService.getId(10000L)