Browse Source

添加分表后自增id插件

fengyanjie@sagacloud.cn 4 years ago
parent
commit
d03456a14b
59 changed files with 2637 additions and 0 deletions
  1. 2 0
      pom.xml
  2. 17 0
      tinyid/.gitignore
  3. 28 0
      tinyid/CONTRIBUTING.md
  4. 201 0
      tinyid/LICENSE
  5. 94 0
      tinyid/README.md
  6. BIN
      tinyid/doc/qqqun.JPG
  7. BIN
      tinyid/doc/tinyid-easy.png
  8. BIN
      tinyid/doc/tinyid.png
  9. BIN
      tinyid/doc/tinyid_final.png
  10. 48 0
      tinyid/pom.xml
  11. 16 0
      tinyid/tinyid-base/pom.xml
  12. 35 0
      tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/entity/Result.java
  13. 24 0
      tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/entity/ResultCode.java
  14. 115 0
      tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/entity/SegmentId.java
  15. 23 0
      tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/exception/TinyIdSysException.java
  16. 36 0
      tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/factory/AbstractIdGeneratorFactory.java
  17. 15 0
      tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/factory/IdGeneratorFactory.java
  18. 21 0
      tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/generator/IdGenerator.java
  19. 109 0
      tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/generator/impl/CachedIdGenerator.java
  20. 17 0
      tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/service/SegmentIdService.java
  21. 36 0
      tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/util/NamedThreadFactory.java
  22. 41 0
      tinyid/tinyid-client/dependency-reduced-pom.xml
  23. 43 0
      tinyid/tinyid-client/pom.xml
  24. 73 0
      tinyid/tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/config/TinyIdClientConfig.java
  25. 85 0
      tinyid/tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/factory/impl/IdGeneratorFactoryClient.java
  26. 53 0
      tinyid/tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/service/impl/HttpSegmentIdServiceImpl.java
  27. 41 0
      tinyid/tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/utils/PropertiesLoader.java
  28. 38 0
      tinyid/tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/utils/TinyId.java
  29. 82 0
      tinyid/tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/utils/TinyIdHttpUtils.java
  30. 22 0
      tinyid/tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/utils/TinyIdNumberUtils.java
  31. 19 0
      tinyid/tinyid-client/src/test/java/com/xiaoju/uemc/tinyid/client/ClientTest.java
  32. 2 0
      tinyid/tinyid-client/src/test/resources/tinyid_client.properties
  33. 26 0
      tinyid/tinyid-server/.gitignore
  34. 30 0
      tinyid/tinyid-server/build.sh
  35. 42 0
      tinyid/tinyid-server/db.sql
  36. 117 0
      tinyid/tinyid-server/pom.xml
  37. 19 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/TinyIdServerApplication.java
  38. 20 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/common/Constants.java
  39. 91 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/config/DataSourceConfig.java
  40. 31 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/config/DynamicDataSource.java
  41. 128 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/controller/IdContronller.java
  42. 26 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/TinyIdInfoDAO.java
  43. 16 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/TinyIdTokenDAO.java
  44. 108 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/entity/TinyIdInfo.java
  45. 68 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/entity/TinyIdToken.java
  46. 62 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/impl/TinyIdInfoDAOImpl.java
  47. 44 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/impl/TinyIdTokenDAOImpl.java
  48. 27 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/factory/impl/IdGeneratorFactoryServer.java
  49. 62 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/filter/RequestFilter.java
  50. 14 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/service/TinyIdTokenService.java
  51. 75 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/service/impl/DbSegmentIdServiceImpl.java
  52. 77 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/service/impl/TinyIdTokenServiceImpl.java
  53. 35 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/vo/ErrorCode.java
  54. 36 0
      tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/vo/Response.java
  55. 24 0
      tinyid/tinyid-server/src/main/resources/offline/application.properties
  56. 39 0
      tinyid/tinyid-server/src/main/resources/offline/log4j2.xml
  57. 18 0
      tinyid/tinyid-server/src/main/resources/online/application.properties
  58. 39 0
      tinyid/tinyid-server/src/main/resources/online/log4j2.xml
  59. 27 0
      tinyid/tinyid-server/src/test/java/com/xiaoju/uemc/tinyid/server/ServerTest.java

+ 2 - 0
pom.xml

@@ -18,6 +18,8 @@
         <module>dmp-rwd-datautils</module>
         <module>dmp-task</module>
         <module>dmp-alarm</module>
+        <module>dmp-report</module>
+        <module>tinyid</module>
     </modules>
 
     <packaging>pom</packaging>

+ 17 - 0
tinyid/.gitignore

