Elixir技术问询:10万联系人列表按100条分块出现重复如何解决
高效拆分十万条Contact列表为每批100条的解决方案
先解决分块重复的问题
你提到用Enum.chunk(phonebook_contacts,100,100,[])出现重复元素,其实这个函数的参数逻辑是对的,但更推荐用语义更清晰的Enum.chunk_every/2——它就是专门用来做无重叠分块的,用法简单还不容易出错:
# 每100条分一块,最后不足100条的保留 Enum.chunk_every(phonebook_contacts, 100)
如果用这个还是出现重复元素,那大概率是你的phonebook_contacts列表本身就包含重复的Contact,建议先排查原列表的生成逻辑,或者用Enum.uniq(phonebook_contacts)先去重。
针对十万条数据的效率优化
十万条数据量不算小,结合你后面的Task处理,给你几个优化点:
- 避免无效重复判断:如果
Telephony.user_balance_account_number(account_number)这个余额判断是全局的(不是每个Contact都要单独判断),把它提到最外层,减少重复调用:unless Telephony.user_balance_account_number(account_number) <= 0 do phonebook_contacts |> Enum.chunk_every(100) |> Enum.each(fn chunk -> Enum.each(chunk, fn contact -> Task.start_link(fn -> # 执行你的后台任务逻辑 end) end) end) end - 控制并发数,避免系统过载:直接给十万条数据启动十万个Task很容易耗尽系统资源,推荐用
Flow来做可控的并发处理,它会自动平衡并发量:unless Telephony.user_balance_account_number(account_number) <= 0 do phonebook_contacts |> Flow.from_enumerable(max_demand: 100) # 控制每次处理的批量大小 |> Flow.each(fn contact -> # 执行你的后台任务逻辑 end) |> Flow.run() end - 如果不需要保留分块结构:其实如果只是要批量处理,甚至可以不用显式分块,直接用
Flow或者Task.Supervisor来控制并发,代码会更简洁。
为什么原来的Enum.chunk可能出现“重复”?
Enum.chunk(list, 100, 100, [])的逻辑是:每次取100条,然后跳过100条(因为step=100),最后不足100条的部分会被丢弃(因为最后一个参数是[])。理论上不会出现重叠重复,除非你的原列表本身有重复元素,或者在分块前的逻辑里不小心复制了元素。用Enum.chunk_every可以避免参数写错的问题,比如如果不小心把step设成了小于chunk_size的数值,才会出现重叠分块。
内容的提问来源于stack exchange,提问作者devie
相关产品推荐
相关产品推荐

