├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── doc ├── qqqun.JPG ├── tinyid-easy.png ├── tinyid.png └── tinyid_final.png ├── pom.xml ├── tinyid-base ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── xiaoju │ └── uemc │ └── tinyid │ └── base │ ├── entity │ ├── Result.java │ ├── ResultCode.java │ └── SegmentId.java │ ├── exception │ └── TinyIdSysException.java │ ├── factory │ ├── AbstractIdGeneratorFactory.java │ └── IdGeneratorFactory.java │ ├── generator │ ├── IdGenerator.java │ └── impl │ │ └── CachedIdGenerator.java │ ├── service │ └── SegmentIdService.java │ └── util │ └── NamedThreadFactory.java ├── tinyid-client ├── dependency-reduced-pom.xml ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── xiaoju │ │ └── uemc │ │ └── tinyid │ │ └── client │ │ ├── config │ │ └── TinyIdClientConfig.java │ │ ├── factory │ │ └── impl │ │ │ └── IdGeneratorFactoryClient.java │ │ ├── service │ │ └── impl │ │ │ └── HttpSegmentIdServiceImpl.java │ │ └── utils │ │ ├── PropertiesLoader.java │ │ ├── TinyId.java │ │ ├── TinyIdHttpUtils.java │ │ └── TinyIdNumberUtils.java │ └── test │ ├── java │ └── com │ │ └── xiaoju │ │ └── uemc │ │ └── tinyid │ │ └── client │ │ └── ClientTest.java │ └── resources │ └── tinyid_client.properties └── tinyid-server ├── .gitignore ├── build.sh ├── db.sql ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── xiaoju │ │ └── uemc │ │ └── tinyid │ │ └── server │ │ ├── TinyIdServerApplication.java │ │ ├── common │ │ └── Constants.java │ │ ├── config │ │ ├── DataSourceConfig.java │ │ └── DynamicDataSource.java │ │ ├── controller │ │ └── IdContronller.java │ │ ├── dao │ │ ├── TinyIdInfoDAO.java │ │ ├── TinyIdTokenDAO.java │ │ ├── entity │ │ │ ├── TinyIdInfo.java │ │ │ └── TinyIdToken.java │ │ └── impl │ │ │ ├── TinyIdInfoDAOImpl.java │ │ │ └── TinyIdTokenDAOImpl.java │ │ ├── factory │ │ └── impl │ │ │ └── IdGeneratorFactoryServer.java │ │ ├── filter │ │ └── RequestFilter.java │ │ ├── service │ │ ├── TinyIdTokenService.java │ │ └── impl │ │ │ ├── DbSegmentIdServiceImpl.java │ │ │ └── TinyIdTokenServiceImpl.java │ │ └── vo │ │ ├── ErrorCode.java │ │ └── Response.java └── resources │ ├── offline │ ├── application.properties │ └── log4j2.xml │ └── online │ ├── application.properties │ └── log4j2.xml └── test └── java └── com └── xiaoju └── uemc └── tinyid └── server └── ServerTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | ### STS ### 3 | .apt_generated 4 | .classpath 5 | .factorypath 6 | .project 7 | .settings 8 | .springBeans 9 | 10 | ### IntelliJ IDEA ### 11 | .idea 12 | *.iws 13 | *.iml 14 | *.ipr 15 | output/* 16 | logs/* 17 | 18 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guideline 2 | 3 | Thanks for considering to contribute this project. All issues and pull requests are highly appreciated. 4 | 5 | ## Pull Requests 6 | 7 | Before sending pull request to this project, please read and follow guidelines below. 8 | 9 | 1. Branch: We only accept pull request on `dev` branch. 10 | 2. Coding style: Follow the coding style used in tinyid. 11 | 3. Commit message: Use English and be aware of your spell. 12 | 4. Test: Make sure to test your code. 13 | 14 | Add device mode, API version, related log, screenshots and other related information in your pull request if possible. 15 | 16 | NOTE: We assume all your contribution can be licensed under the [Apache License 2.0](https://github.com/didi/tinyid/blob/master/LICENSE). 17 | 18 | ## Issues 19 | 20 | We love clearly described issues. :) 21 | 22 | Following information can help us to resolve the issue faster. 23 | 24 | * Device mode and hardware information. 25 | * API version. 26 | * Logs. 27 | * Screenshots. 28 | * Steps to reproduce the issue. 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright (C) 2017 Beijing Didi Infinity Technology and Development Co.,Ltd. All rights reserved. 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Tinyid 2 | [![license](http://img.shields.io/badge/license-Apache2.0-brightgreen.svg?style=flat)](https://github.com/didi/tinyid/blob/master/LICENSE) 3 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/didi/tinyid/pulls) 4 | 5 | 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. 6 | Support jdk version 1.7+ 7 | 8 | # Getting started 9 | 10 | [中文wiki](https://github.com/didi/tinyid/wiki) 11 | 12 | ## Clone code 13 | git clone https://github.com/didi/tinyid.git 14 | 15 | ## Create table 16 | cd tinyid/tinyid-server/ && create table with db.sql (mysql) 17 | 18 | ## Config db 19 | 20 | cd tinyid-server/src/main/resources/offline 21 | vi application.properties 22 | ```properties 23 | datasource.tinyid.names=primary 24 | 25 | datasource.tinyid.primary.driver-class-name=com.mysql.jdbc.Driver 26 | datasource.tinyid.primary.url=jdbc:mysql://ip:port/databaseName?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8 27 | datasource.tinyid.primary.username=root 28 | datasource.tinyid.primary.password=123456 29 | ``` 30 | ## Start tinyid-server 31 | ```xml 32 | cd tinyid-server/ 33 | sh build.sh offline 34 | java -jar output/tinyid-server-xxx.jar 35 | ``` 36 | ## REST API 37 | ```properties 38 | nextId: 39 | curl 'http://localhost:9999/tinyid/id/nextId?bizType=test&token=0f673adf80504e2eaa552f5d791b644c' 40 | response:{"data":[2],"code":200,"message":""} 41 | 42 | nextId Simple: 43 | curl 'http://localhost:9999/tinyid/id/nextIdSimple?bizType=test&token=0f673adf80504e2eaa552f5d791b644c' 44 | response: 3 45 | 46 | with batchSize: 47 | curl 'http://localhost:9999/tinyid/id/nextIdSimple?bizType=test&token=0f673adf80504e2eaa552f5d791b644c&batchSize=10' 48 | response: 4,5,6,7,8,9,10,11,12,13 49 | 50 | Get nextId like 1,3,5,7,9... 51 | bizType=test_odd : delta is 2 and remainder is 1 52 | curl 'http://localhost:9999/tinyid/id/nextIdSimple?bizType=test_odd&batchSize=10&token=0f673adf80504e2eaa552f5d791b644c' 53 | response: 3,5,7,9,11,13,15,17,19,21 54 | ``` 55 | ## Java client (Recommended) 56 | 57 | ### Maven dependency 58 | ```xml 59 | 60 | com.xiaoju.uemc.tinyid 61 | tinyid-client 62 | ${tinyid.version} 63 | 64 | ``` 65 | 66 | ### Create tinyid_client.properties in your classpath 67 | 68 | tinyid_client.properties: 69 | ```properties 70 | tinyid.server=localhost:9999 71 | tinyid.token=0f673adf80504e2eaa552f5d791b644c 72 | 73 | #(tinyid.server=localhost:9999/gateway,ip2:port2/prefix,...) 74 | ``` 75 | ### Java Code 76 | ```java 77 | Long id = TinyId.nextId("test"); 78 | List ids = TinyId.nextId("test", 10); 79 | ``` 80 | 81 | # Communication 82 | Tinyid Community 83 | 84 | # Contributing 85 | 86 | Welcome to contribute by creating issues or sending pull requests. See [Contributing Guide](CONTRIBUTING.md) for guidelines. 87 | 88 | # License 89 | 90 | Tinyid is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file. 91 | 92 | # Note 93 | 94 | This is not an official Didi product (experimental or otherwise), it is just code that happens to be owned by Didi. 95 | -------------------------------------------------------------------------------- /doc/qqqun.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/tinyid/49976d37222ab1089a8c413b4520cc55d105d428/doc/qqqun.JPG -------------------------------------------------------------------------------- /doc/tinyid-easy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/tinyid/49976d37222ab1089a8c413b4520cc55d105d428/doc/tinyid-easy.png -------------------------------------------------------------------------------- /doc/tinyid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/tinyid/49976d37222ab1089a8c413b4520cc55d105d428/doc/tinyid.png -------------------------------------------------------------------------------- /doc/tinyid_final.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/tinyid/49976d37222ab1089a8c413b4520cc55d105d428/doc/tinyid_final.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.xiaoju.uemc.tinyid 7 | tinyid 8 | 0.1.0-SNAPSHOT 9 | pom 10 | 11 | tinyid 12 | 13 | 14 | UTF-8 15 | UTF-8 16 | 1.7 17 | 1.7 18 | 4.12 19 | 20 | 21 | 22 | 23 | 24 | com.xiaoju.uemc.tinyid 25 | tinyid-base 26 | ${project.version} 27 | 28 | 29 | com.xiaoju.uemc.tinyid 30 | tinyid-client 31 | ${project.version} 32 | 33 | 34 | junit 35 | junit 36 | ${junit.version} 37 | test 38 | 39 | 40 | 41 | 42 | 43 | tinyid-server 44 | tinyid-client 45 | tinyid-base 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /tinyid-base/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.xiaoju.uemc.tinyid 7 | tinyid 8 | 0.1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | tinyid-base 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/entity/Result.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.base.entity; 2 | 3 | /** 4 | * @author du_imba 5 | */ 6 | public class Result { 7 | private int code; 8 | private long id; 9 | 10 | public Result(int code, long id) { 11 | this.code = code; 12 | this.id = id; 13 | } 14 | 15 | public int getCode() { 16 | return code; 17 | } 18 | 19 | public void setCode(int code) { 20 | this.code = code; 21 | } 22 | 23 | public long getId() { 24 | return id; 25 | } 26 | 27 | public void setId(long id) { 28 | this.id = id; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "[id:" + id + ",code:" + code + "]"; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/entity/ResultCode.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.base.entity; 2 | 3 | /** 4 | * @author du_imba 5 | */ 6 | public class ResultCode { 7 | 8 | /** 9 | * 正常可用 10 | */ 11 | public static final int NORMAL = 1; 12 | /** 13 | * 需要去加载nextId 14 | */ 15 | public static final int LOADING = 2; 16 | /** 17 | * 超过maxId 不可用 18 | */ 19 | public static final int OVER = 3; 20 | 21 | private ResultCode(){ 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/entity/SegmentId.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.base.entity; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | /** 6 | * @author du_imba 7 | * nextId: (currentId, maxId] 8 | */ 9 | public class SegmentId { 10 | private long maxId; 11 | private long loadingId; 12 | private AtomicLong currentId; 13 | /** 14 | * increment by 15 | */ 16 | private int delta; 17 | /** 18 | * mod num 19 | */ 20 | private int remainder; 21 | 22 | private volatile boolean isInit; 23 | 24 | /** 25 | * 这个方法主要为了1,4,7,10...这种序列准备的 26 | * 设置好初始值之后,会以delta的方式递增,保证无论开始id是多少都能生成正确的序列 27 | * 如当前是号段是(1000,2000],delta=3, remainder=0,则经过这个方法后,currentId会先递增到1002,之后每次增加delta 28 | * 因为currentId会先递增,所以会浪费一个id,所以做了一次减delta的操作,实际currentId会从999开始增,第一个id还是1002 29 | */ 30 | public void init() { 31 | if (isInit) { 32 | return; 33 | } 34 | synchronized (this) { 35 | if (isInit) { 36 | return; 37 | } 38 | long id = currentId.get(); 39 | if (id % delta == remainder) { 40 | isInit = true; 41 | return; 42 | } 43 | for (int i = 0; i <= delta; i++) { 44 | id = currentId.incrementAndGet(); 45 | if (id % delta == remainder) { 46 | // 避免浪费 减掉系统自己占用的一个id 47 | currentId.addAndGet(0 - delta); 48 | isInit = true; 49 | return; 50 | } 51 | } 52 | } 53 | } 54 | 55 | public Result nextId() { 56 | init(); 57 | long id = currentId.addAndGet(delta); 58 | if (id > maxId) { 59 | return new Result(ResultCode.OVER, id); 60 | } 61 | if (id >= loadingId) { 62 | return new Result(ResultCode.LOADING, id); 63 | } 64 | return new Result(ResultCode.NORMAL, id); 65 | } 66 | 67 | public boolean useful() { 68 | return currentId.get() <= maxId; 69 | } 70 | 71 | public long getMaxId() { 72 | return maxId; 73 | } 74 | 75 | public void setMaxId(long maxId) { 76 | this.maxId = maxId; 77 | } 78 | 79 | public long getLoadingId() { 80 | return loadingId; 81 | } 82 | 83 | public void setLoadingId(long loadingId) { 84 | this.loadingId = loadingId; 85 | } 86 | 87 | public AtomicLong getCurrentId() { 88 | return currentId; 89 | } 90 | 91 | public void setCurrentId(AtomicLong currentId) { 92 | this.currentId = currentId; 93 | } 94 | 95 | public int getDelta() { 96 | return delta; 97 | } 98 | 99 | public void setDelta(int delta) { 100 | this.delta = delta; 101 | } 102 | 103 | public int getRemainder() { 104 | return remainder; 105 | } 106 | 107 | public void setRemainder(int remainder) { 108 | this.remainder = remainder; 109 | } 110 | 111 | @Override 112 | public String toString() { 113 | return "[maxId=" + maxId + ",loadingId=" + loadingId + ",currentId=" + currentId + ",delta=" + delta + ",remainder=" + remainder + "]"; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/exception/TinyIdSysException.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.base.exception; 2 | 3 | /** 4 | * @author du_imba 5 | */ 6 | public class TinyIdSysException extends RuntimeException { 7 | 8 | public TinyIdSysException() { 9 | super(); 10 | } 11 | 12 | public TinyIdSysException(String message) { 13 | super(message); 14 | } 15 | 16 | public TinyIdSysException(String message, Throwable cause) { 17 | super(message, cause); 18 | } 19 | 20 | public TinyIdSysException(Throwable cause) { 21 | super(cause); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/factory/AbstractIdGeneratorFactory.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.base.factory; 2 | 3 | import com.xiaoju.uemc.tinyid.base.generator.IdGenerator; 4 | 5 | import java.util.concurrent.ConcurrentHashMap; 6 | 7 | /** 8 | * @author du_imba 9 | */ 10 | public abstract class AbstractIdGeneratorFactory implements IdGeneratorFactory { 11 | 12 | private static ConcurrentHashMap generators = new ConcurrentHashMap<>(); 13 | 14 | @Override 15 | public IdGenerator getIdGenerator(String bizType) { 16 | if (generators.containsKey(bizType)) { 17 | return generators.get(bizType); 18 | } 19 | synchronized (this) { 20 | if (generators.containsKey(bizType)) { 21 | return generators.get(bizType); 22 | } 23 | IdGenerator idGenerator = createIdGenerator(bizType); 24 | generators.put(bizType, idGenerator); 25 | return idGenerator; 26 | } 27 | } 28 | 29 | /** 30 | * 根据bizType创建id生成器 31 | * 32 | * @param bizType 33 | * @return 34 | */ 35 | protected abstract IdGenerator createIdGenerator(String bizType); 36 | } 37 | -------------------------------------------------------------------------------- /tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/factory/IdGeneratorFactory.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.base.factory; 2 | 3 | import com.xiaoju.uemc.tinyid.base.generator.IdGenerator; 4 | 5 | /** 6 | * @author du_imba 7 | */ 8 | public interface IdGeneratorFactory { 9 | /** 10 | * 根据bizType创建id生成器 11 | * @param bizType 12 | * @return 13 | */ 14 | IdGenerator getIdGenerator(String bizType); 15 | } 16 | -------------------------------------------------------------------------------- /tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/generator/IdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.base.generator; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author du_imba 7 | */ 8 | public interface IdGenerator { 9 | /** 10 | * get next id 11 | * @return 12 | */ 13 | Long nextId(); 14 | 15 | /** 16 | * get next id batch 17 | * @param batchSize 18 | * @return 19 | */ 20 | List nextId(Integer batchSize); 21 | } 22 | -------------------------------------------------------------------------------- /tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/generator/impl/CachedIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.base.generator.impl; 2 | 3 | import com.xiaoju.uemc.tinyid.base.entity.Result; 4 | import com.xiaoju.uemc.tinyid.base.entity.ResultCode; 5 | import com.xiaoju.uemc.tinyid.base.entity.SegmentId; 6 | import com.xiaoju.uemc.tinyid.base.exception.TinyIdSysException; 7 | import com.xiaoju.uemc.tinyid.base.generator.IdGenerator; 8 | import com.xiaoju.uemc.tinyid.base.service.SegmentIdService; 9 | import com.xiaoju.uemc.tinyid.base.util.NamedThreadFactory; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.concurrent.ExecutorService; 14 | import java.util.concurrent.Executors; 15 | 16 | /** 17 | * @author du_imba 18 | */ 19 | public class CachedIdGenerator implements IdGenerator { 20 | protected String bizType; 21 | protected SegmentIdService segmentIdService; 22 | protected volatile SegmentId current; 23 | protected volatile SegmentId next; 24 | private volatile boolean isLoadingNext; 25 | private Object lock = new Object(); 26 | private ExecutorService executorService = Executors.newSingleThreadExecutor(new NamedThreadFactory("tinyid-generator")); 27 | 28 | public CachedIdGenerator(String bizType, SegmentIdService segmentIdService) { 29 | this.bizType = bizType; 30 | this.segmentIdService = segmentIdService; 31 | loadCurrent(); 32 | } 33 | 34 | public synchronized void loadCurrent() { 35 | if (current == null || !current.useful()) { 36 | if (next == null) { 37 | SegmentId segmentId = querySegmentId(); 38 | this.current = segmentId; 39 | } else { 40 | current = next; 41 | next = null; 42 | } 43 | } 44 | } 45 | 46 | private SegmentId querySegmentId() { 47 | String message = null; 48 | try { 49 | SegmentId segmentId = segmentIdService.getNextSegmentId(bizType); 50 | if (segmentId != null) { 51 | return segmentId; 52 | } 53 | } catch (Exception e) { 54 | message = e.getMessage(); 55 | } 56 | throw new TinyIdSysException("error query segmentId: " + message); 57 | } 58 | 59 | public void loadNext() { 60 | if (next == null && !isLoadingNext) { 61 | synchronized (lock) { 62 | if (next == null && !isLoadingNext) { 63 | isLoadingNext = true; 64 | executorService.submit(new Runnable() { 65 | @Override 66 | public void run() { 67 | try { 68 | // 无论获取下个segmentId成功与否,都要将isLoadingNext赋值为false 69 | next = querySegmentId(); 70 | } finally { 71 | isLoadingNext = false; 72 | } 73 | } 74 | }); 75 | } 76 | } 77 | } 78 | } 79 | 80 | @Override 81 | public Long nextId() { 82 | while (true) { 83 | if (current == null) { 84 | loadCurrent(); 85 | continue; 86 | } 87 | Result result = current.nextId(); 88 | if (result.getCode() == ResultCode.OVER) { 89 | loadCurrent(); 90 | } else { 91 | if (result.getCode() == ResultCode.LOADING) { 92 | loadNext(); 93 | } 94 | return result.getId(); 95 | } 96 | } 97 | } 98 | 99 | @Override 100 | public List nextId(Integer batchSize) { 101 | List ids = new ArrayList<>(); 102 | for (int i = 0; i < batchSize; i++) { 103 | Long id = nextId(); 104 | ids.add(id); 105 | } 106 | return ids; 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/service/SegmentIdService.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.base.service; 2 | 3 | import com.xiaoju.uemc.tinyid.base.entity.SegmentId; 4 | 5 | /** 6 | * @author du_imba 7 | */ 8 | public interface SegmentIdService { 9 | 10 | /** 11 | * 根据bizType获取下一个SegmentId对象 12 | * @param bizType 13 | * @return 14 | */ 15 | SegmentId getNextSegmentId(String bizType); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /tinyid-base/src/main/java/com/xiaoju/uemc/tinyid/base/util/NamedThreadFactory.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.base.util; 2 | 3 | import java.util.concurrent.ThreadFactory; 4 | import java.util.concurrent.atomic.AtomicInteger; 5 | 6 | /** 7 | * @Author du_imba 8 | */ 9 | public class NamedThreadFactory implements ThreadFactory { 10 | 11 | private final ThreadGroup group; 12 | private final AtomicInteger threadNumber = new AtomicInteger(1); 13 | 14 | private final String namePrefix; 15 | private final boolean daemon; 16 | 17 | public NamedThreadFactory(String namePrefix, boolean daemon) { 18 | this.daemon = daemon; 19 | SecurityManager s = System.getSecurityManager(); 20 | group = (s != null) ? s.getThreadGroup() : 21 | Thread.currentThread().getThreadGroup(); 22 | this.namePrefix = namePrefix; 23 | } 24 | 25 | public NamedThreadFactory(String namePrefix) { 26 | this(namePrefix, false); 27 | } 28 | 29 | @Override 30 | public Thread newThread(Runnable r) { 31 | Thread t = new Thread(group, r, namePrefix + "-thread-" + threadNumber.getAndIncrement(), 0); 32 | t.setDaemon(daemon); 33 | return t; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /tinyid-client/dependency-reduced-pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | tinyid 5 | com.xiaoju.uemc.tinyid 6 | 0.1.0-SNAPSHOT 7 | 8 | 4.0.0 9 | tinyid-client 10 | 11 | 12 | 13 | maven-shade-plugin 14 | 3.0.0 15 | 16 | 17 | package 18 | 19 | shade 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | junit 29 | junit 30 | 4.12 31 | test 32 | 33 | 34 | hamcrest-core 35 | org.hamcrest 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /tinyid-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.xiaoju.uemc.tinyid 7 | tinyid 8 | 0.1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | tinyid-client 13 | 14 | 15 | 16 | com.xiaoju.uemc.tinyid 17 | tinyid-base 18 | 19 | 20 | junit 21 | junit 22 | test 23 | 24 | 25 | 26 | 27 | 28 | 29 | org.apache.maven.plugins 30 | maven-shade-plugin 31 | 3.0.0 32 | 33 | 34 | package 35 | 36 | shade 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/config/TinyIdClientConfig.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.client.config; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author du_imba 7 | */ 8 | public class TinyIdClientConfig { 9 | 10 | private String tinyIdToken; 11 | private String tinyIdServer; 12 | private List serverList; 13 | private Integer readTimeout; 14 | private Integer connectTimeout; 15 | 16 | private volatile static TinyIdClientConfig tinyIdClientConfig; 17 | 18 | private TinyIdClientConfig() { 19 | } 20 | 21 | public static TinyIdClientConfig getInstance() { 22 | if (tinyIdClientConfig != null) { 23 | return tinyIdClientConfig; 24 | } 25 | synchronized (TinyIdClientConfig.class) { 26 | if (tinyIdClientConfig != null) { 27 | return tinyIdClientConfig; 28 | } 29 | tinyIdClientConfig = new TinyIdClientConfig(); 30 | } 31 | return tinyIdClientConfig; 32 | } 33 | 34 | public String getTinyIdToken() { 35 | return tinyIdToken; 36 | } 37 | 38 | public void setTinyIdToken(String tinyIdToken) { 39 | this.tinyIdToken = tinyIdToken; 40 | } 41 | 42 | public String getTinyIdServer() { 43 | return tinyIdServer; 44 | } 45 | 46 | public void setTinyIdServer(String tinyIdServer) { 47 | this.tinyIdServer = tinyIdServer; 48 | } 49 | 50 | public List getServerList() { 51 | return serverList; 52 | } 53 | 54 | public void setServerList(List serverList) { 55 | this.serverList = serverList; 56 | } 57 | 58 | public Integer getReadTimeout() { 59 | return readTimeout; 60 | } 61 | 62 | public void setReadTimeout(Integer readTimeout) { 63 | this.readTimeout = readTimeout; 64 | } 65 | 66 | public Integer getConnectTimeout() { 67 | return connectTimeout; 68 | } 69 | 70 | public void setConnectTimeout(Integer connectTimeout) { 71 | this.connectTimeout = connectTimeout; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/factory/impl/IdGeneratorFactoryClient.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.client.factory.impl; 2 | 3 | import com.xiaoju.uemc.tinyid.base.factory.AbstractIdGeneratorFactory; 4 | import com.xiaoju.uemc.tinyid.base.generator.IdGenerator; 5 | import com.xiaoju.uemc.tinyid.base.generator.impl.CachedIdGenerator; 6 | import com.xiaoju.uemc.tinyid.client.config.TinyIdClientConfig; 7 | import com.xiaoju.uemc.tinyid.client.service.impl.HttpSegmentIdServiceImpl; 8 | import com.xiaoju.uemc.tinyid.client.utils.PropertiesLoader; 9 | import com.xiaoju.uemc.tinyid.client.utils.TinyIdNumberUtils; 10 | 11 | import java.text.MessageFormat; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.Properties; 15 | import java.util.logging.Logger; 16 | 17 | /** 18 | * @author du_imba 19 | */ 20 | public class IdGeneratorFactoryClient extends AbstractIdGeneratorFactory { 21 | 22 | private static final Logger logger = Logger.getLogger(IdGeneratorFactoryClient.class.getName()); 23 | 24 | private static IdGeneratorFactoryClient idGeneratorFactoryClient; 25 | 26 | private static final String DEFAULT_PROP = "tinyid_client.properties"; 27 | 28 | private static final int DEFAULT_TIME_OUT = 5000; 29 | 30 | private static String serverUrl = "http://{0}/tinyid/id/nextSegmentIdSimple?token={1}&bizType="; 31 | 32 | private IdGeneratorFactoryClient() { 33 | 34 | } 35 | 36 | public static IdGeneratorFactoryClient getInstance(String location) { 37 | if (idGeneratorFactoryClient == null) { 38 | synchronized (IdGeneratorFactoryClient.class) { 39 | if (idGeneratorFactoryClient == null) { 40 | if (location == null || "".equals(location)) { 41 | init(DEFAULT_PROP); 42 | } else { 43 | init(location); 44 | } 45 | } 46 | } 47 | } 48 | return idGeneratorFactoryClient; 49 | } 50 | 51 | private static void init(String location) { 52 | idGeneratorFactoryClient = new IdGeneratorFactoryClient(); 53 | Properties properties = PropertiesLoader.loadProperties(location); 54 | String tinyIdToken = properties.getProperty("tinyid.token"); 55 | String tinyIdServer = properties.getProperty("tinyid.server"); 56 | String readTimeout = properties.getProperty("tinyid.readTimeout"); 57 | String connectTimeout = properties.getProperty("tinyid.connectTimeout"); 58 | 59 | if (tinyIdToken == null || "".equals(tinyIdToken.trim()) 60 | || tinyIdServer == null || "".equals(tinyIdServer.trim())) { 61 | throw new IllegalArgumentException("cannot find tinyid.token and tinyid.server config in:" + location); 62 | } 63 | 64 | TinyIdClientConfig tinyIdClientConfig = TinyIdClientConfig.getInstance(); 65 | tinyIdClientConfig.setTinyIdServer(tinyIdServer); 66 | tinyIdClientConfig.setTinyIdToken(tinyIdToken); 67 | tinyIdClientConfig.setReadTimeout(TinyIdNumberUtils.toInt(readTimeout, DEFAULT_TIME_OUT)); 68 | tinyIdClientConfig.setConnectTimeout(TinyIdNumberUtils.toInt(connectTimeout, DEFAULT_TIME_OUT)); 69 | 70 | String[] tinyIdServers = tinyIdServer.split(","); 71 | List serverList = new ArrayList<>(tinyIdServers.length); 72 | for (String server : tinyIdServers) { 73 | String url = MessageFormat.format(serverUrl, server, tinyIdToken); 74 | serverList.add(url); 75 | } 76 | logger.info("init tinyId client success url info:" + serverList); 77 | tinyIdClientConfig.setServerList(serverList); 78 | } 79 | 80 | @Override 81 | protected IdGenerator createIdGenerator(String bizType) { 82 | return new CachedIdGenerator(bizType, new HttpSegmentIdServiceImpl()); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/service/impl/HttpSegmentIdServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.client.service.impl; 2 | 3 | import com.xiaoju.uemc.tinyid.base.entity.SegmentId; 4 | import com.xiaoju.uemc.tinyid.base.service.SegmentIdService; 5 | import com.xiaoju.uemc.tinyid.client.config.TinyIdClientConfig; 6 | import com.xiaoju.uemc.tinyid.client.utils.TinyIdHttpUtils; 7 | 8 | import java.util.List; 9 | import java.util.Random; 10 | import java.util.concurrent.atomic.AtomicLong; 11 | import java.util.logging.Logger; 12 | 13 | /** 14 | * @author du_imba 15 | */ 16 | public class HttpSegmentIdServiceImpl implements SegmentIdService { 17 | 18 | private static final Logger logger = Logger.getLogger(HttpSegmentIdServiceImpl.class.getName()); 19 | 20 | @Override 21 | public SegmentId getNextSegmentId(String bizType) { 22 | String url = chooseService(bizType); 23 | String response = TinyIdHttpUtils.post(url, TinyIdClientConfig.getInstance().getReadTimeout(), 24 | TinyIdClientConfig.getInstance().getConnectTimeout()); 25 | logger.info("tinyId client getNextSegmentId end, response:" + response); 26 | if (response == null || "".equals(response.trim())) { 27 | return null; 28 | } 29 | SegmentId segmentId = new SegmentId(); 30 | String[] arr = response.split(","); 31 | segmentId.setCurrentId(new AtomicLong(Long.parseLong(arr[0]))); 32 | segmentId.setLoadingId(Long.parseLong(arr[1])); 33 | segmentId.setMaxId(Long.parseLong(arr[2])); 34 | segmentId.setDelta(Integer.parseInt(arr[3])); 35 | segmentId.setRemainder(Integer.parseInt(arr[4])); 36 | return segmentId; 37 | } 38 | 39 | private String chooseService(String bizType) { 40 | List serverList = TinyIdClientConfig.getInstance().getServerList(); 41 | String url = ""; 42 | if (serverList != null && serverList.size() == 1) { 43 | url = serverList.get(0); 44 | } else if (serverList != null && serverList.size() > 1) { 45 | Random r = new Random(); 46 | url = serverList.get(r.nextInt(serverList.size())); 47 | } 48 | url += bizType; 49 | return url; 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/utils/PropertiesLoader.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.client.utils; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStreamReader; 5 | import java.util.Properties; 6 | import java.util.logging.Level; 7 | import java.util.logging.Logger; 8 | 9 | /** 10 | * @author du_imba 11 | */ 12 | public class PropertiesLoader { 13 | private static final Logger logger = Logger.getLogger(PropertiesLoader.class.getName()); 14 | 15 | private PropertiesLoader() { 16 | 17 | } 18 | 19 | public static Properties loadProperties(String location) { 20 | Properties props = new Properties(); 21 | logger.info("Loading properties file from path:" + location); 22 | InputStreamReader in = null; 23 | try { 24 | in = new InputStreamReader(PropertiesLoader.class.getClassLoader().getResourceAsStream(location), "UTF-8"); 25 | props.load(in); 26 | } catch (Exception e) { 27 | throw new IllegalStateException(e); 28 | } finally { 29 | if(in != null) { 30 | try { 31 | in.close(); 32 | } catch (IOException e) { 33 | logger.log(Level.WARNING, "error close inputstream", e); 34 | } 35 | } 36 | } 37 | return props; 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/utils/TinyId.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.client.utils; 2 | 3 | import com.xiaoju.uemc.tinyid.client.factory.impl.IdGeneratorFactoryClient; 4 | import com.xiaoju.uemc.tinyid.base.generator.IdGenerator; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * @author du_imba 11 | */ 12 | public class TinyId { 13 | private static IdGeneratorFactoryClient client = IdGeneratorFactoryClient.getInstance(null); 14 | 15 | private TinyId() { 16 | 17 | } 18 | 19 | public static Long nextId(String bizType) { 20 | if(bizType == null) { 21 | throw new IllegalArgumentException("type is null"); 22 | } 23 | IdGenerator idGenerator = client.getIdGenerator(bizType); 24 | return idGenerator.nextId(); 25 | } 26 | 27 | public static List nextId(String bizType, Integer batchSize) { 28 | if(batchSize == null) { 29 | Long id = nextId(bizType); 30 | List list = new ArrayList<>(); 31 | list.add(id); 32 | return list; 33 | } 34 | IdGenerator idGenerator = client.getIdGenerator(bizType); 35 | return idGenerator.nextId(batchSize); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/utils/TinyIdHttpUtils.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.client.utils; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.io.OutputStreamWriter; 7 | import java.net.HttpURLConnection; 8 | import java.net.URL; 9 | import java.util.Map; 10 | import java.util.logging.Level; 11 | import java.util.logging.Logger; 12 | 13 | /** 14 | * @author du_imba 15 | */ 16 | public class TinyIdHttpUtils { 17 | 18 | private static final Logger logger = Logger.getLogger(TinyIdHttpUtils.class.getName()); 19 | 20 | 21 | private TinyIdHttpUtils() { 22 | 23 | } 24 | 25 | public static String post(String url, Integer readTimeout, Integer connectTimeout) { 26 | return post(url, null, readTimeout, connectTimeout); 27 | } 28 | 29 | public static String post(String url, Map form, Integer readTimeout, Integer connectTimeout) { 30 | HttpURLConnection conn = null; 31 | OutputStreamWriter os = null; 32 | BufferedReader rd = null; 33 | StringBuilder param = new StringBuilder(); 34 | StringBuilder sb = new StringBuilder(); 35 | String line = null; 36 | String response = null; 37 | if (form != null) { 38 | for (Map.Entry entry : form.entrySet()) { 39 | String key = entry.getKey(); 40 | if (param.length() != 0) { 41 | param.append("&"); 42 | } 43 | param.append(key).append("=").append(entry.getValue()); 44 | } 45 | } 46 | try { 47 | conn = (HttpURLConnection) new URL(url).openConnection(); 48 | conn.setRequestMethod("POST"); 49 | conn.setDoOutput(true); 50 | conn.setDoInput(true); 51 | conn.setReadTimeout(readTimeout); 52 | conn.setConnectTimeout(connectTimeout); 53 | conn.setUseCaches(false); 54 | conn.connect(); 55 | os = new OutputStreamWriter(conn.getOutputStream(), "UTF-8"); 56 | os.write(param.toString()); 57 | os.flush(); 58 | rd = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); 59 | while ((line = rd.readLine()) != null) { 60 | sb.append(line); 61 | } 62 | response = sb.toString(); 63 | } catch (Exception e) { 64 | logger.log(Level.SEVERE, "error post url:" + url + param, e); 65 | } finally { 66 | try { 67 | if (os != null) { 68 | os.close(); 69 | } 70 | if (rd != null) { 71 | rd.close(); 72 | } 73 | if (conn != null) { 74 | conn.disconnect(); 75 | } 76 | } catch (IOException e) { 77 | logger.log(Level.WARNING, "error close conn", e); 78 | } 79 | } 80 | return response; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /tinyid-client/src/main/java/com/xiaoju/uemc/tinyid/client/utils/TinyIdNumberUtils.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.client.utils; 2 | 3 | /** 4 | * @Author du_imba 5 | */ 6 | public class TinyIdNumberUtils { 7 | 8 | public static int toInt(String str) { 9 | return toInt(str, 0); 10 | } 11 | 12 | public static int toInt(String str, int defaultValue) { 13 | if (str == null) { 14 | return defaultValue; 15 | } 16 | try { 17 | return Integer.parseInt(str); 18 | } catch (NumberFormatException nfe) { 19 | return defaultValue; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tinyid-client/src/test/java/com/xiaoju/uemc/tinyid/client/ClientTest.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.client; 2 | 3 | import com.xiaoju.uemc.tinyid.client.utils.TinyId; 4 | import org.junit.Test; 5 | 6 | /** 7 | * @Author du_imba 8 | */ 9 | 10 | public class ClientTest { 11 | 12 | @Test 13 | public void testNextId() { 14 | for (int i = 0; i < 100; i++) { 15 | Long id = TinyId.nextId("test"); 16 | System.out.println("current id is: " + id); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tinyid-client/src/test/resources/tinyid_client.properties: -------------------------------------------------------------------------------- 1 | tinyid.server=localhost:9999 2 | tinyid.token=0f673adf80504e2eaa552f5d791b644c 3 | -------------------------------------------------------------------------------- /tinyid-server/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ 25 | output/* 26 | logs -------------------------------------------------------------------------------- /tinyid-server/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #export JAVA_HOME=xxx 3 | #export PATH=$JAVA_HOME/bin:$PATH 4 | # 5 | #export MAVEN_HOME=xxxx 6 | #export PATH=$MAVEN_HOME/bin:$PATH 7 | # 8 | 9 | module=tinyid-server 10 | 11 | env=$1 12 | 13 | if [ -z "$env" ]; then 14 | env='online' 15 | fi 16 | 17 | echo "build $env begin" 18 | 19 | mvn clean package -P$env -Dmaven.test.skip=true -f ../pom.xml 20 | ret=$? 21 | if [ $ret -ne 0 ];then 22 | echo "===== maven build failure =====" 23 | exit $ret 24 | else 25 | echo -n "===== maven build successfully! =====" 26 | fi 27 | rm -rf output 28 | mkdir output 29 | mv target/${module}-*.jar output 30 | cd output 31 | -------------------------------------------------------------------------------- /tinyid-server/db.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `tiny_id_info` ( 2 | `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键', 3 | `biz_type` varchar(63) NOT NULL DEFAULT '' COMMENT '业务类型,唯一', 4 | `begin_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '开始id,仅记录初始值,无其他含义。初始化时begin_id和max_id应相同', 5 | `max_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '当前最大id', 6 | `step` int(11) DEFAULT '0' COMMENT '步长', 7 | `delta` int(11) NOT NULL DEFAULT '1' COMMENT '每次id增量', 8 | `remainder` int(11) NOT NULL DEFAULT '0' COMMENT '余数', 9 | `create_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '创建时间', 10 | `update_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '更新时间', 11 | `version` bigint(20) NOT NULL DEFAULT '0' COMMENT '版本号', 12 | PRIMARY KEY (`id`), 13 | UNIQUE KEY `uniq_biz_type` (`biz_type`) 14 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT 'id信息表'; 15 | 16 | CREATE TABLE `tiny_id_token` ( 17 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', 18 | `token` varchar(255) NOT NULL DEFAULT '' COMMENT 'token', 19 | `biz_type` varchar(63) NOT NULL DEFAULT '' COMMENT '此token可访问的业务类型标识', 20 | `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注', 21 | `create_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '创建时间', 22 | `update_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '更新时间', 23 | PRIMARY KEY (`id`) 24 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT 'token信息表'; 25 | 26 | INSERT INTO `tiny_id_info` (`id`, `biz_type`, `begin_id`, `max_id`, `step`, `delta`, `remainder`, `create_time`, `update_time`, `version`) 27 | VALUES 28 | (1, 'test', 1, 1, 100000, 1, 0, '2018-07-21 23:52:58', '2018-07-22 23:19:27', 1); 29 | 30 | INSERT INTO `tiny_id_info` (`id`, `biz_type`, `begin_id`, `max_id`, `step`, `delta`, `remainder`, `create_time`, `update_time`, `version`) 31 | VALUES 32 | (2, 'test_odd', 1, 1, 100000, 2, 1, '2018-07-21 23:52:58', '2018-07-23 00:39:24', 3); 33 | 34 | 35 | INSERT INTO `tiny_id_token` (`id`, `token`, `biz_type`, `remark`, `create_time`, `update_time`) 36 | VALUES 37 | (1, '0f673adf80504e2eaa552f5d791b644c', 'test', '1', '2017-12-14 16:36:46', '2017-12-14 16:36:48'); 38 | 39 | INSERT INTO `tiny_id_token` (`id`, `token`, `biz_type`, `remark`, `create_time`, `update_time`) 40 | VALUES 41 | (2, '0f673adf80504e2eaa552f5d791b644c', 'test_odd', '1', '2017-12-14 16:36:46', '2017-12-14 16:36:48'); 42 | 43 | -------------------------------------------------------------------------------- /tinyid-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | com.xiaoju.uemc.tinyid 7 | tinyid 8 | 0.1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | tinyid-server 13 | 14 | 15 | 1.5.9.RELEASE 16 | 17 | 18 | 19 | 20 | com.xiaoju.uemc.tinyid 21 | tinyid-base 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-web 27 | ${spring.version} 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-logging 32 | 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-tomcat 38 | ${spring.version} 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-test 43 | ${spring.version} 44 | test 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-log4j2 49 | ${spring.version} 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-starter-jdbc 54 | ${spring.version} 55 | 56 | 57 | 58 | junit 59 | junit 60 | test 61 | 62 | 63 | mysql 64 | mysql-connector-java 65 | 5.1.44 66 | 67 | 68 | commons-beanutils 69 | commons-beanutils 70 | 1.9.3 71 | 72 | 73 | 74 | 75 | 76 | online 77 | 78 | online 79 | 80 | 81 | 82 | offline 83 | 84 | true 85 | 86 | 87 | offline 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | org.springframework.boot 96 | spring-boot-maven-plugin 97 | ${spring.version} 98 | 99 | 100 | 101 | repackage 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | src/main/resources/${package.environment} 110 | 111 | 112 | src/main/resources/base 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/TinyIdServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | import org.springframework.scheduling.annotation.EnableScheduling; 7 | 8 | /** 9 | * @author du_imba 10 | */ 11 | @EnableAsync 12 | @SpringBootApplication 13 | @EnableScheduling 14 | public class TinyIdServerApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(TinyIdServerApplication.class, args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/common/Constants.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.common; 2 | 3 | /** 4 | * @author du_imba 5 | */ 6 | public class Constants { 7 | /** 8 | * 预加载下个号段的百分比 9 | */ 10 | public static final int LOADING_PERCENT = 20; 11 | /** 12 | * 重试次数 13 | */ 14 | public static final int RETRY = 3; 15 | 16 | private Constants() { 17 | 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/config/DataSourceConfig.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.config; 2 | 3 | import org.apache.commons.beanutils.BeanUtils; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; 8 | import org.springframework.boot.bind.RelaxedPropertyResolver; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.core.env.Environment; 12 | 13 | import javax.sql.DataSource; 14 | import java.util.ArrayList; 15 | import java.util.HashMap; 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | /** 20 | * @author du_imba 21 | */ 22 | @Configuration 23 | public class DataSourceConfig { 24 | 25 | private static final Logger logger = LoggerFactory.getLogger(DataSourceConfig.class); 26 | 27 | @Autowired 28 | private Environment environment; 29 | private static final String SEP = ","; 30 | 31 | private static final String DEFAULT_DATASOURCE_TYPE = "org.apache.tomcat.jdbc.pool.DataSource"; 32 | 33 | @Bean 34 | public DataSource getDynamicDataSource() { 35 | DynamicDataSource routingDataSource = new DynamicDataSource(); 36 | List dataSourceKeys = new ArrayList<>(); 37 | RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(environment, "datasource.tinyid."); 38 | String names = propertyResolver.getProperty("names"); 39 | String dataSourceType = propertyResolver.getProperty("type"); 40 | 41 | Map targetDataSources = new HashMap<>(4); 42 | routingDataSource.setTargetDataSources(targetDataSources); 43 | routingDataSource.setDataSourceKeys(dataSourceKeys); 44 | // 多个数据源 45 | for (String name : names.split(SEP)) { 46 | Map dsMap = propertyResolver.getSubProperties(name + "."); 47 | DataSource dataSource = buildDataSource(dataSourceType, dsMap); 48 | buildDataSourceProperties(dataSource, dsMap); 49 | targetDataSources.put(name, dataSource); 50 | dataSourceKeys.add(name); 51 | } 52 | return routingDataSource; 53 | } 54 | 55 | private void buildDataSourceProperties(DataSource dataSource, Map dsMap) { 56 | try { 57 | // 此方法性能差,慎用 58 | BeanUtils.copyProperties(dataSource, dsMap); 59 | } catch (Exception e) { 60 | logger.error("error copy properties", e); 61 | } 62 | } 63 | 64 | private DataSource buildDataSource(String dataSourceType, Map dsMap) { 65 | try { 66 | String className = DEFAULT_DATASOURCE_TYPE; 67 | if (dataSourceType != null && !"".equals(dataSourceType.trim())) { 68 | className = dataSourceType; 69 | } 70 | Class type = (Class) Class.forName(className); 71 | String driverClassName = dsMap.get("driver-class-name").toString(); 72 | String url = dsMap.get("url").toString(); 73 | String username = dsMap.get("username").toString(); 74 | String password = dsMap.get("password").toString(); 75 | 76 | return DataSourceBuilder.create() 77 | .driverClassName(driverClassName) 78 | .url(url) 79 | .username(username) 80 | .password(password) 81 | .type(type) 82 | .build(); 83 | 84 | } catch (ClassNotFoundException e) { 85 | logger.error("buildDataSource error", e); 86 | throw new IllegalStateException(e); 87 | } 88 | } 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/config/DynamicDataSource.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.config; 2 | 3 | import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; 4 | 5 | import java.util.List; 6 | import java.util.Random; 7 | 8 | /** 9 | * @author du_imba 10 | */ 11 | public class DynamicDataSource extends AbstractRoutingDataSource { 12 | 13 | private List dataSourceKeys; 14 | 15 | @Override 16 | protected Object determineCurrentLookupKey() { 17 | if(dataSourceKeys.size() == 1) { 18 | return dataSourceKeys.get(0); 19 | } 20 | Random r = new Random(); 21 | return dataSourceKeys.get(r.nextInt(dataSourceKeys.size())); 22 | } 23 | 24 | public List getDataSourceKeys() { 25 | return dataSourceKeys; 26 | } 27 | 28 | public void setDataSourceKeys(List dataSourceKeys) { 29 | this.dataSourceKeys = dataSourceKeys; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/controller/IdContronller.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.controller; 2 | 3 | import com.xiaoju.uemc.tinyid.base.entity.SegmentId; 4 | import com.xiaoju.uemc.tinyid.base.generator.IdGenerator; 5 | import com.xiaoju.uemc.tinyid.base.service.SegmentIdService; 6 | import com.xiaoju.uemc.tinyid.server.factory.impl.IdGeneratorFactoryServer; 7 | import com.xiaoju.uemc.tinyid.server.service.TinyIdTokenService; 8 | import com.xiaoju.uemc.tinyid.server.vo.ErrorCode; 9 | import com.xiaoju.uemc.tinyid.server.vo.Response; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.beans.factory.annotation.Value; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RestController; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * @author du_imba 21 | */ 22 | @RestController 23 | @RequestMapping("/id/") 24 | public class IdContronller { 25 | 26 | private static final Logger logger = LoggerFactory.getLogger(IdContronller.class); 27 | @Autowired 28 | private IdGeneratorFactoryServer idGeneratorFactoryServer; 29 | @Autowired 30 | private SegmentIdService segmentIdService; 31 | @Autowired 32 | private TinyIdTokenService tinyIdTokenService; 33 | @Value("${batch.size.max}") 34 | private Integer batchSizeMax; 35 | 36 | @RequestMapping("nextId") 37 | public Response> nextId(String bizType, Integer batchSize, String token) { 38 | Response> response = new Response<>(); 39 | Integer newBatchSize = checkBatchSize(batchSize); 40 | if (!tinyIdTokenService.canVisit(bizType, token)) { 41 | response.setCode(ErrorCode.TOKEN_ERR.getCode()); 42 | response.setMessage(ErrorCode.TOKEN_ERR.getMessage()); 43 | return response; 44 | } 45 | try { 46 | IdGenerator idGenerator = idGeneratorFactoryServer.getIdGenerator(bizType); 47 | List ids = idGenerator.nextId(newBatchSize); 48 | response.setData(ids); 49 | } catch (Exception e) { 50 | response.setCode(ErrorCode.SYS_ERR.getCode()); 51 | response.setMessage(e.getMessage()); 52 | logger.error("nextId error", e); 53 | } 54 | return response; 55 | } 56 | 57 | private Integer checkBatchSize(Integer batchSize) { 58 | if (batchSize == null) { 59 | batchSize = 1; 60 | } 61 | if (batchSize > batchSizeMax) { 62 | batchSize = batchSizeMax; 63 | } 64 | return batchSize; 65 | } 66 | 67 | @RequestMapping("nextIdSimple") 68 | public String nextIdSimple(String bizType, Integer batchSize, String token) { 69 | Integer newBatchSize = checkBatchSize(batchSize); 70 | if (!tinyIdTokenService.canVisit(bizType, token)) { 71 | return ""; 72 | } 73 | String response = ""; 74 | try { 75 | IdGenerator idGenerator = idGeneratorFactoryServer.getIdGenerator(bizType); 76 | if (newBatchSize == 1) { 77 | Long id = idGenerator.nextId(); 78 | response = id + ""; 79 | } else { 80 | List idList = idGenerator.nextId(newBatchSize); 81 | StringBuilder sb = new StringBuilder(); 82 | for (Long id : idList) { 83 | sb.append(id).append(","); 84 | } 85 | response = sb.deleteCharAt(sb.length() - 1).toString(); 86 | } 87 | } catch (Exception e) { 88 | logger.error("nextIdSimple error", e); 89 | } 90 | return response; 91 | } 92 | 93 | @RequestMapping("nextSegmentId") 94 | public Response nextSegmentId(String bizType, String token) { 95 | Response response = new Response<>(); 96 | if (!tinyIdTokenService.canVisit(bizType, token)) { 97 | response.setCode(ErrorCode.TOKEN_ERR.getCode()); 98 | response.setMessage(ErrorCode.TOKEN_ERR.getMessage()); 99 | return response; 100 | } 101 | try { 102 | SegmentId segmentId = segmentIdService.getNextSegmentId(bizType); 103 | response.setData(segmentId); 104 | } catch (Exception e) { 105 | response.setCode(ErrorCode.SYS_ERR.getCode()); 106 | response.setMessage(e.getMessage()); 107 | logger.error("nextSegmentId error", e); 108 | } 109 | return response; 110 | } 111 | 112 | @RequestMapping("nextSegmentIdSimple") 113 | public String nextSegmentIdSimple(String bizType, String token) { 114 | if (!tinyIdTokenService.canVisit(bizType, token)) { 115 | return ""; 116 | } 117 | String response = ""; 118 | try { 119 | SegmentId segmentId = segmentIdService.getNextSegmentId(bizType); 120 | response = segmentId.getCurrentId() + "," + segmentId.getLoadingId() + "," + segmentId.getMaxId() 121 | + "," + segmentId.getDelta() + "," + segmentId.getRemainder(); 122 | } catch (Exception e) { 123 | logger.error("nextSegmentIdSimple error", e); 124 | } 125 | return response; 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/TinyIdInfoDAO.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.dao; 2 | 3 | import com.xiaoju.uemc.tinyid.server.dao.entity.TinyIdInfo; 4 | 5 | /** 6 | * @author du_imba 7 | */ 8 | public interface TinyIdInfoDAO { 9 | /** 10 | * 根据bizType获取db中的tinyId对象 11 | * @param bizType 12 | * @return 13 | */ 14 | TinyIdInfo queryByBizType(String bizType); 15 | 16 | /** 17 | * 根据id、oldMaxId、version、bizType更新最新的maxId 18 | * @param id 19 | * @param newMaxId 20 | * @param oldMaxId 21 | * @param version 22 | * @param bizType 23 | * @return 24 | */ 25 | int updateMaxId(Long id, Long newMaxId, Long oldMaxId, Long version, String bizType); 26 | } 27 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/TinyIdTokenDAO.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.dao; 2 | 3 | import com.xiaoju.uemc.tinyid.server.dao.entity.TinyIdToken; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @author du_imba 9 | */ 10 | public interface TinyIdTokenDAO { 11 | /** 12 | * 查询db中所有的token信息 13 | * @return 14 | */ 15 | List selectAll(); 16 | } 17 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/entity/TinyIdInfo.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.dao.entity; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * @author du_imba 7 | */ 8 | public class TinyIdInfo { 9 | private Long id; 10 | 11 | private String bizType; 12 | 13 | private Long beginId; 14 | 15 | private Long maxId; 16 | 17 | private Integer step; 18 | 19 | private Integer delta; 20 | 21 | private Integer remainder; 22 | 23 | private Date createTime; 24 | 25 | private Date updateTime; 26 | 27 | private Long version; 28 | 29 | public Long getId() { 30 | return id; 31 | } 32 | 33 | public void setId(Long id) { 34 | this.id = id; 35 | } 36 | 37 | public String getBizType() { 38 | return bizType; 39 | } 40 | 41 | public void setBizType(String bizType) { 42 | this.bizType = bizType; 43 | } 44 | 45 | public Long getBeginId() { 46 | return beginId; 47 | } 48 | 49 | public void setBeginId(Long beginId) { 50 | this.beginId = beginId; 51 | } 52 | 53 | public Long getMaxId() { 54 | return maxId; 55 | } 56 | 57 | public void setMaxId(Long maxId) { 58 | this.maxId = maxId; 59 | } 60 | 61 | public Integer getStep() { 62 | return step; 63 | } 64 | 65 | public void setStep(Integer step) { 66 | this.step = step; 67 | } 68 | 69 | public Integer getDelta() { 70 | return delta; 71 | } 72 | 73 | public void setDelta(Integer delta) { 74 | this.delta = delta; 75 | } 76 | 77 | public Integer getRemainder() { 78 | return remainder; 79 | } 80 | 81 | public void setRemainder(Integer remainder) { 82 | this.remainder = remainder; 83 | } 84 | 85 | public Date getCreateTime() { 86 | return createTime; 87 | } 88 | 89 | public void setCreateTime(Date createTime) { 90 | this.createTime = createTime; 91 | } 92 | 93 | public Date getUpdateTime() { 94 | return updateTime; 95 | } 96 | 97 | public void setUpdateTime(Date updateTime) { 98 | this.updateTime = updateTime; 99 | } 100 | 101 | public Long getVersion() { 102 | return version; 103 | } 104 | 105 | public void setVersion(Long version) { 106 | this.version = version; 107 | } 108 | } -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/entity/TinyIdToken.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.dao.entity; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * @author du_imba 7 | */ 8 | public class TinyIdToken { 9 | private Integer id; 10 | 11 | private String token; 12 | 13 | private String bizType; 14 | 15 | private String remark; 16 | 17 | private Date createTime; 18 | 19 | private Date updateTime; 20 | 21 | public Integer getId() { 22 | return id; 23 | } 24 | 25 | public void setId(Integer id) { 26 | this.id = id; 27 | } 28 | 29 | public String getToken() { 30 | return token; 31 | } 32 | 33 | public void setToken(String token) { 34 | this.token = token == null ? null : token.trim(); 35 | } 36 | 37 | public String getBizType() { 38 | return bizType; 39 | } 40 | 41 | public void setBizType(String bizType) { 42 | this.bizType = bizType == null ? null : bizType.trim(); 43 | } 44 | 45 | public String getRemark() { 46 | return remark; 47 | } 48 | 49 | public void setRemark(String remark) { 50 | this.remark = remark == null ? null : remark.trim(); 51 | } 52 | 53 | public Date getCreateTime() { 54 | return createTime; 55 | } 56 | 57 | public void setCreateTime(Date createTime) { 58 | this.createTime = createTime; 59 | } 60 | 61 | public Date getUpdateTime() { 62 | return updateTime; 63 | } 64 | 65 | public void setUpdateTime(Date updateTime) { 66 | this.updateTime = updateTime; 67 | } 68 | } -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/impl/TinyIdInfoDAOImpl.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.dao.impl; 2 | 3 | import com.xiaoju.uemc.tinyid.server.dao.TinyIdInfoDAO; 4 | import com.xiaoju.uemc.tinyid.server.dao.entity.TinyIdInfo; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.jdbc.core.JdbcTemplate; 7 | import org.springframework.jdbc.core.RowMapper; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.sql.ResultSet; 11 | import java.sql.SQLException; 12 | import java.util.List; 13 | 14 | /** 15 | * @author du_imba 16 | */ 17 | @Repository 18 | public class TinyIdInfoDAOImpl implements TinyIdInfoDAO { 19 | 20 | @Autowired 21 | private JdbcTemplate jdbcTemplate; 22 | 23 | @Override 24 | public TinyIdInfo queryByBizType(String bizType) { 25 | String sql = "select id, biz_type, begin_id, max_id," + 26 | " step, delta, remainder, create_time, update_time, version" + 27 | " from tiny_id_info where biz_type = ?"; 28 | List list = jdbcTemplate.query(sql, new Object[]{bizType}, new TinyIdInfoRowMapper()); 29 | if(list == null || list.isEmpty()) { 30 | return null; 31 | } 32 | return list.get(0); 33 | } 34 | 35 | @Override 36 | public int updateMaxId(Long id, Long newMaxId, Long oldMaxId, Long version, String bizType) { 37 | String sql = "update tiny_id_info set max_id= ?," + 38 | " update_time=now(), version=version+1" + 39 | " where id=? and max_id=? and version=? and biz_type=?"; 40 | return jdbcTemplate.update(sql, newMaxId, id, oldMaxId, version, bizType); 41 | } 42 | 43 | 44 | public static class TinyIdInfoRowMapper implements RowMapper { 45 | 46 | @Override 47 | public TinyIdInfo mapRow(ResultSet resultSet, int i) throws SQLException { 48 | TinyIdInfo tinyIdInfo = new TinyIdInfo(); 49 | tinyIdInfo.setId(resultSet.getLong("id")); 50 | tinyIdInfo.setBizType(resultSet.getString("biz_type")); 51 | tinyIdInfo.setBeginId(resultSet.getLong("begin_id")); 52 | tinyIdInfo.setMaxId(resultSet.getLong("max_id")); 53 | tinyIdInfo.setStep(resultSet.getInt("step")); 54 | tinyIdInfo.setDelta(resultSet.getInt("delta")); 55 | tinyIdInfo.setRemainder(resultSet.getInt("remainder")); 56 | tinyIdInfo.setCreateTime(resultSet.getDate("create_time")); 57 | tinyIdInfo.setUpdateTime(resultSet.getDate("update_time")); 58 | tinyIdInfo.setVersion(resultSet.getLong("version")); 59 | return tinyIdInfo; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/dao/impl/TinyIdTokenDAOImpl.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.dao.impl; 2 | 3 | import com.xiaoju.uemc.tinyid.server.dao.TinyIdTokenDAO; 4 | import com.xiaoju.uemc.tinyid.server.dao.entity.TinyIdToken; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.jdbc.core.JdbcTemplate; 7 | import org.springframework.jdbc.core.RowMapper; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.sql.ResultSet; 11 | import java.sql.SQLException; 12 | import java.util.List; 13 | 14 | /** 15 | * @author du_imba 16 | */ 17 | @Repository 18 | public class TinyIdTokenDAOImpl implements TinyIdTokenDAO { 19 | 20 | @Autowired 21 | private JdbcTemplate jdbcTemplate; 22 | 23 | @Override 24 | public List selectAll() { 25 | String sql = "select id, token, biz_type, remark, " + 26 | "create_time, update_time from tiny_id_token"; 27 | return jdbcTemplate.query(sql, new TinyIdTokenRowMapper()); 28 | } 29 | 30 | public static class TinyIdTokenRowMapper implements RowMapper { 31 | 32 | @Override 33 | public TinyIdToken mapRow(ResultSet resultSet, int i) throws SQLException { 34 | TinyIdToken token = new TinyIdToken(); 35 | token.setId(resultSet.getInt("id")); 36 | token.setToken(resultSet.getString("token")); 37 | token.setBizType(resultSet.getString("biz_type")); 38 | token.setRemark(resultSet.getString("remark")); 39 | token.setCreateTime(resultSet.getDate("create_time")); 40 | token.setUpdateTime(resultSet.getDate("update_time")); 41 | return token; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/factory/impl/IdGeneratorFactoryServer.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.factory.impl; 2 | 3 | import com.xiaoju.uemc.tinyid.base.factory.AbstractIdGeneratorFactory; 4 | import com.xiaoju.uemc.tinyid.base.generator.IdGenerator; 5 | import com.xiaoju.uemc.tinyid.base.generator.impl.CachedIdGenerator; 6 | import com.xiaoju.uemc.tinyid.base.service.SegmentIdService; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * @author du_imba 14 | */ 15 | @Component 16 | public class IdGeneratorFactoryServer extends AbstractIdGeneratorFactory { 17 | 18 | private static final Logger logger = LoggerFactory.getLogger(CachedIdGenerator.class); 19 | @Autowired 20 | private SegmentIdService tinyIdService; 21 | 22 | @Override 23 | public IdGenerator createIdGenerator(String bizType) { 24 | logger.info("createIdGenerator :{}", bizType); 25 | return new CachedIdGenerator(bizType, tinyIdService); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/filter/RequestFilter.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.filter; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.boot.web.servlet.ServletComponentScan; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.util.StringUtils; 8 | 9 | import javax.servlet.Filter; 10 | import javax.servlet.FilterChain; 11 | import javax.servlet.FilterConfig; 12 | import javax.servlet.ServletException; 13 | import javax.servlet.ServletRequest; 14 | import javax.servlet.ServletResponse; 15 | import javax.servlet.annotation.WebFilter; 16 | import javax.servlet.http.HttpServletRequest; 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.io.IOException; 19 | import java.util.Map; 20 | 21 | /** 22 | * @Author du_imba 23 | */ 24 | @Component 25 | @ServletComponentScan 26 | @WebFilter(urlPatterns = "/*", filterName = "requestFilter") 27 | public class RequestFilter implements Filter { 28 | 29 | private static final Logger logger = LoggerFactory.getLogger(RequestFilter.class); 30 | 31 | @Override 32 | public void init(FilterConfig filterConfig) throws ServletException { 33 | 34 | } 35 | 36 | @Override 37 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 38 | HttpServletRequest request = (HttpServletRequest) servletRequest; 39 | HttpServletResponse response = (HttpServletResponse) servletResponse; 40 | String params = ""; 41 | Map paramsMap = request.getParameterMap(); 42 | if (paramsMap != null && !paramsMap.isEmpty()) { 43 | for (Map.Entry entry : paramsMap.entrySet()) { 44 | params += entry.getKey() + ":" + StringUtils.arrayToDelimitedString(entry.getValue(), ",") + ";"; 45 | } 46 | } 47 | long start = System.currentTimeMillis(); 48 | try { 49 | filterChain.doFilter(request, response); 50 | } catch (Throwable e) { 51 | throw e; 52 | } finally { 53 | long cost = System.currentTimeMillis() - start; 54 | logger.info("request filter path={}, cost={}, params={}", request.getServletPath(), cost, params); 55 | } 56 | } 57 | 58 | @Override 59 | public void destroy() { 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/service/TinyIdTokenService.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.service; 2 | 3 | /** 4 | * @author du_imba 5 | */ 6 | public interface TinyIdTokenService { 7 | /** 8 | * 是否有权限 9 | * @param bizType 10 | * @param token 11 | * @return 12 | */ 13 | boolean canVisit(String bizType, String token); 14 | } 15 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/service/impl/DbSegmentIdServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.service.impl; 2 | 3 | import com.xiaoju.uemc.tinyid.base.entity.SegmentId; 4 | import com.xiaoju.uemc.tinyid.base.exception.TinyIdSysException; 5 | import com.xiaoju.uemc.tinyid.base.service.SegmentIdService; 6 | import com.xiaoju.uemc.tinyid.server.common.Constants; 7 | import com.xiaoju.uemc.tinyid.server.dao.TinyIdInfoDAO; 8 | import com.xiaoju.uemc.tinyid.server.dao.entity.TinyIdInfo; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Component; 13 | import org.springframework.transaction.annotation.Isolation; 14 | import org.springframework.transaction.annotation.Transactional; 15 | 16 | import java.util.concurrent.atomic.AtomicLong; 17 | 18 | 19 | /** 20 | * @author du_imba 21 | */ 22 | @Component 23 | public class DbSegmentIdServiceImpl implements SegmentIdService { 24 | 25 | private static final Logger logger = LoggerFactory.getLogger(DbSegmentIdServiceImpl.class); 26 | 27 | @Autowired 28 | private TinyIdInfoDAO tinyIdInfoDAO; 29 | 30 | /** 31 | * Transactional标记保证query和update使用的是同一连接 32 | * 事务隔离级别应该为READ_COMMITTED,Spring默认是DEFAULT(取决于底层使用的数据库,mysql的默认隔离级别为REPEATABLE_READ) 33 | *

