如何在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
相关产品推荐
相关产品推荐