@@ -0,0 +1,17 @@
+target/
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+output/*
+logs/*
+

+ 28 - 0
tinyid/CONTRIBUTING.md

@@ -0,0 +1,28 @@
+# Contribution Guideline
+
+Thanks for considering to contribute this project. All issues and pull requests are highly appreciated.
+
+## Pull Requests
+
+Before sending pull request to this project, please read and follow guidelines below.
+
+1. Branch: We only accept pull request on `dev` branch.
+2. Coding style: Follow the coding style used in tinyid.
+3. Commit message: Use English and be aware of your spell.
+4. Test: Make sure to test your code.
+
+Add device mode, API version, related log, screenshots and other related information in your pull request if possible.
+
+NOTE: We assume all your contribution can be licensed under the [Apache License 2.0](https://github.com/didi/tinyid/blob/master/LICENSE). 
+
+## Issues
+
+We love clearly described issues. :)
+
+Following information can help us to resolve the issue faster.
+
+* Device mode and hardware information.
+* API version.
+* Logs.
+* Screenshots.
+* Steps to reproduce the issue.

+ 201 - 0
tinyid/LICENSE

@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright (C) 2017 Beijing Didi Infinity Technology and Development Co.,Ltd. All rights reserved.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 94 - 0
tinyid/README.md

@@ -0,0 +1,94 @@
+## Tinyid
+[![license](http://img.shields.io/badge/license-Apache2.0-brightgreen.svg?style=flat)](https://github.com/didi/tinyid/blob/master/LICENSE)
+[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/didi/tinyid/pulls)
+
+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](https://github.com/didi/tinyid/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
+```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
+```xml
+cd tinyid-server/
+sh build.sh offline
+java -jar output/tinyid-server-xxx.jar
+```
+## REST API 
+```properties
+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
+```xml
+<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:
+```properties
+tinyid.server=localhost:9999
+tinyid.token=0f673adf80504e2eaa552f5d791b644c
+
+#(tinyid.server=localhost:9999/gateway,ip2:port2/prefix,...)
+```
+### Java Code
+```java
+Long id = TinyId.nextId("test");
+List<Long> ids = TinyId.nextId("test", 10);
+```
+
+# Communication
+<img src="doc/qqqun.JPG" alt="Tinyid Community" width="200"/>
+
+# Contributing
+
+Welcome to contribute by creating issues or sending pull requests. See [Contributing Guide](CONTRIBUTING.md) for guidelines.
+
+# License
+
+Tinyid is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file.
+
+# Note
+
+This is not an official Didi product (experimental or otherwise), it is just code that happens to be owned by Didi.

BIN
tinyid/doc/qqqun.JPG


BIN
tinyid/doc/tinyid-easy.png


BIN
tinyid/doc/tinyid.png


BIN
tinyid/doc/tinyid_final.png


+ 48 - 0
tinyid/pom.xml

@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.xiaoju.uemc.tinyid</groupId>
+    <artifactId>tinyid</artifactId>
+    <version>0.1.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <name>tinyid</name>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <maven.compiler.target>1.7</maven.compiler.target>
+        <maven.compiler.source>1.7</maven.compiler.source>
+        <junit.version>4.12</junit.version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>com.xiaoju.uemc.tinyid</groupId>
+                <artifactId>tinyid-base</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.xiaoju.uemc.tinyid</groupId>
+                <artifactId>tinyid-client</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>junit</groupId>
+                <artifactId>junit</artifactId>
+                <version>${junit.version}</version>
+                <scope>test</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <modules>
+        <module>tinyid-server</module>
+        <module>tinyid-client</module>
+        <module>tinyid-base</module>
+    </modules>
+
+</project>

+ 16 - 0
tinyid/tinyid-base/pom.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>com.xiaoju.uemc.tinyid</groupId>
+        <artifactId>tinyid</artifactId>
+        <version>0.1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>tinyid-base</artifactId>
+
+    <dependencies>
+    </dependencies>
+</project>

+ 35 - 0
tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/entity/Result.java

@@ -0,0 +1,35 @@
+package com.xiaoju.uemc.tinyid.base.entity;
+
+/**
+ * @author du_imba
+ */
+public class Result {
+    private int code;
+    private long id;
+
+    public Result(int code, long id) {
+        this.code = code;
+        this.id = id;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    @Override
+    public String toString() {
+        return "[id:" + id + ",code:" + code + "]";
+    }
+}

+ 24 - 0
tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/entity/ResultCode.java

@@ -0,0 +1,24 @@
+package com.xiaoju.uemc.tinyid.base.entity;
+
+/**
+ * @author du_imba
+ */
+public class  ResultCode {
+
+    /**
+     * 正常可用
+     */
+    public static final int NORMAL = 1;
+    /**
+     * 需要去加载nextId
+     */
+    public static final int LOADING = 2;
+    /**
+     * 超过maxId 不可用
+     */
+    public static final int OVER = 3;
+
+    private ResultCode(){
+
+    }
+}

+ 115 - 0
tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/entity/SegmentId.java

@@ -0,0 +1,115 @@
+package com.xiaoju.uemc.tinyid.base.entity;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * @author du_imba
+ *         nextId: (currentId, maxId]
+ */
+public class SegmentId {
+    private long maxId;
+    private long loadingId;
+    private AtomicLong currentId;
+    /**
+     * increment by
+     */
+    private int delta;
+    /**
+     * mod num
+     */
+    private int remainder;
+
+    private volatile boolean isInit;
+
+    /**
+     * 这个方法主要为了1,4,7,10...这种序列准备的
+     * 设置好初始值之后,会以delta的方式递增,保证无论开始id是多少都能生成正确的序列
+     * 如当前是号段是(1000,2000],delta=3, remainder=0,则经过这个方法后,currentId会先递增到1002,之后每次增加delta
+     * 因为currentId会先递增,所以会浪费一个id,所以做了一次减delta的操作,实际currentId会从999开始增,第一个id还是1002
+     */
+    public void init() {
+        if (isInit) {
+            return;
+        }
+        synchronized (this) {
+            if (isInit) {
+                return;
+            }
+            long id = currentId.get();
+            if (id % delta == remainder) {
+                isInit = true;
+                return;
+            }
+            for (int i = 0; i <= delta; i++) {
+                id = currentId.incrementAndGet();
+                if (id % delta == remainder) {
+                    // 避免浪费 减掉系统自己占用的一个id
+                    currentId.addAndGet(0 - delta);
+                    isInit = true;
+                    return;
+                }
+            }
+        }
+    }
+
+    public Result nextId() {
+        init();
+        long id = currentId.addAndGet(delta);
+        if (id > maxId) {
+            return new Result(ResultCode.OVER, id);
+        }
+        if (id >= loadingId) {
+            return new Result(ResultCode.LOADING, id);
+        }
+        return new Result(ResultCode.NORMAL, id);
+    }
+
+    public boolean useful() {
+        return currentId.get() <= maxId;
+    }
+
+    public long getMaxId() {
+        return maxId;
+    }
+
+    public void setMaxId(long maxId) {
+        this.maxId = maxId;
+    }
+
+    public long getLoadingId() {
+        return loadingId;
+    }
+
+    public void setLoadingId(long loadingId) {
+        this.loadingId = loadingId;
+    }
+
+    public AtomicLong getCurrentId() {
+        return currentId;
+    }
+
+    public void setCurrentId(AtomicLong currentId) {
+        this.currentId = currentId;
+    }
+
+    public int getDelta() {
+        return delta;
+    }
+
+    public void setDelta(int delta) {
+        this.delta = delta;
+    }
+
+    public int getRemainder() {
+        return remainder;
+    }
+
+    public void setRemainder(int remainder) {
+        this.remainder = remainder;
+    }
+
+    @Override
+    public String toString() {
+        return "[maxId=" + maxId + ",loadingId=" + loadingId + ",currentId=" + currentId + ",delta=" + delta + ",remainder=" + remainder + "]";
+    }
+}

+ 23 - 0
tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/exception/TinyIdSysException.java

@@ -0,0 +1,23 @@
+package com.xiaoju.uemc.tinyid.base.exception;
+
+/**
+ * @author du_imba
+ */
+public class TinyIdSysException extends RuntimeException {
+
+    public TinyIdSysException() {
+        super();
+    }
+
+    public TinyIdSysException(String message) {
+        super(message);
+    }
+
+    public TinyIdSysException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public TinyIdSysException(Throwable cause) {
+        super(cause);
+    }
+}

+ 36 - 0
tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/factory/AbstractIdGeneratorFactory.java

@@ -0,0 +1,36 @@
+package com.xiaoju.uemc.tinyid.base.factory;
+
+import com.xiaoju.uemc.tinyid.base.generator.IdGenerator;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author du_imba
+ */
+public abstract class AbstractIdGeneratorFactory implements IdGeneratorFactory {
+
+    private static ConcurrentHashMap<String, IdGenerator> generators = new ConcurrentHashMap<>();
+
+    @Override
+    public IdGenerator getIdGenerator(String bizType) {
+        if (generators.containsKey(bizType)) {
+            return generators.get(bizType);
+        }
+        synchronized (this) {
+            if (generators.containsKey(bizType)) {
+                return generators.get(bizType);
+            }
+            IdGenerator idGenerator = createIdGenerator(bizType);
+            generators.put(bizType, idGenerator);
+            return idGenerator;
+        }
+    }
+
+    /**
+     * 根据bizType创建id生成器
+     *
+     * @param bizType
+     * @return
+     */
+    protected abstract IdGenerator createIdGenerator(String bizType);
+}

+ 15 - 0
tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/factory/IdGeneratorFactory.java

@@ -0,0 +1,15 @@
+package com.xiaoju.uemc.tinyid.base.factory;
+
+import com.xiaoju.uemc.tinyid.base.generator.IdGenerator;
+
+/**
+ * @author du_imba
+ */
+public interface IdGeneratorFactory {
+    /**
+     * 根据bizType创建id生成器
+     * @param bizType
+     * @return
+     */
+    IdGenerator getIdGenerator(String bizType);
+}

+ 21 - 0
tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/generator/IdGenerator.java

@@ -0,0 +1,21 @@
+package com.xiaoju.uemc.tinyid.base.generator;
+
+import java.util.List;
+
+/**
+ * @author du_imba
+ */
+public interface IdGenerator {
+    /**
+     * get next id
+     * @return
+     */
+    Long nextId();
+
+    /**
+     * get next id batch
+     * @param batchSize
+     * @return
+     */
+    List<Long> nextId(Integer batchSize);
+}

+ 109 - 0
tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/generator/impl/CachedIdGenerator.java

@@ -0,0 +1,109 @@
+package com.xiaoju.uemc.tinyid.base.generator.impl;
+
+import com.xiaoju.uemc.tinyid.base.entity.Result;
+import com.xiaoju.uemc.tinyid.base.entity.ResultCode;
+import com.xiaoju.uemc.tinyid.base.entity.SegmentId;
+import com.xiaoju.uemc.tinyid.base.exception.TinyIdSysException;
+import com.xiaoju.uemc.tinyid.base.generator.IdGenerator;
+import com.xiaoju.uemc.tinyid.base.service.SegmentIdService;
+import com.xiaoju.uemc.tinyid.base.util.NamedThreadFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * @author du_imba
+ */
+public class CachedIdGenerator implements IdGenerator {
+    protected String bizType;
+    protected SegmentIdService segmentIdService;
+    protected volatile SegmentId current;
+    protected volatile SegmentId next;
+    private volatile boolean isLoadingNext;
+    private Object lock = new Object();
+    private ExecutorService executorService = Executors.newSingleThreadExecutor(new NamedThreadFactory("tinyid-generator"));
+
+    public CachedIdGenerator(String bizType, SegmentIdService segmentIdService) {
+        this.bizType = bizType;
+        this.segmentIdService = segmentIdService;
+        loadCurrent();
+    }
+
+    public synchronized void loadCurrent() {
+        if (current == null || !current.useful()) {
+            if (next == null) {
+                SegmentId segmentId = querySegmentId();
+                this.current = segmentId;
+            } else {
+                current = next;
+                next = null;
+            }
+        }
+    }
+
+    private SegmentId querySegmentId() {
+        String message = null;
+        try {
+            SegmentId segmentId = segmentIdService.getNextSegmentId(bizType);
+            if (segmentId != null) {
+                return segmentId;
+            }
+        } catch (Exception e) {
+            message = e.getMessage();
+        }
+        throw new TinyIdSysException("error query segmentId: " + message);
+    }
+
+    public void loadNext() {
+        if (next == null && !isLoadingNext) {
+            synchronized (lock) {
+                if (next == null && !isLoadingNext) {
+                    isLoadingNext = true;
+                    executorService.submit(new Runnable() {
+                        @Override
+                        public void run() {
+                            try {
+                                // 无论获取下个segmentId成功与否,都要将isLoadingNext赋值为false
+                                next = querySegmentId();
+                            } finally {
+                                isLoadingNext = false;
+                            }
+                        }
+                    });
+                }
+            }
+        }
+    }
+
+    @Override
+    public Long nextId() {
+        while (true) {
+            if (current == null) {
+                loadCurrent();
+                continue;
+            }
+            Result result = current.nextId();
+            if (result.getCode() == ResultCode.OVER) {
+                loadCurrent();
+            } else {
+                if (result.getCode() == ResultCode.LOADING) {
+                    loadNext();
+                }
+                return result.getId();
+            }
+        }
+    }
+
+    @Override
+    public List<Long> nextId(Integer batchSize) {
+        List<Long> ids = new ArrayList<>();
+        for (int i = 0; i < batchSize; i++) {
+            Long id = nextId();
+            ids.add(id);
+        }
+        return ids;
+    }
+
+}

+ 17 - 0
tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/service/SegmentIdService.java

@@ -0,0 +1,17 @@
+package com.xiaoju.uemc.tinyid.base.service;
+
+import com.xiaoju.uemc.tinyid.base.entity.SegmentId;
+
+/**
+ * @author du_imba
+ */
+public interface SegmentIdService {
+
+    /**
+     * 根据bizType获取下一个SegmentId对象
+     * @param bizType
+     * @return
+     */
+    SegmentId getNextSegmentId(String bizType);
+
+}

+ 36 - 0
tinyid/tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/util/NamedThreadFactory.java

@@ -0,0 +1,36 @@
+package com.xiaoju.uemc.tinyid.base.util;
+
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @Author du_imba
+ */
+public class NamedThreadFactory implements ThreadFactory {
+
+    private final ThreadGroup group;
+    private final AtomicInteger threadNumber = new AtomicInteger(1);
+
+    private final String namePrefix;
+    private final boolean daemon;
+
+    public NamedThreadFactory(String namePrefix, boolean daemon) {
+        this.daemon = daemon;
+        SecurityManager s = System.getSecurityManager();
+        group = (s != null) ? s.getThreadGroup() :
+                Thread.currentThread().getThreadGroup();
+        this.namePrefix = namePrefix;
+    }
+
+    public NamedThreadFactory(String namePrefix) {
+        this(namePrefix, false);
+    }
+
+    @Override
+    public Thread newThread(Runnable r) {
+        Thread t = new Thread(group, r, namePrefix + "-thread-" + threadNumber.getAndIncrement(), 0);
+        t.setDaemon(daemon);
+        return t;
+    }
+
+}

+ 41 - 0
tinyid/tinyid-client/dependency-reduced-pom.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <artifactId>tinyid</artifactId>
+    <groupId>com.xiaoju.uemc.tinyid</groupId>
+    <version>0.1.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>tinyid-client</artifactId>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>3.0.0</version>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.12</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <artifactId>hamcrest-core</artifactId>
+          <groupId>org.hamcrest</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+  </dependencies>
+</project>
+

+ 43 - 0
tinyid/tinyid-client/pom.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>com.xiaoju.uemc.tinyid</groupId>
+        <artifactId>tinyid</artifactId>
+        <version>0.1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>tinyid-client</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.xiaoju.uemc.tinyid</groupId>
+            <artifactId>tinyid-base</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>3.0.0</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 73 - 0
tinyid/tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/config/TinyIdClientConfig.java

@@ -0,0 +1,73 @@
+package com.xiaoju.uemc.tinyid.client.config;
+
+import java.util.List;
+
+/**
+ * @author du_imba
+ */
+public class TinyIdClientConfig {
+
+    private String tinyIdToken;
+    private String tinyIdServer;
+    private List<String> serverList;
+    private Integer readTimeout;
+    private Integer connectTimeout;
+
+    private volatile static TinyIdClientConfig tinyIdClientConfig;
+
+    private TinyIdClientConfig() {
+    }
+
+    public static TinyIdClientConfig getInstance() {
+        if (tinyIdClientConfig != null) {
+            return tinyIdClientConfig;
+        }
+        synchronized (TinyIdClientConfig.class) {
+            if (tinyIdClientConfig != null) {
+                return tinyIdClientConfig;
+            }
+            tinyIdClientConfig = new TinyIdClientConfig();
+        }
+        return tinyIdClientConfig;
+    }
+
+    public String getTinyIdToken() {
+        return tinyIdToken;
+    }
+
+    public void setTinyIdToken(String tinyIdToken) {
+        this.tinyIdToken = tinyIdToken;
+    }
+
+    public String getTinyIdServer() {
+        return tinyIdServer;
+    }
+
+    public void setTinyIdServer(String tinyIdServer) {
+        this.tinyIdServer = tinyIdServer;
+    }
+
+    public List<String> getServerList() {
+        return serverList;
+    }
+
+    public void setServerList(List<String> serverList) {
+        this.serverList = serverList;
+    }
+
+    public Integer getReadTimeout() {
+        return readTimeout;
+    }
+
+    public void setReadTimeout(Integer readTimeout) {
+        this.readTimeout = readTimeout;
+    }
+
+    public Integer getConnectTimeout() {
+        return connectTimeout;
+    }
+
+    public void setConnectTimeout(Integer connectTimeout) {
+        this.connectTimeout = connectTimeout;
+    }
+}

+ 85 - 0
tinyid/tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/factory/impl/IdGeneratorFactoryClient.java

@@ -0,0 +1,85 @@
+package com.xiaoju.uemc.tinyid.client.factory.impl;
+
+import com.xiaoju.uemc.tinyid.base.factory.AbstractIdGeneratorFactory;
+import com.xiaoju.uemc.tinyid.base.generator.IdGenerator;
+import com.xiaoju.uemc.tinyid.base.generator.impl.CachedIdGenerator;
+import com.xiaoju.uemc.tinyid.client.config.TinyIdClientConfig;
+import com.xiaoju.uemc.tinyid.client.service.impl.HttpSegmentIdServiceImpl;
+import com.xiaoju.uemc.tinyid.client.utils.PropertiesLoader;
+import com.xiaoju.uemc.tinyid.client.utils.TinyIdNumberUtils;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+/**
+ * @author du_imba
+ */
+public class IdGeneratorFactoryClient extends AbstractIdGeneratorFactory {
+
+    private static final Logger logger = Logger.getLogger(IdGeneratorFactoryClient.class.getName());
+
+    private static IdGeneratorFactoryClient idGeneratorFactoryClient;
+
+    private static final String DEFAULT_PROP = "tinyid_client.properties";
+
+    private static final int DEFAULT_TIME_OUT = 5000;
+
+    private static String serverUrl = "http://{0}/tinyid/id/nextSegmentIdSimple?token={1}&bizType=";
+
+    private IdGeneratorFactoryClient() {
+
+    }
+
+    public static IdGeneratorFactoryClient getInstance(String location) {
+        if (idGeneratorFactoryClient == null) {
+            synchronized (IdGeneratorFactoryClient.class) {
+                if (idGeneratorFactoryClient == null) {
+                    if (location == null || "".equals(location)) {
+                        init(DEFAULT_PROP);
+                    } else {
+                        init(location);
+                    }
+                }
+            }
+        }
+        return idGeneratorFactoryClient;
+    }
+
+    private static void init(String location) {
+        idGeneratorFactoryClient = new IdGeneratorFactoryClient();
+        Properties properties = PropertiesLoader.loadProperties(location);
+        String tinyIdToken = properties.getProperty("tinyid.token");
+        String tinyIdServer = properties.getProperty("tinyid.server");
+        String readTimeout = properties.getProperty("tinyid.readTimeout");
+        String connectTimeout = properties.getProperty("tinyid.connectTimeout");
+
+        if (tinyIdToken == null || "".equals(tinyIdToken.trim())
+                || tinyIdServer == null || "".equals(tinyIdServer.trim())) {
+            throw new IllegalArgumentException("cannot find tinyid.token and tinyid.server config in:" + location);
+        }
+
+        TinyIdClientConfig tinyIdClientConfig = TinyIdClientConfig.getInstance();
+        tinyIdClientConfig.setTinyIdServer(tinyIdServer);
+        tinyIdClientConfig.setTinyIdToken(tinyIdToken);
+        tinyIdClientConfig.setReadTimeout(TinyIdNumberUtils.toInt(readTimeout, DEFAULT_TIME_OUT));
+        tinyIdClientConfig.setConnectTimeout(TinyIdNumberUtils.toInt(connectTimeout, DEFAULT_TIME_OUT));
+
+        String[] tinyIdServers = tinyIdServer.split(",");
+        List<String> serverList = new ArrayList<>(tinyIdServers.length);
+        for (String server : tinyIdServers) {
+            String url = MessageFormat.format(serverUrl, server, tinyIdToken);
+            serverList.add(url);
+        }
+        logger.info("init tinyId client success url info:" + serverList);
+        tinyIdClientConfig.setServerList(serverList);
+    }
+
+    @Override
+    protected IdGenerator createIdGenerator(String bizType) {
+        return new CachedIdGenerator(bizType, new HttpSegmentIdServiceImpl());
+    }
+
+}

+ 53 - 0
tinyid/tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/service/impl/HttpSegmentIdServiceImpl.java

@@ -0,0 +1,53 @@
+package com.xiaoju.uemc.tinyid.client.service.impl;
+
+import com.xiaoju.uemc.tinyid.base.entity.SegmentId;
+import com.xiaoju.uemc.tinyid.base.service.SegmentIdService;
+import com.xiaoju.uemc.tinyid.client.config.TinyIdClientConfig;
+import com.xiaoju.uemc.tinyid.client.utils.TinyIdHttpUtils;
+
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.logging.Logger;
+
+/**
+ * @author du_imba
+ */
+public class HttpSegmentIdServiceImpl implements SegmentIdService {
+
+    private static final Logger logger = Logger.getLogger(HttpSegmentIdServiceImpl.class.getName());
+
+    @Override
+    public SegmentId getNextSegmentId(String bizType) {
+        String url = chooseService(bizType);
+        String response = TinyIdHttpUtils.post(url, TinyIdClientConfig.getInstance().getReadTimeout(),
+                TinyIdClientConfig.getInstance().getConnectTimeout());
+        logger.info("tinyId client getNextSegmentId end, response:" + response);
+        if (response == null || "".equals(response.trim())) {
+            return null;
+        }
+        SegmentId segmentId = new SegmentId();
+        String[] arr = response.split(",");
+        segmentId.setCurrentId(new AtomicLong(Long.parseLong(arr[0])));
+        segmentId.setLoadingId(Long.parseLong(arr[1]));
+        segmentId.setMaxId(Long.parseLong(arr[2]));
+        segmentId.setDelta(Integer.parseInt(arr[3]));
+        segmentId.setRemainder(Integer.parseInt(arr[4]));
+        return segmentId;
+    }
+
+    private String chooseService(String bizType) {
+        List<String> serverList = TinyIdClientConfig.getInstance().getServerList();
+        String url = "";
+        if (serverList != null && serverList.size() == 1) {
+            url = serverList.get(0);
+        } else if (serverList != null && serverList.size() > 1) {
+            Random r = new Random();
+            url = serverList.get(r.nextInt(serverList.size()));
+        }
+        url += bizType;
+        return url;
+    }
+
+
+}

+ 41 - 0
tinyid/tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/utils/PropertiesLoader.java

@@ -0,0 +1,41 @@
+package com.xiaoju.uemc.tinyid.client.utils;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author du_imba
+ */
+public class PropertiesLoader {
+    private static final Logger logger = Logger.getLogger(PropertiesLoader.class.getName());
+
+    private PropertiesLoader() {
+
+    }
+
+    public static Properties loadProperties(String location) {
+        Properties props = new Properties();
+        logger.info("Loading properties file from path:" + location);
+        InputStreamReader in = null;
+        try {
+            in = new InputStreamReader(PropertiesLoader.class.getClassLoader().getResourceAsStream(location), "UTF-8");
+            props.load(in);
+        } catch (Exception e) {
+            throw new IllegalStateException(e);
+        } finally {
+            if(in != null) {
+                try {
+                    in.close();
+                } catch (IOException e) {
+                    logger.log(Level.WARNING, "error close inputstream", e);
+                }
+            }
+        }
+        return props;
+
+    }
+
+}

+ 38 - 0
tinyid/tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/utils/TinyId.java

@@ -0,0 +1,38 @@
+package com.xiaoju.uemc.tinyid.client.utils;
+
+import com.xiaoju.uemc.tinyid.client.factory.impl.IdGeneratorFactoryClient;
+import com.xiaoju.uemc.tinyid.base.generator.IdGenerator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author du_imba
+ */
+public class TinyId {
+    private static IdGeneratorFactoryClient client = IdGeneratorFactoryClient.getInstance(null);
+
+    private TinyId() {
+
+    }
+
+    public static Long nextId(String bizType) {
+        if(bizType == null) {
+            throw new IllegalArgumentException("type is null");
+        }
+        IdGenerator idGenerator = client.getIdGenerator(bizType);
+        return idGenerator.nextId();
+    }
+
+    public static List<Long> nextId(String bizType, Integer batchSize) {
+        if(batchSize == null) {
+            Long id = nextId(bizType);
+            List<Long> list = new ArrayList<>();
+            list.add(id);
+            return list;
+         }
+        IdGenerator idGenerator = client.getIdGenerator(bizType);
+        return idGenerator.nextId(batchSize);
+    }
+
+}

+ 82 - 0
tinyid/tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/utils/TinyIdHttpUtils.java

@@ -0,0 +1,82 @@
+package com.xiaoju.uemc.tinyid.client.utils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author du_imba
+ */
+public class TinyIdHttpUtils {
+
+    private static final Logger logger = Logger.getLogger(TinyIdHttpUtils.class.getName());
+
+
+    private TinyIdHttpUtils() {
+
+    }
+
+    public static String post(String url, Integer readTimeout, Integer connectTimeout) {
+        return post(url, null, readTimeout, connectTimeout);
+    }
+
+    public static String post(String url, Map<String, String> form, Integer readTimeout, Integer connectTimeout) {
+        HttpURLConnection conn = null;
+        OutputStreamWriter os = null;
+        BufferedReader rd = null;
+        StringBuilder param = new StringBuilder();
+        StringBuilder sb = new StringBuilder();
+        String line = null;
+        String response = null;
+        if (form != null) {
+            for (Map.Entry<String, String> entry : form.entrySet()) {
+                String key = entry.getKey();
+                if (param.length() != 0) {
+                    param.append("&");
+                }
+                param.append(key).append("=").append(entry.getValue());
+            }
+        }
+        try {
+            conn = (HttpURLConnection) new URL(url).openConnection();
+            conn.setRequestMethod("POST");
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+            conn.setReadTimeout(readTimeout);
+            conn.setConnectTimeout(connectTimeout);
+            conn.setUseCaches(false);
+            conn.connect();
+            os = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
+            os.write(param.toString());
+            os.flush();
+            rd = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
+            while ((line = rd.readLine()) != null) {
+                sb.append(line);
+            }
+            response = sb.toString();
+        } catch (Exception e) {
+            logger.log(Level.SEVERE, "error post url:" + url + param, e);
+        } finally {
+            try {
+                if (os != null) {
+                    os.close();
+                }
+                if (rd != null) {
+                    rd.close();
+                }
+                if (conn != null) {
+                    conn.disconnect();
+                }
+            } catch (IOException e) {
+                logger.log(Level.WARNING, "error close conn", e);
+            }
+        }
+        return response;
+    }
+}

+ 22 - 0
tinyid/tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/utils/TinyIdNumberUtils.java

@@ -0,0 +1,22 @@
+package com.xiaoju.uemc.tinyid.client.utils;
+
+/**
+ * @Author du_imba
+ */
+public class TinyIdNumberUtils {
+
+    public static int toInt(String str) {
+        return toInt(str, 0);
+    }
+
+    public static int toInt(String str, int defaultValue) {
+        if (str == null) {
+            return defaultValue;
+        }
+        try {
+            return Integer.parseInt(str);
+        } catch (NumberFormatException nfe) {
+            return defaultValue;
+        }
+    }
+}

+ 19 - 0
tinyid/tinyid-client/src/test/java/com/xiaoju/uemc/tinyid/client/ClientTest.java

@@ -0,0 +1,19 @@
+package com.xiaoju.uemc.tinyid.client;
+
+import com.xiaoju.uemc.tinyid.client.utils.TinyId;
+import org.junit.Test;
+
+/**
+ * @Author du_imba
+ */
+
+public class ClientTest {
+
+    @Test
+    public void testNextId() {
+        for (int i = 0; i < 100; i++) {
+            Long id = TinyId.nextId("test");
+            System.err.println("current id is: " + id);
+        }
+    }
+}

+ 2 - 0
tinyid/tinyid-client/src/test/resources/tinyid_client.properties

@@ -0,0 +1,2 @@
+tinyid.server=localhost:9999
+tinyid.token=0f673adf80504e2eaa552f5d791b644c

+ 26 - 0
tinyid/tinyid-server/.gitignore

@@ -0,0 +1,26 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+output/*
+logs

+ 30 - 0
tinyid/tinyid-server/build.sh

@@ -0,0 +1,30 @@
+#!/bin/bash
+#export JAVA_HOME=xxx
+#export PATH=$JAVA_HOME/bin:$PATH
+#
+#export MAVEN_HOME=xxxx
+#export PATH=$MAVEN_HOME/bin:$PATH
+#
+
+module=tinyid-server
+
+env=$1
+
+if [ -z "$env" ]; then
+    env='online'
+fi
+
+echo "build $env begin"
+
+mvn clean package -P$env -Dmaven.test.skip=true -f ../pom.xml
+ret=$?
+if [ $ret -ne 0 ];then
+    echo "===== maven build failure ====="
+    exit $ret
+else
+    echo -n "===== maven build successfully! ====="
+fi
+rm -rf output
+mkdir output
+mv target/${module}-*.jar output
+cd output

+ 42 - 0
tinyid/tinyid-server/db.sql

@@ -0,0 +1,42 @@
+CREATE TABLE `tiny_id_info` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
+  `biz_type` varchar(63) NOT NULL DEFAULT '' COMMENT '业务类型,唯一',
+  `begin_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '开始id,仅记录初始值,无其他含义。初始化时begin_id和max_id应相同',
+  `max_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '当前最大id',
+  `step` int(11) DEFAULT '0' COMMENT '步长',
+  `delta` int(11) NOT NULL DEFAULT '1' COMMENT '每次id增量',
+  `remainder` int(11) NOT NULL DEFAULT '0' COMMENT '余数',
+  `create_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '创建时间',
+  `update_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '更新时间',
+  `version` bigint(20) NOT NULL DEFAULT '0' COMMENT '版本号',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `uniq_biz_type` (`biz_type`)
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT 'id信息表';
+
+CREATE TABLE `tiny_id_token` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
+  `token` varchar(255) NOT NULL DEFAULT '' COMMENT 'token',
+  `biz_type` varchar(63) NOT NULL DEFAULT '' COMMENT '此token可访问的业务类型标识',
+  `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注',
+  `create_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '创建时间',
+  `update_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '更新时间',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT 'token信息表';
+
+INSERT INTO `tiny_id_info` (`id`, `biz_type`, `begin_id`, `max_id`, `step`, `delta`, `remainder`, `create_time`, `update_time`, `version`)
+VALUES
+	(1, 'test', 1, 1, 100000, 1, 0, '2018-07-21 23:52:58', '2018-07-22 23:19:27', 1);
+
+INSERT INTO `tiny_id_info` (`id`, `biz_type`, `begin_id`, `max_id`, `step`, `delta`, `remainder`, `create_time`, `update_time`, `version`)
+VALUES
+	(2, 'test_odd', 1, 1, 100000, 2, 1, '2018-07-21 23:52:58', '2018-07-23 00:39:24', 3);
+
+
+INSERT INTO `tiny_id_token` (`id`, `token`, `biz_type`, `remark`, `create_time`, `update_time`)
+VALUES
+	(1, '0f673adf80504e2eaa552f5d791b644c', 'test', '1', '2017-12-14 16:36:46', '2017-12-14 16:36:48');
+
+INSERT INTO `tiny_id_token` (`id`, `token`, `biz_type`, `remark`, `create_time`, `update_time`)
+VALUES
+	(2, '0f673adf80504e2eaa552f5d791b644c', 'test_odd', '1', '2017-12-14 16:36:46', '2017-12-14 16:36:48');
+

+ 117 - 0
tinyid/tinyid-server/pom.xml

@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>com.xiaoju.uemc.tinyid</groupId>
+        <artifactId>tinyid</artifactId>
+        <version>0.1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>tinyid-server</artifactId>
+
+    <properties>
+        <spring.version>1.5.9.RELEASE</spring.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.xiaoju.uemc.tinyid</groupId>
+            <artifactId>tinyid-base</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <version>${spring.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-tomcat</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <version>${spring.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-log4j2</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-jdbc</artifactId>
+            <version>${spring.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>5.1.44</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-beanutils</groupId>
+            <artifactId>commons-beanutils</artifactId>
+            <version>1.9.3</version>
+        </dependency>
+    </dependencies>
+
+    <profiles>
+        <profile>
+            <id>online</id>
+            <properties>
+                <package.environment>online</package.environment>
+            </properties>
+        </profile>
+        <profile>
+            <id>offline</id>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <properties>
+                <package.environment>offline</package.environment>
+            </properties>
+        </profile>
+    </profiles>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring.version}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <resources>
+            <resource>
+                <directory>src/main/resources/${package.environment}</directory>
+            </resource>
+            <resource>
+                <directory>src/main/resources/base</directory>
+            </resource>
+        </resources>
+    </build>
+
+</project>

+ 19 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/TinyIdServerApplication.java

@@ -0,0 +1,19 @@
+package com.xiaoju.uemc.tinyid.server;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * @author du_imba
+ */
+@EnableAsync
+@SpringBootApplication
+@EnableScheduling
+public class TinyIdServerApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(TinyIdServerApplication.class, args);
+    }
+}

