tx-lcn
tx-lcn copied to clipboard
6.0 唯一主键生成策略
框架中有两个地方需要创建唯一主键。 分别是:事务组 GroupId值的创建 与 事务日志中id的主键策略。数据类型 groupId:string id:long
groupid格式未必一定是string,也可以修改成lang类型。但是要保证全局环境中的唯一性
目前生成的策略是啥。 推荐默认使用雪花算法,还可提供接口,有使用者实现
雪花算法可以,但是需要均衡各个节点上的数据
/**
* @author lorne
* @date 2020/8/8
* @description
*/
public class IdUtils {
/**
* 创建GroupId策略
*
* @return
*/
public static String generateGroupId(){
//todo
return UUID.randomUUID().toString();
}
}
目前是直接使用的UUID.randomUUID().toString();
/** * @author lorne * @date 2020/8/8 * @description */ public class IdUtils { /** * 创建GroupId策略 * * @return */ public static String generateGroupId(){ //todo return UUID.randomUUID().toString(); } }
目前是直接使用的UUID.randomUUID().toString();
我在以下测试中发现使用雪花算法当 workId 相同时 , 会有 30% 可能生成重复的 id ,为了避免这种情况发生可能需要落库或是 使用 redis
@Test
public void theSameWorkId() throws InterruptedException {
final CountDownLatch COUNT_DOWN_LATCH = new CountDownLatch(10);
Set<Long> idSet = new HashSet<>();
IntStream.range(0, 10).forEach(i -> {
new Thread(() -> {
try {
Snowflake snowflake = IdUtils.createSnowflake(1);
IntStream.range(0, 1000).forEach(j -> {
long id = snowflake.nextId();
idSet.add(id);
});
} catch (Exception e) {
e.printStackTrace();
} finally {
COUNT_DOWN_LATCH.countDown();
}
}).start();
});
COUNT_DOWN_LATCH.await();
System.out.println(idSet.size());
Assert.isTrue(10000 == idSet.size(), "size must the same");
}
是要workId不重复就行是吗?
ObjectId就行了,24位长度也可以接受,天然的分布式id,同时也是趋势增长的,mongo就用这个.
是要workId不重复就行是吗?
~~经试验,workId 不重复就行了, 假设有2个机子有 tc ,workId 相同的概率 也不过是 1/1024,id相同的概率也不会很大~~
ObjectId就行了,24位长度也可以接受,天然的分布式id,同时也是趋势增长的,mongo就用这个.
试了下,效果还可以,除非极端情况,会有些许误差
@Test
public void theSameObjectId() throws InterruptedException {
final CountDownLatch COUNT_DOWN_LATCH = new CountDownLatch(2);
Set<String> idSet = new HashSet<>();
IntStream.range(0, 2).forEach(i -> {
new Thread(() -> {
try {
IntStream.range(0, 10000).forEach(j -> {
String id = ObjectId.next();
idSet.add(id);
});
} catch (Exception e) {
e.printStackTrace();
} finally {
COUNT_DOWN_LATCH.countDown();
}
}).start();
});
COUNT_DOWN_LATCH.await();
System.out.println(idSet.size());//19969
Assert.isTrue(20000 == idSet.size(), "size must the same");
}
那可以这样来设计 当tc链接到tm以后,由tm来分给workid,workid的自增策略由tm来控制,为了实现全局数据统一可讲workid值记录在tm的redis下。
那可以这样来设计 当tc链接到tm以后,由tm来分给workid,workid的自增策略由tm来控制,为了实现全局数据统一可讲workid值记录在tm的redis下。
正有此意,虽然做法稍微比 ObjectId 的方式复杂些