我能用LCG,也就是线性同余生成器,给我的员工一个9位的,唯一的,但不重复的工作ID吗。
算法应使用BSD rand()
公式,初始种子(状态0)为11111111,但将mod 2^31
更改为mod 999,999,937
:
但我是否必须总是从上次添加的人员中检索work ID
来计算下一个?
请帮忙!
最佳答案
我能用LCG,也就是线性同余生成器,给我的员工一个9位的,唯一的,但不重复的工作ID吗。
这取决于你如何使用它。
如果您想为每个请求生成一个工作ID,那么不行,因为
lcg不适合并行编程。多个线程可能同时访问当前存储的状态,从而导致争用情况。在对不同线程使用相同初始化的实现中,在同时执行的线程上可能出现相等的随机数序列。不应信任随机数生成器,特别是并行计算机的随机数生成器。
(见Wikipedia)
但您可以预先生成一组工作ID,对于每个员工,只需将第一个未使用的ID分配给他/她。
例如,您可以使用db/seed.rb
预生成工作id(假设您有AR模型WorkId
)
分贝/种子.rb
total_work_ids = 10_000 # based on how many potential employees
state = 111_111_111 # the seed
total_work_ids.times do
state = (1_103_515_245 * state + 12345) % 999_999_937
WorkId.create(value: '%09d' % state)
end
更新
使用数据库存储工作ID仍然可能有竞争条件,因为每次获取新的工作ID时,都需要一个查询(
SELECT id, value FROM work_ids WHERE used = 0 LIMIT 1
)和一个更新(UPDATE work_ids SET used = 1 WHERE id = ?
),这不是原子的。我认为最好的解决方案是在Rails应用程序之外实现一个外部服务,它以先进先出的方式提供工作id。这个服务应该很快,因为它被所有的Rails线程/进程访问并阻塞它们。
我认为redis set是存储那些未使用的工作id的好地方,因为它确保了其中元素的唯一性,而且它的
spop
是原子的。关于ruby-on-rails - 用于在Ruby on Rails中为Postgresql提供唯一,不重复的随机数的Linear Congruent Generator?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36108955/