+ 20 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/common/Constants.java

@@ -0,0 +1,20 @@
+package com.xiaoju.uemc.tinyid.server.common;
+
+/**
+ * @author du_imba
+ */
+public class Constants {
+    /**
+     * 预加载下个号段的百分比
+     */
+    public static final int LOADING_PERCENT = 20;
+    /**
+     * 重试次数
+     */
+    public static final int RETRY = 3;
+
+    private Constants() {
+
+    }
+
+}

+ 91 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/config/DataSourceConfig.java

@@ -0,0 +1,91 @@
+package com.xiaoju.uemc.tinyid.server.config;
+
+import org.apache.commons.beanutils.BeanUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
+import org.springframework.boot.bind.RelaxedPropertyResolver;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+import javax.sql.DataSource;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author du_imba
+ */
+@Configuration
+public class DataSourceConfig {
+
+    private static final Logger logger = LoggerFactory.getLogger(DataSourceConfig.class);
+
+    @Autowired
+    private Environment environment;
+    private static final String SEP = ",";
+
+    private static final String DEFAULT_DATASOURCE_TYPE = "org.apache.tomcat.jdbc.pool.DataSource";
+
+    @Bean
+    public DataSource getDynamicDataSource() {
+        DynamicDataSource routingDataSource = new DynamicDataSource();
+        List<String> dataSourceKeys = new ArrayList<>();
+        RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(environment, "datasource.tinyid.");
+        String names = propertyResolver.getProperty("names");
+        String dataSourceType = propertyResolver.getProperty("type");
+
+        Map<Object, Object> targetDataSources = new HashMap<>(4);
+        routingDataSource.setTargetDataSources(targetDataSources);
+        routingDataSource.setDataSourceKeys(dataSourceKeys);
+        // 多个数据源
+        for (String name : names.split(SEP)) {
+            Map<String, Object> dsMap = propertyResolver.getSubProperties(name + ".");
+            DataSource dataSource = buildDataSource(dataSourceType, dsMap);
+            buildDataSourceProperties(dataSource, dsMap);
+            targetDataSources.put(name, dataSource);
+            dataSourceKeys.add(name);
+        }
+        return routingDataSource;
+    }
+
+    private void buildDataSourceProperties(DataSource dataSource, Map<String, Object> dsMap) {
+        try {
+            // 此方法性能差,慎用
+            BeanUtils.copyProperties(dataSource, dsMap);
+        } catch (Exception e) {
+            logger.error("error copy properties", e);
+        }
+    }
+
+    private DataSource buildDataSource(String dataSourceType, Map<String, Object> dsMap) {
+        try {
+            String className = DEFAULT_DATASOURCE_TYPE;
+            if (dataSourceType != null && !"".equals(dataSourceType.trim())) {
+                className = dataSourceType;
+            }
+            Class<? extends DataSource> type = (Class<? extends DataSource>) Class.forName(className);
+            String driverClassName = dsMap.get("driver-class-name").toString();
+            String url = dsMap.get("url").toString();
+            String username = dsMap.get("username").toString();
+            String password = dsMap.get("password").toString();
+
+            return DataSourceBuilder.create()
+                    .driverClassName(driverClassName)
+                    .url(url)
+                    .username(username)
+                    .password(password)
+                    .type(type)
+                    .build();
+
+        } catch (ClassNotFoundException e) {
+            logger.error("buildDataSource error", e);
+            throw new IllegalStateException(e);
+        }
+    }
+
+
+}

