需求
雙十二要搞乙個一分錢門票搶購的活動。
分析
效能分析,搶購時會發生高併發,如果僅僅依靠mysql資料庫,有可能因為大量的請求頻繁訪問資料庫造成伺服器雪崩,所以考慮通過redis減庫存,最終的資料落地到db中。
在高併發的情況下,還要考慮到超賣的問題,因而打算使用lua指令碼完成原子減的操作。
在這裡,我們只針對減庫存的操作進行分析。
實現
不使用原子操作,出現超賣的情況。第一步:先從redis中查出庫存進行判斷,第二步:如果庫存》0,則進行減庫存的操作。
**實現:
1用多執行緒模擬併發請求:庫存為500,建立505個執行緒去搶購。//第一步:從redis中查出庫存
2 integer stock = (integer) redisutils.get("stock");34
//第二步:如果庫存》0,則進行減庫存的操作
5if (stock > 0) else
1執行結果:出現超賣問題,原因是:查詢庫存及減庫存不是原子性操作。for(int i =1;i<=505;i++)
使用原子性操作:直接減庫存。
1lua指令碼實現減庫存操作:public
void
run() else
89 }
/**執行結果:505個執行緒去搶500個商品,有五個執行緒會搶不到,測試結果與預期一致,解決了超賣的問題。* 庫存不足
*/public
static
final
int low_stock = 0;
/*** 不限庫存
*/public
static
final
long uninitialized_stock = -1l;
/*** 執行扣庫存的指令碼
*/public
static
final
string stock_lua;
static
/*** 扣庫存**
@param
key 庫存key
* @return
扣減之前剩餘的庫存【0:庫存不足; -1:庫存未初始化; 大於0:扣減庫存之前的剩餘庫存】
*/public
static
long stock(string key)
//單機模式
else
if (nativeconnection instanceof
jedis)
return
uninitialized_stock;
}});
return
result;
}
參考:
Redis使用Lua指令碼自定義原子操作
1 eval eval 指令碼內容 key個數 key列表 引數列表 127.0.0.1 6379 eval return hello keys 1 ar 1 1 redis why hello redis why 2 evalsha 先通過script load命令將lua指令碼載入到redis,...
lua指令碼保證Redis多條命令原子性
redis能執行lua指令碼,一段lua指令碼可以作為乙個整體,這樣將多條redis命令寫入lua,即可以實現事務的原子性,下面演示了jedis和redistemplate是如何呼叫lua指令碼的 完成的功能是 set my key1 my value1 ex 15 nx,lua指令碼很神奇不需要加...
Redis使用lua指令碼
版本 自2.6.0起可用。時間複雜度 取決於執行的指令碼。使用lua指令碼的好處 命令格式 eval script numkeys key key arg arg 說明 簡單例項 127.0.0.1 6379 eval return ar 1 0 100 100 127.0.0.1 6379 eva...