跳转到主要内容

snowflake

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

概览

扩展包名版本分类许可证语言
snowflake2.6.0FUNCPostgreSQLC
ID扩展名BinLibLoadCreateTrustReloc模式
4590snowflake否是否是否否snowflake

Bundled with pgEdge 15.19/16.15/17.11/18.6; set snowflake.node.

版本

类型仓库版本PG 大版本包名依赖
EXTPIGSTY2.6.01817161514snowflake-
RPMPIGSTY18.61817161514pgedge-$v-
DEBPIGSTY18.61817161514pgedge-$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 扩展包的预置二进制包,首先确保 PGDG 和 PIGSTY 仓库已经添加并启用:

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

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

安装
pig install snowflake;          # 当前活跃 PG 版本安装
pig
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
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
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)返回自 1970-01-01 起的 Unix 纪元秒数,精度为毫秒
snowflake.get_count(snowflake int8)提取计数值部分(每毫秒重置)
snowflake.get_node(snowflake int8)提取节点标识符
snowflake.format(snowflake int8)返回 JSONB 字段 id(节点标识符)、ts 和 count

示例

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

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

-- Decode a fixed example: node 1, count 0
SET TIME ZONE 'UTC';
SELECT snowflake.get_epoch(136169504773246976);
-- 1704996539.845

SELECT to_timestamp(snowflake.get_epoch(136169504773246976));
-- 2024-01-11 18:08:59.845+00

SELECT snowflake.get_node(136169504773246976);
-- 1

SELECT snowflake.get_count(136169504773246976);
-- 0

SELECT snowflake.format(136169504773246976);
-- {"id": 1, "ts": "2024-01-11 18:08:59.845+00", "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。
  • 保持节点标识符在整个并发写入的生命周期内稳定且唯一;将其作为集群规划和故障转移流程的一部分进行记录。
  • 在逻辑复制或涉及转换后序列定义的滚动更改之前,在每个节点上安装相同的扩展版本。

2.6.0 新增 PostgreSQL 19 支持;当前 Pigsty pgEdge 组合包覆盖 PostgreSQL 15–18。snowflake.node 必须位于 1–1023,默认值有意设为无效。控制文件固定使用 snowflake 模式,无需共享预加载。从更早版本升级已经转换过的序列时,仍须关注 2.5.0 的导出与恢复修复。

应由管理员安装 C 扩展并转换 identity 定义。生成 ID 需要目标序列的 USAGE 或 UPDATE 权限;只有同一会话中该序列已经生成过 ID 后,当前值才有定义。

这个页面对您有帮助吗?