+ 31 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/config/DynamicDataSource.java

@@ -0,0 +1,31 @@
+package com.xiaoju.uemc.tinyid.server.config;
+
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+
+import java.util.List;
+import java.util.Random;
+
+/**
+ * @author du_imba
+ */
+public class DynamicDataSource extends AbstractRoutingDataSource {
+
+    private List<String> dataSourceKeys;
+
+    @Override
+    protected Object determineCurrentLookupKey() {
+        if(dataSourceKeys.size() == 1) {
+            return dataSourceKeys.get(0);
+        }
+        Random r = new Random();
+        return dataSourceKeys.get(r.nextInt(dataSourceKeys.size()));
+    }
+
+    public List<String> getDataSourceKeys() {
+        return dataSourceKeys;
+    }
+
+    public void setDataSourceKeys(List<String> dataSourceKeys) {
+        this.dataSourceKeys = dataSourceKeys;
+    }
+}

+ 128 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/controller/IdContronller.java

@@ -0,0 +1,128 @@
+package com.xiaoju.uemc.tinyid.server.controller;
+
+import com.xiaoju.uemc.tinyid.base.entity.SegmentId;
+import com.xiaoju.uemc.tinyid.base.generator.IdGenerator;
+import com.xiaoju.uemc.tinyid.base.service.SegmentIdService;
+import com.xiaoju.uemc.tinyid.server.factory.impl.IdGeneratorFactoryServer;
+import com.xiaoju.uemc.tinyid.server.service.TinyIdTokenService;
+import com.xiaoju.uemc.tinyid.server.vo.ErrorCode;
+import com.xiaoju.uemc.tinyid.server.vo.Response;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * @author du_imba
+ */
+@RestController
+@RequestMapping("/id/")
+public class IdContronller {
+
+    private static final Logger logger = LoggerFactory.getLogger(IdContronller.class);
+    @Autowired
+    private IdGeneratorFactoryServer idGeneratorFactoryServer;
+    @Autowired
+    private SegmentIdService segmentIdService;
+    @Autowired
+    private TinyIdTokenService tinyIdTokenService;
+    @Value("${batch.size.max}")
+    private Integer batchSizeMax;
+
+    @RequestMapping("nextId")
+    public Response<List<Long>> nextId(String bizType, Integer batchSize, String token) {
+        Response<List<Long>> response = new Response<>();
+        Integer newBatchSize = checkBatchSize(batchSize);
+        if (!tinyIdTokenService.canVisit(bizType, token)) {
+            response.setCode(ErrorCode.TOKEN_ERR.getCode());
+            response.setMessage(ErrorCode.TOKEN_ERR.getMessage());
+            return response;
+        }
+        try {
+            IdGenerator idGenerator = idGeneratorFactoryServer.getIdGenerator(bizType);
+            List<Long> ids = idGenerator.nextId(newBatchSize);
+            response.setData(ids);
+        } catch (Exception e) {
+            response.setCode(ErrorCode.SYS_ERR.getCode());
+            response.setMessage(e.getMessage());
+            logger.error("nextId error", e);
+        }
+        return response;
+    }
+
+    private Integer checkBatchSize(Integer batchSize) {
+        if (batchSize == null) {
+            batchSize = 1;
+        }
+        if (batchSize > batchSizeMax) {
+            batchSize = batchSizeMax;
+        }
+        return batchSize;
+    }
+
+    @RequestMapping("nextIdSimple")
+    public String nextIdSimple(String bizType, Integer batchSize, String token) {
+        Integer newBatchSize = checkBatchSize(batchSize);
+        if (!tinyIdTokenService.canVisit(bizType, token)) {
+            return "";
+        }
+        String response = "";
+        try {
+            IdGenerator idGenerator = idGeneratorFactoryServer.getIdGenerator(bizType);
+            if (newBatchSize == 1) {
+                Long id = idGenerator.nextId();
+                response = id + "";
+            } else {
+                List<Long> idList = idGenerator.nextId(newBatchSize);
+                StringBuilder sb = new StringBuilder();
+                for (Long id : idList) {
+                    sb.append(id).append(",");
+                }
+                response = sb.deleteCharAt(sb.length() - 1).toString();
+            }
+        } catch (Exception e) {
+            logger.error("nextIdSimple error", e);
+        }
+        return response;
+    }
+
+    @RequestMapping("nextSegmentId")
+    public Response<SegmentId> nextSegmentId(String bizType, String token) {
+        Response<SegmentId> response = new Response<>();
+        if (!tinyIdTokenService.canVisit(bizType, token)) {
+            response.setCode(ErrorCode.TOKEN_ERR.getCode());
+            response.setMessage(ErrorCode.TOKEN_ERR.getMessage());
+            return response;
+        }
+        try {
+            SegmentId segmentId = segmentIdService.getNextSegmentId(bizType);
+            response.setData(segmentId);
+        } catch (Exception e) {
+            response.setCode(ErrorCode.SYS_ERR.getCode());
+            response.setMessage(e.getMessage());
+            logger.error("nextSegmentId error", e);
+        }
+        return response;
+    }
+
+    @RequestMapping("nextSegmentIdSimple")
+    public String nextSegmentIdSimple(String bizType, String token) {
+        if (!tinyIdTokenService.canVisit(bizType, token)) {
+            return "";
+        }
+        String response = "";
+        try {
+            SegmentId segmentId = segmentIdService.getNextSegmentId(bizType);
+            response = segmentId.getCurrentId() + "," + segmentId.getLoadingId() + "," + segmentId.getMaxId()
+                    + "," + segmentId.getDelta() + "," + segmentId.getRemainder();
+        } catch (Exception e) {
+            logger.error("nextSegmentIdSimple error", e);
+        }
+        return response;
+    }
+
+}

