常见问题
需要部署 CosId 服务端吗?
不需要。CosId 是一个库:ID 在你的应用内部生成,计数器和租约保存在你已经在运行的存储中(Redis、数据库、MongoDB 或 ZooKeeper)。独立的 ID 服务会让每个 ID 都多一次网络调用,而这正是 CosId 要避免的。CosId Proxy 是可选的;它在应用不能直接访问存储时代替存储,ID 仍然在本地生成。
ID 是有序的吗?
单个实例内是递增的。跨实例是趋势递增:某个实例的号段 ID 可能比另一个实例更早发放的 ID 还小,差距最多约为 step × 每个实例持有的号段数(当前号段加预取的号段:至少 safe-distance 个,负载高时更多)× 实例数;Snowflake ID 的有序程度取决于各主机时钟的一致程度。不经过单点协调,任何分布式生成器都无法做到严格的全局有序;如有需要请使用数据库序列。
为什么会有空洞?
号段生成器在重启或号段过期时会跳过剩余号段,号段链也可能预取到最终没有用到的号段。Snowflake ID 中没有请求使用的序列号也会空出。空洞是正常的;不要用 ID 来统计行数。
PrefetchWorker 如何维护安全距离?
- 定时维护:每隔
prefetch-period(1 秒)检查号段链,补足到safe-distance个号段。 - 饥饿唤醒:发现没有可用号段的线程会自己获取一个,并唤醒预取任务;预取任务把预取距离翻倍(最多
max-prefetch-distance),在一次存储调用中申请这么多号段。需求下降后距离再减半。
既然趋势递增就够了,为什么还要尽量接近单调递增?
趋势递增是一种权衡:窗口内的乱序是不必为每个 ID 做协调的代价。窗口越小,插入越集中在索引末尾,所以 CosId 尽量缩小窗口(小步长,用预取代替大号段)。
两个应用可以共用一个存储吗?
可以。为每个应用设置各自的 cosid.namespace:计数器和机器号按命名空间隔离。
存储不可用时会怎样?
生成会继续使用内存中的 ID:号段链使用预留的号段,Snowflake 生成器只在启动和续约时需要存储。在最后一次成功续约之后约 4 分 50 秒(safe-guard-duration - min(10s, safe-guard-duration / 10)),Snowflake 生成器和 CosIdGenerator 会抛出 MachineIdLostException 停止生成,而不是冒险生成重复 ID。存储不可用期间,新实例无法启动。
还有其他问题,请到 Issues 提问。
