1. 程式人生 > >redis原子性讀寫操作之LUA指令碼和watch機制

redis原子性讀寫操作之LUA指令碼和watch機制

最近在開發電商平臺的子系統——儲值卡系統,系統核心業務涉及到金額消費以及庫存控制,因此為了解決建立在記憶體上高併發情況下的事務控制,使用了spring封裝的RedisTemplate執行lua指令碼進行原子性操作,確保金額消費,庫存按順序處理,解決資源爭搶。

  1.使用lua指令碼

  Redis 使用單個 Lua 直譯器去執行所有指令碼,並且, Redis 也保證指令碼會以原子性(atomic)的方式執行:當某個指令碼正在執行的時候,不會有其他指令碼或 Redis 命令被執行。這和使用 MULTI / EXEC 包圍的事務很類似。在其他別的客戶端看來,指令碼的效果(effect)要麼是不可見的(not visible),要麼就是已完成的(already completed)。

  另一方面,這也意味著,執行一個執行緩慢的指令碼並不是一個好主意。寫一個跑得很快很順溜的指令碼並不難,因為指令碼的執行開銷(overhead)非常少,但是當你不得不使用一些跑得比較慢的指令碼時,請小心,因為當這些蝸牛指令碼在慢吞吞地執行的時候,其他客戶端會因為伺服器正忙而無法執行命令。

  2.實現watch機制

  WATCH key [key ...]

  監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那麼事務將被打斷。

  MULTI

  標記一個事務塊的開始。

  事務塊內的多條命令會按照先後順序被放進一個隊列當中,最後由 EXEC 命令原子性(atomic)地執行。

  EXEC

  執行所有事務塊內的命令。

  假如某個(或某些) key 正處於 WATCH 命令的監視之下,且事務塊中有和這個(或這些) key 相關的命令,那麼 EXEC 命令只在這個(或這些) key 沒有被其 他命令所改動的情況下執行並生效,否則該事務被打斷(abort)。

    例子:

  # 事務被成功執行

  redis> MULTI
  OK

  redis> INCR user_id
  QUEUED

  redis> INCR user_id
  QUEUED

  redis> INCR user_id
  QUEUED

  redis> PING
  QUEUED

  redis> EXEC
  1) (integer) 1
  2) (integer) 2
  3) (integer) 3
  4) PONG


  # 監視 key ,且事務成功執行

  redis> WATCH lock lock_times
  OK
  redis> MULTI   OK   redis> SET lock "huangz"   QUEUED   redis> INCR lock_times   QUEUED   redis> EXEC   1) OK   2) (integer) 1   # 監視 key ,且事務被打斷   redis> WATCH lock lock_times   OK   redis> MULTI   OK   redis> SET lock "joe" # 就在這時,另一個客戶端修改了 lock_times 的值   QUEUED   redis> INCR lock_times   QUEUED   redis> EXEC # 因為 lock_times 被修改, joe 的事務執行失敗   (nil)

轉載於:https://www.cnblogs.com/cl2Blogs/p/6097206.html