+ 26 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/TinyIdInfoDAO.java

@@ -0,0 +1,26 @@
+package com.xiaoju.uemc.tinyid.server.dao;
+
+import com.xiaoju.uemc.tinyid.server.dao.entity.TinyIdInfo;
+
+/**
+ * @author du_imba
+ */
+public interface TinyIdInfoDAO {
+    /**
+     * 根据bizType获取db中的tinyId对象
+     * @param bizType
+     * @return
+     */
+    TinyIdInfo queryByBizType(String bizType);
+
+    /**
+     * 根据id、oldMaxId、version、bizType更新最新的maxId
+     * @param id
+     * @param newMaxId
+     * @param oldMaxId
+     * @param version
+     * @param bizType
+     * @return
+     */
+    int updateMaxId(Long id, Long newMaxId, Long oldMaxId, Long version, String bizType);
+}

+ 16 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/TinyIdTokenDAO.java

@@ -0,0 +1,16 @@
+package com.xiaoju.uemc.tinyid.server.dao;
+
+import com.xiaoju.uemc.tinyid.server.dao.entity.TinyIdToken;
+
+import java.util.List;
+
+/**
+ * @author du_imba
+ */
+public interface TinyIdTokenDAO {
+    /**
+     * 查询db中所有的token信息
+     * @return
+     */
+    List<TinyIdToken> selectAll();
+}

