You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ETS中通过AUTO_INCREMENT实现ID自动生成?

ETS结构体存储模块的ID自动生成实现

先修正你代码里的几个问题:

  • :ets.lookup无匹配时返回空列表,用hd/1会触发报错,应该用Enum.empty?/1判断条目是否存在
  • 插入时直接存储元组,和结构体结构不匹配,建议保持结构体格式存入ETS

下面提供两种ID自动生成的实用方案:

方案一:基于OrderedSet特性实现自增ID

因为你使用了:orderedset类型,可以通过:ets.last/1获取当前最大ID,新ID直接取最大ID+1(表为空时初始化为1)。这种方式简单高效,适合单进程写入场景。

修改后的完整代码:

defmodule StructTable do
  defstruct id: 0, data: nil

  def create_table do
    :ets.new(__MODULE__, [:orderedset, :named_table, {:keypos, 1}])
  end

  # 自动生成ID的插入方法
  def insert(data) do
    new_id = case :ets.last(__MODULE__) do
      :undefined -> 1
      last_id -> last_id + 1
    end
    struct = %__MODULE__{id: new_id, data: data}
    :ets.insert(__MODULE__, struct)
    struct # 返回插入的结构体,方便调用者获取生成的ID
  end

  # 修正指定ID插入的判断逻辑
  def insert_into_table(%__MODULE__{id: id} = struct) do
    if Enum.empty?(:ets.lookup(__MODULE__, id)) do
      :ets.insert(__MODULE__, struct)
    else
      IO.puts("ID #{id} already exists")
    end
  end

  def select_data(id) do
    case :ets.lookup(__MODULE__, id) do
      [struct] -> struct
      [] -> nil
    end
  end

  def select_all do
    :ets.tab2list(__MODULE__)
  end
end

方案二:全局唯一ID生成(适合多进程并发写入)

如果是多进程同时写入场景,方案一可能出现竞态条件(两个进程同时获取相同的最大ID,导致ID重复)。这时可以用:erlang.unique_integer/1生成全局唯一ID:

def insert(data) do
  # 生成递增的正整数唯一ID
  new_id = :erlang.unique_integer([:positive, :monotonic])
  struct = %__MODULE__{id: new_id, data: data}
  :ets.insert(__MODULE__, struct)
  struct
end

:monotonic保证ID递增,:positive确保ID为正整数,这种方式无需额外进程,适配高并发场景。

选型建议

  • 需要连续自增ID:选方案一
  • 高并发场景,允许ID不连续但全局唯一:选方案二

内容的提问来源于stack exchange,提问作者Sana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 12:55:14