Giter Site home page Giter Site logo

tinyid's Introduction

Tinyid

license PRs Welcome

Tinyid is a ID Generator Service. It provides a REST API and a java client for getting ids. Over 10 million QPS per single instance when using the java client. Support jdk version 1.7+

Getting started

中文wiki

Clone code

git clone https://github.com/didi/tinyid.git

Create table

cd tinyid/tinyid-server/ && create table with db.sql (mysql)

Config db

cd tinyid-server/src/main/resources/offline
vi application.properties

datasource.tinyid.names=primary

datasource.tinyid.primary.driver-class-name=com.mysql.jdbc.Driver
datasource.tinyid.primary.url=jdbc:mysql://ip:port/databaseName?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
datasource.tinyid.primary.username=root
datasource.tinyid.primary.password=123456

Start tinyid-server

cd tinyid-server/
sh build.sh offline
java -jar output/tinyid-server-xxx.jar

REST API

nextId:
curl 'http://localhost:9999/tinyid/id/nextId?bizType=test&token=0f673adf80504e2eaa552f5d791b644c'
response:{"data":[2],"code":200,"message":""}

nextId Simple:
curl 'http://localhost:9999/tinyid/id/nextIdSimple?bizType=test&token=0f673adf80504e2eaa552f5d791b644c'
response: 3

with batchSize:
curl 'http://localhost:9999/tinyid/id/nextIdSimple?bizType=test&token=0f673adf80504e2eaa552f5d791b644c&batchSize=10'
response: 4,5,6,7,8,9,10,11,12,13

Get nextId like 1,3,5,7,9...
bizType=test_odd : delta is 2 and remainder is 1
curl 'http://localhost:9999/tinyid/id/nextIdSimple?bizType=test_odd&batchSize=10&token=0f673adf80504e2eaa552f5d791b644c'
response: 3,5,7,9,11,13,15,17,19,21

Java client (Recommended)

Maven dependency

<dependency>
    <groupId>com.xiaoju.uemc.tinyid</groupId>
    <artifactId>tinyid-client</artifactId>
    <version>${tinyid.version}</version>
</dependency>

Create tinyid_client.properties in your classpath

tinyid_client.properties:

tinyid.server=localhost:9999
tinyid.token=0f673adf80504e2eaa552f5d791b644c

#(tinyid.server=localhost:9999/gateway,ip2:port2/prefix,...)

Java Code

Long id = TinyId.nextId("test");
List<Long> ids = TinyId.nextId("test", 10);

Communication

Tinyid Community

Contributing

Welcome to contribute by creating issues or sending pull requests. See Contributing Guide for guidelines.

License

Tinyid is licensed under the Apache License 2.0. See the LICENSE file.

Note

This is not an official Didi product (experimental or otherwise), it is just code that happens to be owned by Didi.

tinyid's People

Contributors

automvc avatar duimba avatar fantasypig avatar lookingatstarts avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tinyid's Issues

有个非常严重的Bug

在动态数据源DynamicDataSource类中determineCurrentLookupKey,每次都是随机选择真实的DataSource,但是在DbSegmentIdServiceImpl.getNextSegmentId方法中使用了乐观锁,每获取一个SegmentInfo都存在query 以及 update 数据的动作,所以query和update可能操作的不是同一张表

DbSegmentIdServiceImpl的retry全局变量

单例的DbSegmentIdServiceImpl的retry全局变量,最好搞成常量,大写。

IdController 中 idGeneratorFactoryServer.getIdGenerator(bizType) 每次返回的都是新的CachedIdGenerator的实例,而你在这个实例里搞了(实例)锁,起不到对数据库(version冲突)减压的效果。应该锁 “bizType”

Tinyid-Server查询db最新号段的事务使用方式存在疑问