+ 108 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/entity/TinyIdInfo.java

@@ -0,0 +1,108 @@
+package com.xiaoju.uemc.tinyid.server.dao.entity;
+
+import java.util.Date;
+
+/**
+ * @author du_imba
+ */
+public class TinyIdInfo {
+    private Long id;
+
+    private String bizType;
+
+    private Long beginId;
+
+    private Long maxId;
+
+    private Integer step;
+
+    private Integer delta;
+
+    private Integer remainder;
+
+    private Date createTime;
+
+    private Date updateTime;
+
+    private Long version;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getBizType() {
+        return bizType;
+    }
+
+    public void setBizType(String bizType) {
+        this.bizType = bizType;
+    }
+
+    public Long getBeginId() {
+        return beginId;
+    }
+
+    public void setBeginId(Long beginId) {
+        this.beginId = beginId;
+    }
+
+    public Long getMaxId() {
+        return maxId;
+    }
+
+    public void setMaxId(Long maxId) {
+        this.maxId = maxId;
+    }
+
+    public Integer getStep() {
+        return step;
+    }
+
+    public void setStep(Integer step) {
+        this.step = step;
+    }
+
+    public Integer getDelta() {
+        return delta;
+    }
+
+    public void setDelta(Integer delta) {
+        this.delta = delta;
+    }
+
+    public Integer getRemainder() {
+        return remainder;
+    }
+
+    public void setRemainder(Integer remainder) {
+        this.remainder = remainder;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public Long getVersion() {
+        return version;
+    }
+
+    public void setVersion(Long version) {
+        this.version = version;
+    }
+}

+ 68 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/entity/TinyIdToken.java

@@ -0,0 +1,68 @@
+package com.xiaoju.uemc.tinyid.server.dao.entity;
+
+import java.util.Date;
+
+/**
+ * @author du_imba
+ */
+public class TinyIdToken {
+    private Integer id;
+
+    private String token;
+
+    private String bizType;
+
+    private String remark;
+
+    private Date createTime;
+
+    private Date updateTime;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getToken() {
+        return token;
+    }
+
+    public void setToken(String token) {
+        this.token = token == null ? null : token.trim();
+    }
+
+    public String getBizType() {
+        return bizType;
+    }
+
+    public void setBizType(String bizType) {
+        this.bizType = bizType == null ? null : bizType.trim();
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark == null ? null : remark.trim();
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+}

+ 62 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/impl/TinyIdInfoDAOImpl.java

@@ -0,0 +1,62 @@
+package com.xiaoju.uemc.tinyid.server.dao.impl;
+
+import com.xiaoju.uemc.tinyid.server.dao.TinyIdInfoDAO;
+import com.xiaoju.uemc.tinyid.server.dao.entity.TinyIdInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Repository;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * @author du_imba
+ */
+@Repository
+public class TinyIdInfoDAOImpl implements TinyIdInfoDAO {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Override
+    public TinyIdInfo queryByBizType(String bizType) {
+        String sql = "select id, biz_type, begin_id, max_id," +
+                " step, delta, remainder, create_time, update_time, version" +
+                " from tiny_id_info where biz_type = ?";
+        List<TinyIdInfo> list = jdbcTemplate.query(sql, new Object[]{bizType}, new TinyIdInfoRowMapper());
+        if(list == null || list.isEmpty()) {
+            return null;
+        }
+        return list.get(0);
+    }
+
+    @Override
+    public int updateMaxId(Long id, Long newMaxId, Long oldMaxId, Long version, String bizType) {
+        String sql = "update tiny_id_info set max_id= ?," +
+                " update_time=now(), version=version+1" +
+                " where id=? and max_id=? and version=? and biz_type=?";
+        return jdbcTemplate.update(sql, newMaxId, id, oldMaxId, version, bizType);
+    }
+
+
+    public static class TinyIdInfoRowMapper implements RowMapper<TinyIdInfo> {
+
+        @Override
+        public TinyIdInfo mapRow(ResultSet resultSet, int i) throws SQLException {
+            TinyIdInfo tinyIdInfo = new TinyIdInfo();
+            tinyIdInfo.setId(resultSet.getLong("id"));
+            tinyIdInfo.setBizType(resultSet.getString("biz_type"));
+            tinyIdInfo.setBeginId(resultSet.getLong("begin_id"));
+            tinyIdInfo.setMaxId(resultSet.getLong("max_id"));
+            tinyIdInfo.setStep(resultSet.getInt("step"));
+            tinyIdInfo.setDelta(resultSet.getInt("delta"));
+            tinyIdInfo.setRemainder(resultSet.getInt("remainder"));
+            tinyIdInfo.setCreateTime(resultSet.getDate("create_time"));
+            tinyIdInfo.setUpdateTime(resultSet.getDate("update_time"));
+            tinyIdInfo.setVersion(resultSet.getLong("version"));
+            return tinyIdInfo;
+        }
+    }
+}

+ 44 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/impl/TinyIdTokenDAOImpl.java

@@ -0,0 +1,44 @@
+package com.xiaoju.uemc.tinyid.server.dao.impl;
+
+import com.xiaoju.uemc.tinyid.server.dao.TinyIdTokenDAO;
+import com.xiaoju.uemc.tinyid.server.dao.entity.TinyIdToken;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Repository;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * @author du_imba
+ */
+@Repository
+public class TinyIdTokenDAOImpl implements TinyIdTokenDAO {
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Override
+    public List<TinyIdToken> selectAll() {
+        String sql = "select id, token, biz_type, remark, " +
+                "create_time, update_time from tiny_id_token";
+        return jdbcTemplate.query(sql, new TinyIdTokenRowMapper());
+    }
+
+    public static class TinyIdTokenRowMapper implements RowMapper<TinyIdToken> {
+
+        @Override
+        public TinyIdToken mapRow(ResultSet resultSet, int i) throws SQLException {
+            TinyIdToken token = new TinyIdToken();
+            token.setId(resultSet.getInt("id"));
+            token.setToken(resultSet.getString("token"));
+            token.setBizType(resultSet.getString("biz_type"));
+            token.setRemark(resultSet.getString("remark"));
+            token.setCreateTime(resultSet.getDate("create_time"));
+            token.setUpdateTime(resultSet.getDate("update_time"));
+            return token;
+        }
+    }
+}

+ 27 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/factory/impl/IdGeneratorFactoryServer.java

@@ -0,0 +1,27 @@
+package com.xiaoju.uemc.tinyid.server.factory.impl;
+
+import com.xiaoju.uemc.tinyid.base.factory.AbstractIdGeneratorFactory;
+import com.xiaoju.uemc.tinyid.base.generator.IdGenerator;
+import com.xiaoju.uemc.tinyid.base.generator.impl.CachedIdGenerator;
+import com.xiaoju.uemc.tinyid.base.service.SegmentIdService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author du_imba
+ */
+@Component
+public class IdGeneratorFactoryServer extends AbstractIdGeneratorFactory {
+
+    private static final Logger logger = LoggerFactory.getLogger(CachedIdGenerator.class);
+    @Autowired
+    private SegmentIdService tinyIdService;
+
+    @Override
+    public IdGenerator createIdGenerator(String bizType) {
+        logger.info("createIdGenerator :{}", bizType);
+        return new CachedIdGenerator(bizType, tinyIdService);
+    }
+}

+ 62 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/filter/RequestFilter.java

@@ -0,0 +1,62 @@
+package com.xiaoju.uemc.tinyid.server.filter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.web.servlet.ServletComponentScan;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * @Author du_imba
+ */
+@Component
+@ServletComponentScan
+@WebFilter(urlPatterns = "/*", filterName = "requestFilter")
+public class RequestFilter implements Filter {
+
+    private static final Logger logger = LoggerFactory.getLogger(RequestFilter.class);
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+
+    }
+
+    @Override
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
+        HttpServletRequest request = (HttpServletRequest) servletRequest;
+        HttpServletResponse response = (HttpServletResponse) servletResponse;
+        String params = "";
+        Map<String, String[]> paramsMap = request.getParameterMap();
+        if (paramsMap != null && !paramsMap.isEmpty()) {
+            for (Map.Entry<String, String[]> entry : paramsMap.entrySet()) {
+                params += entry.getKey() + ":" + StringUtils.arrayToDelimitedString(entry.getValue(), ",") + ";";
+            }
+        }
+        long start = System.currentTimeMillis();
+        try {
+            filterChain.doFilter(request, response);
+        } catch (Throwable e) {
+            throw e;
+        } finally {
+            long cost = System.currentTimeMillis() - start;
+            logger.info("request filter path={}, cost={}, params={}", request.getServletPath(), cost, params);
+        }
+    }
+
+    @Override
+    public void destroy() {
+
+    }
+}

