8

分享一个 id 自增生成器,依赖于 redis,求大佬帮忙挑挑毛病

 3 years ago
source link: https://www.v2ex.com/t/802473
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

V2EX  ›  程序员

分享一个 id 自增生成器,依赖于 redis,求大佬帮忙挑挑毛病

  flycloud · 1 小时 2 分钟前 · 425 次点击

看了雪花算法,服务需要配置标识位(数据中心 ID 、机器 ID ),多一项配置就多一份出错的风险,同时在不依赖其他基础服务的情况下也不太好解决时间回调的问题。然后自己实现了一个简化版的,依赖于 redis 。大佬们帮忙看看有啥问题没有,感谢。

func GlobalIncrId() (int64, error) {
	script := redis.NewScript(`
		local key = KEYS[1]
		local stamp = ARGV[1]
		
		local newValue = redis.call("incr", key)
		if newValue then
			if newValue > tonumber(stamp) then
				return newValue
			else
				local flag = redis.call("set", key, stamp)
				if flag then
					return stamp
				end
			end
		end
	
		return nil
	`)
	stamp := (time.Now().Unix() - 50 * 365 * 86400) << 22
	ret, err := script.Run(RedisIns, []string{sredis.KEY_GLOBAL_INCR_ID}, stamp).Int64()
	return ret, err
}

自增 id 带上 stamp 信息, 是为了防止 redis 的 key 丢失, 或者值被清除。stamp 的计算回拨了 50 年, 因为 32bit 的时间戳到 2038 年就溢出了。只要机器的系统时间回调以及 key 失效这两件事不同时发生, 就能保持自增性。

低 22 位用于 redis incr 自增,高位是时间信息,即 1s 内最多支持 4194304 个 id,超出了也没关系,只是会提前占用高位的时间。

用 22 位来自增是因为某些业务可能会将 id 用在 zadd 中,zadd 的 score 范围是:-(2^53) 至 +(2^53), 即时间信息可以占用 31 位, 保证 score 不会溢出。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK