snowflake

Snowflake 风格 64 位 ID 生成与序列工具

概览

扩展包名版本分类许可证语言
snowflake2.5.0FUNCPostgreSQLC
ID扩展名BinLibLoadCreateTrustReloc模式
4590snowflakesnowflake
相关扩展spock lolor

works on pgedge kernel fork. Set snowflake.node (1..1023) before using snowflake.nextval().

版本

类型仓库版本PG 大版本包名依赖
EXTPIGSTY2.5.01817161514snowflake-
RPMPIGSTY18.41817161514pgedge-$v-
DEBPIGSTY18.41817161514pgedge-$v-
OS / PGPG18PG17PG16PG15PG14
el8.x86_64N/A
el8.aarch64N/A
el9.x86_64N/A
el9.aarch64N/A
el10.x86_64N/A
el10.aarch64N/A
d12.x86_64N/A
d12.aarch64N/A
d13.x86_64N/A
d13.aarch64N/A
u22.x86_64N/A
u22.aarch64N/A
u24.x86_64N/A
u24.aarch64N/A
u26.x86_64N/A
u26.aarch64N/A

构建

您可以使用 pig build 命令构建 snowflake 扩展的 RPM / DEB 包:

pig build pkg snowflake         # 构建 RPM / DEB 包

安装

您可以直接安装 snowflake 扩展包的预置二进制包,首先确保 PGDGPIGSTY 仓库已经添加并启用:

pig repo add pgsql -u          # 添加仓库并更新缓存

使用 pig 或者是 apt/yum/dnf 安装扩展:

pig install snowflake;          # 当前活跃 PG 版本安装
pig ext install -y snowflake -v 18  # PG 18
pig ext install -y snowflake -v 17  # PG 17
pig ext install -y snowflake -v 16  # PG 16
pig ext install -y snowflake -v 15  # PG 15
dnf install -y pgedge-18       # PG 18
dnf install -y pgedge-17       # PG 17
dnf install -y pgedge-16       # PG 16
dnf install -y pgedge-15       # PG 15
apt install -y pgedge-18   # PG 18
apt install -y pgedge-17   # PG 17
apt install -y pgedge-16   # PG 16
apt install -y pgedge-15   # PG 15

创建扩展

CREATE EXTENSION snowflake;

用法

来源:

snowflake 生成分布式 bigint 标识符,从时间戳、节点标识符和毫秒计数器中产生。现有的 PostgreSQL 序列可以被转换,使得表的默认值继续使用 nextval(...) 同时生产 Snowflake ID。

CREATE EXTENSION snowflake;

配置

postgresql.conf 中为每个可写的节点分配一个唯一的标识符,然后重新加载 PostgreSQL:

snowflake.node = 1

在同一时间可以写入的服务器上重复使用节点标识符可能会生成重复的 ID。

转换一个序列

创建一个普通的 PostgreSQL 序列,然后转换其定义。引用列中的现有值不会被重写。

CREATE TABLE orders (
  id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  payload jsonb NOT NULL
);

SELECT snowflake.convert_sequence_to_snowflake(
  pg_get_serial_sequence('orders', 'id')::regclass
);

INSERT INTO orders (payload) VALUES ('{"status":"new"}');
SELECT id, snowflake.format(id) FROM orders;

函数

函数描述
snowflake.nextval([sequence regclass])生成下一个 Snowflake ID(如果没有指定序列,则使用内部序列)
snowflake.currval([sequence regclass])返回序列的当前值
snowflake.get_epoch(snowflake int8)提取时间戳为纪元(自2023-01-01以来的秒数)
snowflake.get_count(snowflake int8)提取计数值部分(每毫秒重置)
snowflake.get_node(snowflake int8)提取节点标识符
snowflake.format(snowflake int8)返回包含 nodetscount 字段的 JSONB

示例

-- Generate a snowflake ID
SELECT snowflake.nextval();
-- 136169504773242881

-- Use an already converted named sequence
SELECT snowflake.nextval('orders_id_seq'::regclass);

-- Extract components
SELECT snowflake.get_epoch(136169504773242881);
-- 1704996539.845

SELECT to_timestamp(snowflake.get_epoch(136169504773242881));
-- 2024-01-11 13:08:59.845-05

SELECT snowflake.get_node(136169504773242881);
-- 1

SELECT snowflake.format(136169504773242881);
-- {"id": 1, "ts": "2024-01-11 13:08:59.845-05", "count": 0}

-- Use as default column
CREATE TABLE direct_ids (
  id int8 DEFAULT snowflake.nextval() PRIMARY KEY,
  data text
);

审查与升级

使用 psql \d+ 或 PostgreSQL 系统目录审查转换后的表默认值。它们应该调用 snowflake.nextval(...) 而不是原来的 nextval(...)

SELECT table_schema, table_name, column_name, column_default
FROM information_schema.columns
WHERE column_default LIKE 'snowflake.nextval(%';

版本 2.5.0 修复了导出/恢复被转换序列的 MAXVALUE 设置为正常 bigint 最大值的问题。它还修复了受影响序列的转换 SQL 并增加了对 PostgreSQL 18 的支持。

注意事项

  • 转换会改变序列定义,而不是已经存储在表行中的 ID。
  • Snowflake 生成器每毫秒最多可以发出 4096 个计数值。不要将序列增量配置为超过 4096。
  • 保持节点标识符在整个并发写入的生命周期内稳定且唯一;将其作为集群规划和故障转移流程的一部分进行记录。
  • 在逻辑复制或涉及转换后序列定义的滚动更改之前,在每个节点上安装相同的扩展版本。