+ 14 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/service/TinyIdTokenService.java

@@ -0,0 +1,14 @@
+package com.xiaoju.uemc.tinyid.server.service;
+
+/**
+ * @author du_imba
+ */
+public interface TinyIdTokenService {
+    /**
+     * 是否有权限
+     * @param bizType
+     * @param token
+     * @return
+     */
+    boolean canVisit(String bizType, String token);
+}

+ 75 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/service/impl/DbSegmentIdServiceImpl.java

@@ -0,0 +1,75 @@
+package com.xiaoju.uemc.tinyid.server.service.impl;
+
+import com.xiaoju.uemc.tinyid.base.entity.SegmentId;
+import com.xiaoju.uemc.tinyid.base.exception.TinyIdSysException;
+import com.xiaoju.uemc.tinyid.base.service.SegmentIdService;
+import com.xiaoju.uemc.tinyid.server.common.Constants;
+import com.xiaoju.uemc.tinyid.server.dao.TinyIdInfoDAO;
+import com.xiaoju.uemc.tinyid.server.dao.entity.TinyIdInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+
+/**
+ * @author du_imba
+ */
+@Component
+public class DbSegmentIdServiceImpl implements SegmentIdService {
+
+    private static final Logger logger = LoggerFactory.getLogger(DbSegmentIdServiceImpl.class);
+
+    @Autowired
+    private TinyIdInfoDAO tinyIdInfoDAO;
+
+    /**
+     * Transactional标记保证query和update使用的是同一连接
+     * 事务隔离级别应该为READ_COMMITTED,Spring默认是DEFAULT(取决于底层使用的数据库,mysql的默认隔离级别为REPEATABLE_READ)
+     * <p>
+     * 如果是REPEATABLE_READ,那么在本次事务中循环调用tinyIdInfoDAO.queryByBizType(bizType)获取的结果是没有变化的,也就是查询不到别的事务提交的内容
+     * 所以多次调用tinyIdInfoDAO.updateMaxId也就不会成功
+     *
+     * @param bizType
+     * @return
+     */
+    @Override
+    @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);
+            if (tinyIdInfo == null) {
+                throw new TinyIdSysException("can not find biztype:" + bizType);
+            }
+            Long newMaxId = tinyIdInfo.getMaxId() + tinyIdInfo.getStep();
+            Long oldMaxId = tinyIdInfo.getMaxId();
+            int row = tinyIdInfoDAO.updateMaxId(tinyIdInfo.getId(), newMaxId, oldMaxId, tinyIdInfo.getVersion(),
+                    tinyIdInfo.getBizType());
+            if (row == 1) {
+                tinyIdInfo.setMaxId(newMaxId);
+                SegmentId segmentId = convert(tinyIdInfo);
+                logger.info("getNextSegmentId success tinyIdInfo:{} current:{}", tinyIdInfo, segmentId);
+                return segmentId;
+            } else {
+                logger.info("getNextSegmentId conflict tinyIdInfo:{}", tinyIdInfo);
+            }
+        }
+        throw new TinyIdSysException("get next segmentId conflict");
+    }
+
+    public SegmentId convert(TinyIdInfo idInfo) {
+        SegmentId segmentId = new SegmentId();
+        segmentId.setCurrentId(new AtomicLong(idInfo.getMaxId() - idInfo.getStep()));
+        segmentId.setMaxId(idInfo.getMaxId());
+        segmentId.setRemainder(idInfo.getRemainder() == null ? 0 : idInfo.getRemainder());
+        segmentId.setDelta(idInfo.getDelta() == null ? 1 : idInfo.getDelta());
+        // 默认20%加载
+        segmentId.setLoadingId(segmentId.getCurrentId().get() + idInfo.getStep() * Constants.LOADING_PERCENT / 100);
+        return segmentId;
+    }
+}

+ 77 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/service/impl/TinyIdTokenServiceImpl.java