34 | * 如果是REPEATABLE_READ,那么在本次事务中循环调用tinyIdInfoDAO.queryByBizType(bizType)获取的结果是没有变化的,也就是查询不到别的事务提交的内容 35 | * 所以多次调用tinyIdInfoDAO.updateMaxId也就不会成功 36 | * 37 | * @param bizType 38 | * @return 39 | */ 40 | @Override 41 | @Transactional(isolation = Isolation.READ_COMMITTED) 42 | public SegmentId getNextSegmentId(String bizType) { 43 | // 获取nextTinyId的时候,有可能存在version冲突,需要重试 44 | for (int i = 0; i < Constants.RETRY; i++) { 45 | TinyIdInfo tinyIdInfo = tinyIdInfoDAO.queryByBizType(bizType); 46 | if (tinyIdInfo == null) { 47 | throw new TinyIdSysException("can not find biztype:" + bizType); 48 | } 49 | Long newMaxId = tinyIdInfo.getMaxId() + tinyIdInfo.getStep(); 50 | Long oldMaxId = tinyIdInfo.getMaxId(); 51 | int row = tinyIdInfoDAO.updateMaxId(tinyIdInfo.getId(), newMaxId, oldMaxId, tinyIdInfo.getVersion(), 52 | tinyIdInfo.getBizType()); 53 | if (row == 1) { 54 | tinyIdInfo.setMaxId(newMaxId); 55 | SegmentId segmentId = convert(tinyIdInfo); 56 | logger.info("getNextSegmentId success tinyIdInfo:{} current:{}", tinyIdInfo, segmentId); 57 | return segmentId; 58 | } else { 59 | logger.info("getNextSegmentId conflict tinyIdInfo:{}", tinyIdInfo); 60 | } 61 | } 62 | throw new TinyIdSysException("get next segmentId conflict"); 63 | } 64 | 65 | public SegmentId convert(TinyIdInfo idInfo) { 66 | SegmentId segmentId = new SegmentId(); 67 | segmentId.setCurrentId(new AtomicLong(idInfo.getMaxId() - idInfo.getStep())); 68 | segmentId.setMaxId(idInfo.getMaxId()); 69 | segmentId.setRemainder(idInfo.getRemainder() == null ? 0 : idInfo.getRemainder()); 70 | segmentId.setDelta(idInfo.getDelta() == null ? 1 : idInfo.getDelta()); 71 | // 默认20%加载 72 | segmentId.setLoadingId(segmentId.getCurrentId().get() + idInfo.getStep() * Constants.LOADING_PERCENT / 100); 73 | return segmentId; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/service/impl/TinyIdTokenServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.service.impl; 2 | 3 | import com.xiaoju.uemc.tinyid.server.dao.TinyIdTokenDAO; 4 | import com.xiaoju.uemc.tinyid.server.dao.entity.TinyIdToken; 5 | import com.xiaoju.uemc.tinyid.server.service.TinyIdTokenService; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.scheduling.annotation.Scheduled; 10 | import org.springframework.stereotype.Component; 11 | import org.springframework.util.StringUtils; 12 | 13 | import javax.annotation.PostConstruct; 14 | import java.util.HashMap; 15 | import java.util.HashSet; 16 | import java.util.List; 17 | import java.util.Map; 18 | import java.util.Set; 19 | 20 | /** 21 | * @author du_imba 22 | */ 23 | @Component 24 | public class TinyIdTokenServiceImpl implements TinyIdTokenService { 25 | 26 | @Autowired 27 | private TinyIdTokenDAO tinyIdTokenDAO; 28 | 29 | private static Map> token2bizTypes = new HashMap<>(); 30 | 31 | private static final Logger logger = LoggerFactory.getLogger(TinyIdTokenServiceImpl.class); 32 | 33 | public List queryAll() { 34 | return tinyIdTokenDAO.selectAll(); 35 | } 36 | 37 | /** 38 | * 1分钟刷新一次token 39 | */ 40 | @Scheduled(cron = "0 0/1 * * * ?") 41 | public void refresh() { 42 | logger.info("refresh token begin"); 43 | init(); 44 | } 45 | 46 | @PostConstruct 47 | private synchronized void init() { 48 | logger.info("tinyId token init begin"); 49 | List list = queryAll(); 50 | Map> map = converToMap(list); 51 | token2bizTypes = map; 52 | logger.info("tinyId token init success, token size:{}", list == null ? 0 : list.size()); 53 | } 54 | 55 | @Override 56 | public boolean canVisit(String bizType, String token) { 57 | if (StringUtils.isEmpty(bizType) || StringUtils.isEmpty(token)) { 58 | return false; 59 | } 60 | Set bizTypes = token2bizTypes.get(token); 61 | return (bizTypes != null && bizTypes.contains(bizType)); 62 | } 63 | 64 | public Map> converToMap(List list) { 65 | Map> map = new HashMap<>(64); 66 | if (list != null) { 67 | for (TinyIdToken tinyIdToken : list) { 68 | if (!map.containsKey(tinyIdToken.getToken())) { 69 | map.put(tinyIdToken.getToken(), new HashSet()); 70 | } 71 | map.get(tinyIdToken.getToken()).add(tinyIdToken.getBizType()); 72 | } 73 | } 74 | return map; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/vo/ErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.vo; 2 | 3 | /** 4 | * @author du_imba 5 | */ 6 | public enum ErrorCode { 7 | /** 8 | * token is wrong 9 | */ 10 | TOKEN_ERR(5, "token is error"), 11 | /** 12 | * server internal error 13 | */ 14 | SYS_ERR(6, "sys error"); 15 | 16 | private Integer code; 17 | private String message; 18 | 19 | ErrorCode(Integer code, String message) { 20 | this.code = code; 21 | this.message = message; 22 | } 23 | 24 | public Integer getCode() { 25 | return code; 26 | } 27 | 28 | 29 | public String getMessage() { 30 | return message; 31 | } 32 | 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /tinyid-server/src/main/java/com/xiaoju/uemc/tinyid/server/vo/Response.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server.vo; 2 | 3 | /** 4 | * @author du_imba 5 | */ 6 | public class Response { 7 | private T data; 8 | private Integer code = 200; 9 | private String message = ""; 10 | 11 | public static final int SYS_ERROR = 500; 12 | 13 | public T getData() { 14 | return data; 15 | } 16 | 17 | public void setData(T data) { 18 | this.data = data; 19 | } 20 | 21 | public Integer getCode() { 22 | return code; 23 | } 24 | 25 | public void setCode(Integer code) { 26 | this.code = code; 27 | } 28 | 29 | public String getMessage() { 30 | return message; 31 | } 32 | 33 | public void setMessage(String message) { 34 | this.message = message; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tinyid-server/src/main/resources/offline/application.properties: -------------------------------------------------------------------------------- 1 | server.port=9999 2 | server.context-path=/tinyid 3 | 4 | batch.size.max=100000 5 | 6 | datasource.tinyid.names=primary 7 | #datasource.tinyid.names=primary,secondary 8 | datasource.tinyid.type=org.apache.tomcat.jdbc.pool.DataSource 9 | 10 | datasource.tinyid.primary.driver-class-name=com.mysql.jdbc.Driver 11 | datasource.tinyid.primary.url=jdbc:mysql://localhost:3306/db1?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8 12 | datasource.tinyid.primary.username=root 13 | datasource.tinyid.primary.password=123456 14 | #datasource.tinyid.primary.testOnBorrow=false 15 | #datasource.tinyid.primary.maxActive=10 16 | 17 | #datasource.tinyid.secondary.driver-class-name=com.mysql.jdbc.Driver 18 | #datasource.tinyid.secondary.url=jdbc:mysql://localhost:3306/db2?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8 19 | #datasource.tinyid.secondary.username=root 20 | #datasource.tinyid.secondary.password=123456 21 | #datasource.tinyid.secondary.testOnBorrow=false 22 | #datasource.tinyid.secondary.maxActive=10 23 | 24 | 25 | -------------------------------------------------------------------------------- /tinyid-server/src/main/resources/offline/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ./logs/ 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /tinyid-server/src/main/resources/online/application.properties: -------------------------------------------------------------------------------- 1 | #online 2 | server.port=9999 3 | server.context-path=/tinyid 4 | 5 | batch.size.max=100000 6 | 7 | datasource.tinyid.names=primary 8 | #datasource.tinyid.names=primary,secondary 9 | 10 | datasource.tinyid.primary.driver-class-name=com.mysql.jdbc.Driver 11 | datasource.tinyid.primary.url=jdbc:mysql://localhost:3306/db1?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8 12 | datasource.tinyid.primary.username=root 13 | datasource.tinyid.primary.password=123456 14 | 15 | #datasource.tinyid.secondary.driver-class-name=com.mysql.jdbc.Driver 16 | #datasource.tinyid.secondary.url=jdbc:mysql://localhost:3306/db2?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8 17 | #datasource.tinyid.secondary.username=root 18 | #datasource.tinyid.secondary.password=123456 19 | -------------------------------------------------------------------------------- /tinyid-server/src/main/resources/online/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /home/xiaoju/tinyid-server/logs/ 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /tinyid-server/src/test/java/com/xiaoju/uemc/tinyid/server/ServerTest.java: -------------------------------------------------------------------------------- 1 | package com.xiaoju.uemc.tinyid.server; 2 | 3 | import com.xiaoju.uemc.tinyid.base.generator.IdGenerator; 4 | import com.xiaoju.uemc.tinyid.server.factory.impl.IdGeneratorFactoryServer; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | 11 | /** 12 | * @Author du_imba 13 | */ 14 | @RunWith(SpringRunner.class) 15 | @SpringBootTest 16 | public class ServerTest { 17 | 18 | @Autowired 19 | IdGeneratorFactoryServer idGeneratorFactoryServer; 20 | 21 | @Test 22 | public void testNextId() { 23 | IdGenerator idGenerator = idGeneratorFactoryServer.getIdGenerator("test"); 24 | Long id = idGenerator.nextId(); 25 | System.out.println("current id is: " + id); 26 | } 27 | } 28 | --------------------------------------------------------------------------------