2021-10-21

2021-10-21,第1张

2021-10-21

分布式系统中,有一些需要使用全局唯一ID的场景,有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成,这时候通常我们会选择使用雪花算法

 

1

2

 

snowflake的结构如下(每部分用-分开):

0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000

第一位为未使用,接下来的41位为毫秒级时间(41位的长度可以使用69年) 然后是5位datacenterId和5位workerId(10位的长度最多支持部署1024个节点) 最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)。

一般创建雪花算法的时候,依赖:

 

1

2

3

 

Params:

workerId – 终端ID

datacenterId – 数据中心ID

两个参数,这两个值的取值都为 0~31 之间的整型。

提供了一个基于Redis的实现方式:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

 

import java.io.Serializable;

import java.util.linkedHashMap;

import java.util.Map;

import lombok.AllArgsConstructor;

import lombok.Builder;

import lombok.Data;

import lombok.NoArgsConstructor;

import org.apache.commons.lang3.StringUtils;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.data.redis.support.atomic.RedisAtomicLong;

public class SnowflakeInitiator {

@Data

@Builder

@NoArgsConstructor

@AllArgsConstructor

public static class SnowIdDto implements Serializable, Comparable {

private Long timestamp;

private Integer dataCenterId;

private Integer workerId;

@Override

public int compareTo(SnowIdDto o) {

long ex = this.timestamp - o.getTimestamp();

return ex > 0 ? 1 : -1;

}

}

private static final Integer DATA_SIZE = 32;

private static final String[] RADIX_STR = new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v"};

private static Map RADIX_MAP = new linkedHashMap<>();

private static final String SNOW = "RedisPrefix";

static {

for (int i = 0; i < DATA_SIZE; i++) {

RADIX_MAP.put(RADIX_STR[i], i);

}

}

private SnowIdDto calculateDataIdAndWorkId(RedisTemplate redisTemplate, String appName) {

String key = SNOW + appName;

RedisAtomicLong redisAtomicLong = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());

long andIncrement = redisAtomicLong.getAndIncrement();

long result = andIncrement % (DATA_SIZE * DATA_SIZE);

String str = StringUtils.leftPad(Integer.toString(Math.toIntExact(result), DATA_SIZE), 2, "0");

Integer dataId = RADIX_MAP.get(str.substring(0, 1));

Integer workId = RADIX_MAP.get(str.substring(1, 2));

return new SnowIdDto(System.currentTimeMillis(), dataId, workId);

}

}

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/4670294.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-11-06
下一篇2022-11-06

发表评论

登录后才能评论

评论列表(0条)

    保存