@@ -0,0 +1,77 @@
+package com.xiaoju.uemc.tinyid.server.service.impl;
+
+import com.xiaoju.uemc.tinyid.server.dao.TinyIdTokenDAO;
+import com.xiaoju.uemc.tinyid.server.dao.entity.TinyIdToken;
+import com.xiaoju.uemc.tinyid.server.service.TinyIdTokenService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.PostConstruct;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author du_imba
+ */
+@Component
+public class TinyIdTokenServiceImpl implements TinyIdTokenService {
+
+    @Autowired
+    private TinyIdTokenDAO tinyIdTokenDAO;
+
+    private static Map<String, Set<String>> token2bizTypes = new HashMap<>();
+
+    private static final Logger logger = LoggerFactory.getLogger(TinyIdTokenServiceImpl.class);
+
+    public List<TinyIdToken> queryAll() {
+        return tinyIdTokenDAO.selectAll();
+    }
+
+    /**
+     * 1分钟刷新一次token
+     */
+    @Scheduled(cron = "0 0/1 * * * ?")
+    public void refresh() {
+        logger.info("refresh token begin");
+        init();
+    }
+
+    @PostConstruct
+    private synchronized void init() {
+        logger.info("tinyId token init begin");
+        List<TinyIdToken> list = queryAll();
+        Map<String, Set<String>> map = converToMap(list);
+        token2bizTypes = map;
+        logger.info("tinyId token init success, token size:{}", list == null ? 0 : list.size());
+    }
+
+    @Override
+    public boolean canVisit(String bizType, String token) {
+        if (StringUtils.isEmpty(bizType) || StringUtils.isEmpty(token)) {
+            return false;
+        }
+        Set<String> bizTypes = token2bizTypes.get(token);
+        return (bizTypes != null && bizTypes.contains(bizType));
+    }
+
+    public Map<String, Set<String>> converToMap(List<TinyIdToken> list) {
+        Map<String, Set<String>> map = new HashMap<>(64);
+        if (list != null) {
+            for (TinyIdToken tinyIdToken : list) {
+                if (!map.containsKey(tinyIdToken.getToken())) {
+                    map.put(tinyIdToken.getToken(), new HashSet<String>());
+                }
+                map.get(tinyIdToken.getToken()).add(tinyIdToken.getBizType());
+            }
+        }
+        return map;
+    }
+
+}

+ 35 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/vo/ErrorCode.java

@@ -0,0 +1,35 @@
+package com.xiaoju.uemc.tinyid.server.vo;
+
+/**
+ * @author du_imba
+ */
+public enum ErrorCode {
+    /**
+     * token is wrong
+     */
+    TOKEN_ERR(5, "token is error"),
+    /**
+     * server internal error
+     */
+    SYS_ERR(6, "sys error");
+
+    private Integer code;
+    private String message;
+
+    ErrorCode(Integer code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+
+    public String getMessage() {
+        return message;
+    }
+
+}
+
+

+ 36 - 0
tinyid/tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/vo/Response.java

@@ -0,0 +1,36 @@
+package com.xiaoju.uemc.tinyid.server.vo;
+
+/**
+ * @author du_imba
+ */
+public class Response<T> {
+    private T data;
+    private Integer code = 200;
+    private String message = "";
+
+    public static final int SYS_ERROR = 500;
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}

+ 24 - 0
tinyid/tinyid-server/src/main/resources/offline/application.properties

@@ -0,0 +1,24 @@
+server.port=9999
+server.context-path=/tinyid
+
+batch.size.max=100000
+
+datasource.tinyid.names=primary
+#datasource.tinyid.names=primary,secondary
+datasource.tinyid.type=org.apache.tomcat.jdbc.pool.DataSource
+
+datasource.tinyid.primary.driver-class-name=com.mysql.jdbc.Driver
+datasource.tinyid.primary.url=jdbc:mysql://192.168.64.15:9934/test-tiny?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
+datasource.tinyid.primary.username=root
+datasource.tinyid.primary.password=brzj123456
+#datasource.tinyid.primary.testOnBorrow=false
+#datasource.tinyid.primary.maxActive=10
+
+#datasource.tinyid.secondary.driver-class-name=com.mysql.jdbc.Driver
+#datasource.tinyid.secondary.url=jdbc:mysql://localhost:3306/db2?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
+#datasource.tinyid.secondary.username=root
+#datasource.tinyid.secondary.password=123456
+#datasource.tinyid.secondary.testOnBorrow=false
+#datasource.tinyid.secondary.maxActive=10
+
+

+ 39 - 0
tinyid/tinyid-server/src/main/resources/offline/log4j2.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<configuration status="error" shutdownHook="disable">
+
+    <Properties>
+        <Property name="log-path">./logs/</Property>
+    </Properties>
+    <!--先定义所有的appender-->
+    <appenders>
+        <!--这个输出控制台的配置-->
+        <Console name="Console" target="SYSTEM_OUT">
+            <PatternLayout pattern="%date{HH:mm:ss,SSS} [%thread] [%level] %logger{1.} - %msg%n"/>
+        </Console>
+        <RollingFile name="ServerRollingFile" fileName="${log-path}/tinyid-server.log"
+                     filePattern="${log-path}/tinyid-server.log.%d{yyyyMMddHH}">
+            <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss,SSS} [%thread] [%level] %logger{1.} - %msg%n"/>
+            <Policies>
+                <TimeBasedTriggeringPolicy/>
+            </Policies>
+        </RollingFile>
+    </appenders>
+    <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
+    <loggers>
+        <logger name="com.xiaoju.uemc.tinyid" level="INFO"/>
+        <logger name="org.springframework" level="INFO"/>
+
+        <!--<logger name="org.springframework.kafka" level="DEBUG" />-->
+        <!--
+        <logger name="org.mybatis" level="DEBUG" />
+        <logger name="java.sql" level="DEBUG"/>
+         -->
+
+        <!--建立一个默认的root的logger, 除了上面定义的logger,其他只有warn才会打印-->
+        <root level="WARN">
+            <appender-ref ref="ServerRollingFile"/>
+            <appender-ref ref="Console"/>
+        </root>
+    </loggers>
+</configuration>

+ 18 - 0
tinyid/tinyid-server/src/main/resources/online/application.properties

@@ -0,0 +1,18 @@
+#online
+server.port=9999
+server.context-path=/tinyid
+
+batch.size.max=100000
+
+datasource.tinyid.names=primary
+#datasource.tinyid.names=primary,secondary
+
+datasource.tinyid.primary.driver-class-name=com.mysql.jdbc.Driver
+datasource.tinyid.primary.url=jdbc:mysql://192.168.64.15:9934/test-tiny?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
+datasource.tinyid.primary.username=root
+datasource.tinyid.primary.password=brzj123456
+
+#datasource.tinyid.secondary.driver-class-name=com.mysql.jdbc.Driver
+#datasource.tinyid.secondary.url=jdbc:mysql://localhost:3306/db2?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
+#datasource.tinyid.secondary.username=root
+#datasource.tinyid.secondary.password=123456

+ 39 - 0
tinyid/tinyid-server/src/main/resources/online/log4j2.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<configuration status="error" shutdownHook="disable">
+
+    <Properties>
+        <Property name="log-path">/home/xiaoju/tinyid-server/logs/</Property>
+    </Properties>
+    <!--先定义所有的appender-->
+    <appenders>
+        <!--这个输出控制台的配置-->
+        <Console name="Console" target="SYSTEM_OUT">
+            <PatternLayout pattern="%date{HH:mm:ss,SSS} [%thread] [%level] %logger{1.} - %msg%n"/>
+        </Console>
+        <RollingFile name="ServerRollingFile" fileName="${log-path}/tinyid-server.log"
+                     filePattern="${log-path}/tinyid-server.log.%d{yyyyMMddHH}">
+            <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss,SSS} [%thread] [%level] %logger{1.} - %msg%n"/>
+            <Policies>
+                <TimeBasedTriggeringPolicy/>
+            </Policies>
+        </RollingFile>
+    </appenders>
+    <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
+    <loggers>
+        <logger name="com.xiaoju.uemc.tinyid" level="INFO"/>
+        <logger name="org.springframework" level="INFO"/>
+
+        <!--<logger name="org.springframework.kafka" level="DEBUG" />-->
+        <!--
+        <logger name="org.mybatis" level="DEBUG" />
+        <logger name="java.sql" level="DEBUG"/>
+         -->
+
+        <!--建立一个默认的root的logger, 除了上面定义的logger,其他只有warn才会打印-->
+        <root level="WARN">
+            <appender-ref ref="ServerRollingFile"/>
+            <appender-ref ref="Console"/>
+        </root>
+    </loggers>
+</configuration>

+ 27 - 0
tinyid/tinyid-server/src/test/java/com/xiaoju/uemc/tinyid/server/ServerTest.java

@@ -0,0 +1,27 @@
+package com.xiaoju.uemc.tinyid.server;
+
+import com.xiaoju.uemc.tinyid.base.generator.IdGenerator;
+import com.xiaoju.uemc.tinyid.server.factory.impl.IdGeneratorFactoryServer;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * @Author du_imba
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class ServerTest {
+
+    @Autowired
+    IdGeneratorFactoryServer idGeneratorFactoryServer;
+
+    @Test
+    public void testNextId() {
+        IdGenerator idGenerator = idGeneratorFactoryServer.getIdGenerator("test");
+        Long id = idGenerator.nextId();
+        System.err.println("current id is: " + id);
+    }
+}