UDF 上下文中的 UDF 写入生成检查

问题描述 投票:0回答:1

我有 Aerospike 的用例,其中有多个记录,例如:

+--------+---------+
| PK     | signal  |
+--------+---------+
| 123451 | 1       |
| 102221 | 1.0816  |
+--------+---------+

我的服务 A 在约 1000 Vms 的 VM 队列上运行,每 3 分钟读取一次此信号值。 现在,该信号值还需要根据服务 A 范围内的其他现实世界值 (x...y) 每 3 分钟更新一次。它可以每 3 分钟上升或下降,也可以每 24 小时重置一次。 此外,所有 1000 个虚拟机都需要同时看到相同的更新信号值。

现在理想的方法可能是运行一个单独的服务(服务 B),每 3 分钟更新一次此信号。但动态值很难在任何其他服务中重新创建,并且不容易导出。

因此,要在服务 A 中执行此操作,我可以在每个虚拟机上遵循 CAS(检查和设置)模式 我有一个调度程序每 3 分钟间隔执行一次同步到纪元的操作:

  1. 阅读信号
  2. 计算更新信号
  3. 写回新的计算信号

现在这是低效的,因为在最好的情况下,所有 1000 个服务 A 虚拟机都将向 aerospike 写回相同的值,范围到我可能遇到的最坏情况

  1. 由于 1000 个并发写入而导致写入争用(密钥繁忙)
  2. 由于不同上下文中 X 和 Y 的不同动态值的边缘情况,会写回不同的信号。

考虑使用写入策略生成来实现此目的:

  1. 我读取所有密钥,保留所有密钥的生成
  2. 计算所有新密钥。
  3. 写回所有新密钥,并对写入策略进行匹配生成检查
  4. 返回最终更新的密钥(需要吗?)

看起来很笨拙,所以尝试了这样的UDF:

function updateSignal(rec, binName, someParamX, someParamY, hyperParameter, resetFlag)
    if aerospike:exists(rec) then
      local currentSignal = rec[binName]
      local geneneration = record.gen(rec)
      if (someParamX > someParamY) then
        local multiplier = someFunction()
        local updatedSignal = currentSignal * multiplier
        rec[binName] = updatedSignal
      else
        rec[binName] = 1
      end  
      aerospike:update(rec)
    else
      aerospike:create(rec)
      rec[binName] = 1
      aerospike:update(rec)
    end
    return rec[binName]  -- Return the updated value
end

问题是,在 UDF 上下文中,如果我不最初将 write gen 传递给 UDF,我实际上没有任何 write gen 检查能力。

此外,如果我将写入生成作为 UDF 调用的一部分传递,如果写入由于生成检查(冲突)而失败,我还需要返回信号的当前值。 因为如果记录是从其他地方更新的,那么一旦在 udf 上下文中我就不会收到更新的信号。 (这会发生吗?读某处udfs锁定记录?是读锁/写锁吗?)

有什么办法解决这个问题吗?我是不是错过了什么?

lua user-defined-functions aerospike aerospike-ce
1个回答
0
投票

记录 UDF 将在持有记录锁的同时完全运行。因此,在读取然后更新记录的 UDF 内,您不能让另一个 VM 更改记录。希望这会有所帮助(我可能错过了您特定用例的一些微妙之处)。

© www.soinside.com 2019 - 2024. All rights reserved.