服务器系列
文章目录
- 服务器系列
- 前言
- 一、雪花算法
- 二、C++的代码示例
- 总结
前言
在分布式系统中,经常涉及到时间同步问题,这样由于时间校准,以及其他因素,可能导致服务器时间回退,如果恰巧回退前生成过一些id,而时间回退后,生成的id就有可能重复。现有
技术中对于此问题并没有给出明确的解决方案,而是简单的抛错处理,这样会造成在时间
被追回之前的这段时间服务不可用,导致交易失败,用户体验极其不好。
一、雪花算法
雪花算法是一种用于生成唯一ID的算法,它的核心思想是将时间戳、机器ID和序列号组合起来生成一个唯一的ID。具体实现过程如下:
获取当前时间戳,精确到毫秒级别。
将时间戳转换成二进制,并左移22位,腾出前22位用于存储机器ID。
获取机器ID,可以是MAC地址、IP地址或者自定义的ID。
将机器ID转换成二进制,并左移12位,腾出中间的12位用于存储序列号。
生成序列号,可以是自增的数字或者随机数。
将时间戳、机器ID和序列号进行位运算或者相加,生成一个64位的唯一ID。
二、C++的代码示例
#include <iostream>
#include <chrono>
#include <thread>class Snowflake {
public:Snowflake(uint16_t worker_id) : worker_id_(worker_id), sequence_(0) {}uint64_t next_id() {uint64_t timestamp = get_timestamp();uint64_t id = ((timestamp - epoch_) << timestamp_left_shift_) |(worker_id_ << worker_id_left_shift_) |(sequence_++ & sequence_mask_);if (sequence_ > sequence_mask_) {std::this_thread::sleep_for(std::chrono::milliseconds(1));sequence_ = 0;}return id;}private:uint64_t get_timestamp() {return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();}const uint64_t epoch_ = 1609459200000; // 2021-01-01 00:00:00const uint64_t worker_id_left_shift_ = 12;const uint64_t timestamp_left_shift_ = 22;const uint64_t sequence_mask_ = 0xFFF;uint16_t worker_id_;uint64_t sequence_;
};int main() {Snowflake snowflake(1);for (int i = 0; i < 10; i++) {std::cout << snowflake.next_id() << std::endl;}return 0;
}
总结
以上代码中,Snowflake类表示雪花算法,next_id()函数用于生成唯一ID。在构造函数中传入worker_id,表示机器ID。get_timestamp()函数用于获取当前时间戳,精确到毫秒级别。在next_id()函数中,根据时间戳、机器ID和序列号生成唯一ID,并将序列号自增,如果序列号超过了最大值,则等待1毫秒后重置序列号。最后输出生成的唯一ID。