全局主键生成器
介绍:
相对于DB自增序列的全局主键生成器,性能更高,同时保留业务需求的业务含义,
对于有分库分表需求的业务同时可以存储分库和分表的信息,对于高并发的互联网企业分库分表生成主键来说是一种很好的方法
1. package
2.
3. import
4. import
5. import
6.
7. public class
8.
9. public static void main(String[] args) throws
10.
11. /**
12. * 项目:交易单分表
13. *
14. * 需求
15. * 查询需求: 1. userId维度
16. * 2. 产品维度
17. * 3. 商户维度
18. * 4. 时间区间维度
19. *
20. * 预计订单量:
21. * 一单平均10000, 一年交易额5000亿, 需要成功订单量 = 500000000000 / 10000 = 50000000 5000万订单
22. * 购买加回款应该是1亿订单量, 所以, 单表2000万, 一年需要5张表
23. *
24. * 最后扩展64库 + 64表, 共64*64 = 4096表, 4096 * 2000万 = 819亿订单够用了, 819亿 * 10000 = 8190000亿 819万亿,够用了
25. *
26. * 全局唯一主键:
27. * 15位时间戳 + 自增序号四位 + 机器后两段IP,6位 + 备用1位 + 分库信息两位 + 分表信息两位 共30位, 回款改造前
28. * 15位时间戳 + 自增序号四位 + 机器后两段IP,6位 + 备用3位 + 分库信息两位 + 分表信息两位 共32位, 回款改造后
29. *
30. * 单JVM支持最多1s 1000 * 9999 = 9999000, 999万9千笔订单,后续还可以扩展。
31. *
32. * 分库规则:
33. * 寻找到数据库 (userId/100) % 64 + 1 找到数据库 订单最多64个库 目前一个库 二分法裂变扩容
34. * 分表规则:
35. * 寻找到表信息 userId % 64 + 1 找到表信息 一个库最多64个表 目前分8张表 以后二分法裂变扩容
36. *
37. * 迁移规则:
38. * 迁移方案同步写, 目前用动态表名, 以后分表中间件稳定后, 迁移过去
39. *
40. * 查询改造:
41. * 原接口不变,对用户无感知, 底层钩子遍历
42. */
43.
44. // 只获取本地局域网IP即可
45. String ip = InetAddress.getLocalHost().getHostAddress();
46. "\\.");
47.
48. final String lastTwoPhaseIp = StringUtils.rightPad(ipArray[2], 3, '0')
49. 3], 3, '0');
50.
51. for (int i = 0; i < 100000; i++) {
52. new Thread(new
53.
54. @Override
55. public void
56. // TSS commons工具类
57. String tss = TSS.getTimeStampSequence();
58. "000" + "01" + "08";
59. System.out.println(id);
60. }
61. }).start();
62. }
63. }
64.
65. }
1. package
2.
3. import
4.
5. import
6. import
7. import
8. import
9. import
10. import
11. import
12. import
13. import
14.
15. /**
16. * 时间戳序列器<br>
17. *
18. * 支持同一毫秒最多生成9999笔序列号<br>
19. * @author sanfeng
20. *
21. * 想象力就是生产力
22. */
23. public class
24.
25. // 默认1个大小
26. private static
27. new HashMap<String, AtomicInteger>(1);
28.
29. private static final ReentrantLock lock = new
30.
31. // 因为有锁,所以是变成了线程安全的,省去每次 new 的消耗,耗时降低约一半
32. private static final SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmssSSS");
33.
34. public static
35.
36. null;
37. null;
38.
39. lock.lock();
40. try
41.
42. new
43. AtomicInteger value = tssCache.get(timestamp);
44. if(value == null) {
45. tssCache.clear();
46. int defaultStartValue = 0;
47. new
48. inc = String.valueOf(defaultStartValue);
49. else
50. 1));
51. }
52. finally
53. lock.unlock();
54. }
55.
56. return timestamp + StringUtils.leftPad(inc, 4, '0');
57. }
58.
59.
60. public static void main(String[] args) throws
61.
62. // for (int i = 0; i < 1000; i++) {
63. // new Thread(new Runnable() {
64. //
65. // @Override
66. // public void run() {
67. // for (int j = 0; j < 10; j++) {
68. // System.out.println(TSS.getTimeStampSequence());
69. // }
70. // }
71. // }).start();
72. // }
73.
74.
75. // 统计重复
76. new
77. new
78. new InputStreamReader(new FileInputStream("C:/Users/Administrator/Desktop/1.txt")));
79. String str = br.readLine();
80. while(str != null) {
81. if(set.contains(str)) {
82. System.out.println(str);
83. else
84. set.add(str);
85. }
86. str = br.readLine();
87. }
88.
89. br.close();
90.
91. }
92. }