springboot~多节点应用里的雪花算法唯一性

雪花算法的唯一性,在单个节点中是可以保证的,对应kubernetes中的应用,如果是横向扩展后,进行多副本的情况下,可能出现重复的ID,这需要我们按着pod_name进行一个workId的生成,我还是建议通过不引入第三方组件和网络请求的前提下解决这个问题,所以我修改了kubernetes的yaml文件。

  • k8s的yaml配置
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: my-image:latest
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name  # 获取当前 Pod 的名称

  • 字符串(0~1024)数字方法,通过掩码的方式
public static int stringToNumber(String input) {
        // 使用CRC32计算字符串的哈希值
        CRC32 crc = new CRC32();
        byte[] bytes = input.getBytes(StandardCharsets.UTF_8);
        crc.update(bytes);
        
        // 获取哈希值并限制在0到1023之间
        long hashValue = crc.getValue();
        return (int) (hashValue % 1024);
    }
  • 获取服务器机器码
/**
	 * 获取机器码.
	 * @return
	 */
	public static String getUniqueMachineId() {
		StringBuilder uniqueId = new StringBuilder();

		try {
			// 获取本机的IP地址
			InetAddress localHost = InetAddress.getLocalHost();
			uniqueId.append(localHost.getHostAddress()).append("_");

			// 获取网络接口并获取MAC地址
			Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
			while (networkInterfaces.hasMoreElements()) {
				NetworkInterface networkInterface = networkInterfaces.nextElement();
				byte[] mac = networkInterface.getHardwareAddress();
				if (mac != null) {
					for (int i = 0; i < mac.length; i++) {
						uniqueId.append(String.format("%02X", mac[i]));
						if (i < mac.length - 1) {
							uniqueId.append("-");
						}
					}
					uniqueId.append("_");
				}
			}

			// 添加系统信息作为补充
			String osName = System.getProperty("os.name");
			String osVersion = System.getProperty("os.version");
			String userName = System.getProperty("user.name");
			uniqueId.append(osName).append("_").append(osVersion).append("_").append(userName);

		}
		catch (Exception e) {
			e.printStackTrace();
		}

		return uniqueId.toString();
	}
  • ID生成器的改进
@Slf4j
public class IdUtils {

	static SnowFlakeGenerator snowFlakeGenerator;

	public static String generateId() {
		if (snowFlakeGenerator == null) {
			long podNameCode = stringToNumber(Optional.ofNullable(System.getenv("POD_NAME")).orElse(stringToNumber(getUniqueMachineId())));
			log.debug("podNameCode:{}", podNameCode);
			snowFlakeGenerator = new SnowFlakeGenerator(podNameCode);

		}
		return snowFlakeGenerator.hexNextId();
	}
posted @ 2024-12-30 15:31  张占岭  阅读(412)  评论(0编辑  收藏  举报