sfid 0.1.1

Distributed Snowflake ID generator with Redis-based auto machine ID allocation / 基于 Redis 自动分配机器号的分布式雪花 ID 生成器
Documentation
# sfid 设计文档

基于 Redis 自动分配机器号的雪花 ID 生成器。

## 架构

```
┌─────────────────────────────────────────────────────────────┐
│                        sfid                                  │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────────┐  │
│  │  Snowflake  │───▶│  machine_id │───▶│  MACHINE_ID     │  │
│  │  Generator  │    │  ()         │    │  (xboot::auto)│  │
│  └─────────────┘    └─────────────┘    └────────┬────────┘  │
│                                                  │           │
│                                                  ▼           │
│                                        ┌─────────────────┐  │
│                                        │  Redis HEXPIRE  │  │
│                                        │  (机器号分配)    │  │
│                                        └─────────────────┘  │
└─────────────────────────────────────────────────────────────┘
```

## 雪花 ID 结构 (64 bits)

```
┌───────┬──────────────────────────┬────────────┬──────────────┐
│ 1 bit │        41 bits           │  10 bits   │   12 bits    │
│ 符号  │        时间戳(ms)         │  机器号    │   序列号     │
│ (0)   │  (相对 2020-01-01 偏移)   │  (0-1023)  │   (0-4095)   │
└───────┴──────────────────────────┴────────────┴──────────────┘
```

- 时间戳: 41 bits,可用约 69 年 (2020-2089)
- 机器号: 10 bits,最多 1024 台机器
- 序列号: 12 bits,每毫秒最多 4096 个 ID

## 机器号分配

### Redis 存储结构

使用 Redis Hash 存储机器号分配:

```
Key: sfid
Field: 机器号 (0-1023)
Value: 机器唯一标识 (machine-uid 或 uuid)
TTL: 1 小时 (使用 HEXPIRE,Redis 7.4+)
```

### 分配流程

```
┌─────────────┐
│   启动      │
└──────┬──────┘
┌─────────────────────┐
│ 生成随机起始点 start │
└──────┬──────────────┘
┌─────────────────────┐
│ id = (start + i) %  │◀──────┐
│      1024           │       │
└──────┬──────────────┘       │
       ▼                      │
┌─────────────────────┐       │
│ HSETNX sfid id      │       │
│ local_id            │       │
└──────┬──────────────┘       │
       ▼                      │
   ┌───────┐                  │
   │成功?  │──否──▶ 检查是否  │
   └───┬───┘       已拥有 ────┘
       │是                │是
       ▼                  ▼
┌─────────────────────────────┐
│ HEXPIRE sfid 3600 FIELDS    │
│ 1 id                        │
└──────┬──────────────────────┘
┌─────────────────────┐
│ 启动心跳任务        │
│ (每 15 分钟续期)    │
└─────────────────────┘
```

### 心跳机制

- 间隔: 15 分钟
- 过期: 1 小时
- 操作: HSET + HEXPIRE 刷新

超过 1 小时无心跳,机器号自动释放,可被其他实例认领。

## 时钟回拨处理

使用 `coarsetime` 获取时间,减少系统调用开销。

### 回拨策略

```
┌─────────────────────┐
│ 获取当前时间 ts     │
└──────┬──────────────┘
   ┌───────────┐
   │ ts < last │
   └─────┬─────┘
         │是
   ┌───────────────┐
   │ diff > 100ms? │
   └───────┬───────┘
       是  │  否
       ▼   ▼
   ┌─────┐ ┌──────────────┐
   │错误 │ │ sleep(diff)  │
   └─────┘ │ 等待追上     │
           └──────────────┘
```

- 小幅回拨 (≤100ms): 等待时间追上
- 大幅回拨 (>100ms): 返回错误,拒绝生成

## 并发安全

### Snowflake Generator

- `last_ts`: AtomicI64,CAS 更新
- `sequence`: AtomicU16,原子递增
- 无锁设计,高并发性能

### 序列号溢出

同一毫秒内序列号用尽 (>4095) 时,自旋等待下一毫秒。

## 依赖

| Crate | 用途 |
|-------|------|
| coarsetime | 高性能时间获取 |
| fred | Redis 客户端 |
| machine-uid | 机器唯一标识 |
| static_ | 异步静态初始化 |
| xkv | Redis 连接池 |

## 使用示例

```rust
use sfid::{Snowflake, MACHINE_ID};

static SF: Snowflake = Snowflake::new();

#[tokio::main]
async fn main() -> Result<()> {
  // 初始化机器号
  xboot::auto().await?;
  
  println!("machine_id: {}", **MACHINE_ID);
  
  // 生成 ID
  let id = SF.next()?;
  println!("id: {id}");
  
  Ok(())
}
```