DbSegmentIdServiceImpl类查询db最新号段
@Transactional(isolation = Isolation.READ_COMMITTED) public SegmentId getNextSegmentId(String bizType) { // 获取nextTinyId的时候,有可能存在version冲突,需要重试 for (int i = 0; i < Constants.RETRY; i++) { TinyIdInfo tinyIdInfo = tinyIdInfoDAO.queryByBizType(bizType); ...... int row = tinyIdInfoDAO.updateMaxId(tinyIdInfo.getId(), newMaxId, oldMaxId, tinyIdInfo.getVersion(), tinyIdInfo.getBizType()); ..... } throw new TinyIdSysException("get next segmentId conflict"); }
1、查询db获取最新号段的确需要做容错重试,重试的逻辑应该是在更上层service业务做的,这里service只做单一的更新号段逻辑。
2、如果在上层service做重试,这里查询和更新操作可以不放在同一个事务中,如果考虑到同一个事务使用同一个mysql连接成本更低,这里就不用使用读已提交的隔离级别了。

为啥引入tinyid-client包,应该是本地调用方法,为啥在使用IdGeneratorFactoryClient.createIdGenerator(String bizType)时,还是需要进行http请求?那本地调用的意义何在?)

class IdGeneratorFactoryClient extends AbstractIdGeneratorFactory{
....省略
@OverRide
protected IdGenerator createIdGenerator(String bizType) {
return new CachedIdGenerator(bizType, new HttpSegmentIdServiceImpl());
}
....省略
}
是不是有点问题,需要手动改一下,将HttpSegmentIdServiceImpl改为DbSegmentIdServiceImpl,但改为DbSegmentIdServiceImpl不就引用了tinyId-server工程了吗

生成器提前初始化提高首次访问性能

现在IdGenerator是在每次请求来时去初始化的,这样可能导致初次访问性能较差,可以启动时完成对IdGenerator的初始化,然后开启定时任务去扫表增量初始化新加入的

能否增加动态step调整,让segment分配的频率更加可控

能否增加动态step调整,因为如果一开始对业务调用量无法评估的话,对step设置的过小会导致每次分配的segement使用过快,更新时冲突的概率变大,设置得过大又容易造成segement浪费。如果在增加maxId时记录增加时间lastTimeStamp,在下次增加maxId时,判断当前时间减去lastTimeStamp之间的时间差,如果小于我们设定的时间间隔(例如15分钟),那么我们就增大内存中step变量的值,如果大于就适当减少step变量的值,这样可以让segment分配的频率在我们可控的氛围内,如果可以增加的话,我可以实现这部分代码提PR

这个ID生成器,已经长期没人维护了,只能说能用,要用最好fork改一份

这个ID生成器,已经长期没人维护了,只能说能用,要用最好fork改一份,否则挺多陈旧的代码。

如果要用的,几个要点需要改下:

  1. Server 端 数据库不支持mysql8.x 及以上的
  2. 最好升级下springboot 版本,1.x 过于陈旧,升级时,需要改动一下代码
  3. 使用 hikari. 连接池替换 tomcat 自带连接池,提高性能
  4. 升级为 springboot 2.x 及以上,server.context-path 需要 更改为 server.servlet.context-path
  5. Client 端,默认硬编码读取resource 下的 tinyid_client.properties 配置文件,不太友好,最好改成可配置

其他的BUG,PR 有修复,有人维护的话最好是合并下吧。

在调用 nextIdSimple 获取id时,batchSize = 0 时会出现越界

curl http://127.0.0.1:9999/tinyid/id/nextIdSimple -d 'token=0f673adf80504e2eaa552f5d791b644c&bizType=test&batchSize=0'

java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.AbstractStringBuilder.deleteCharAt(AbstractStringBuilder.java:824) ~[?:1.8.0_241]
at java.lang.StringBuilder.deleteCharAt(StringBuilder.java:253) ~[?:1.8.0_241]
at com.xiaoju.uemc.tinyid.server.controller.IdContronller.nextIdSimple(IdContronller.java:85) [classes/:?]

loadNext, loadCurrent, 会产生 号段 使用上的跳跃

  1. 假设当前使用的号段为①
  2. 调用nextId多次后,会走进loadNext, 假设next = querySegmentId()里的querySegmentId已经执行完了,等待赋值给next
    • 假设这时候查到的号段为②
  3. 继续调用nextId直到用完,会走进loadCurrent。然后因为上面的next还没赋值,所以会走进querySegmentId
    • 假设这时候查到的号段为③

造成的结果: ①号段使用完了,③号段接着用,然后才可能用到②号段

单例存在并发问题

IdGeneratorFactoryClient = new IdGeneratorFactoryClient();
应该在init方法成功之后再new

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.