<?php
/**
* Created by PhpStorm.
* redis 銷量超賣秒殺解決方案
* redis 文檔:http://doc.redisfans.com/
* ab -n 10000 -c 3000 http://localhost/demo.php 模擬併發
*/
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
//1. 對某一個鍵加鎖,這個鍵是咱們本身設置,起到監視做業
$redis->watch('sales');
//獲取銷量,清空sales 爲0
$sales = $redis->get('sales');
//總庫存
$store = 4;
if($sales>=$store){
exit('已經被搶光了'); //跳轉活動結束頁面
}
//redis事務不會回滾, 開啓事務
$redis->multi();
$redis->set('sales',$sales+1); //銷量加1
$res = $redis->exec();
if($res){
//減庫存
include db.php; //數據庫鏈接
//執行sql ,減庫存
}
exit;
=====================redis接口限流============================
以上代碼有兩點缺陷 private boolean accessLimit(String ip, int limit, int time, Jedis jedis) { boolean result = true; String key = "rate.limit:" + ip; if (jedis.exists(key)) { long afterValue = jedis.incr(key); if (afterValue > limit) { result = false; } } else { Transaction transaction = jedis.multi(); transaction.incr(key); transaction.expire(key, time); transaction.exec(); } return result; }
WATCH
監控 rate.limit:$IP
的變更, 但較爲麻煩;pipeline
的狀況下最多須要向Redis請求5條指令, 傳輸過多.Lua腳本實現
Redis 容許將 Lua 腳本傳到 Redis 服務器中執行, 腳本內能夠調用大部分 Redis 命令, 且 Redis 保證腳本的原子性:php
-- -- Created by IntelliJ IDEA. -- User: jifang -- Date: 16/8/24 -- Time: 下午6:11 -- local key = "rate.limit:" .. KEYS[1] local limit = tonumber(ARGV[1]) local expire_time = ARGV[2] local is_exists = redis.call("EXISTS", key) if is_exists == 1 then if redis.call("INCR", key) > limit then return 0 else return 1 end else redis.call("SET", key, 1) redis.call("EXPIRE", key, expire_time) return 1 end
private boolean accessLimit(String ip, int limit, int timeout, Jedis connection) throws IOException { List<String> keys = Collections.singletonList(ip); List<String> argv = Arrays.asList(String.valueOf(limit), String.valueOf(timeout)); return 1 == (long) connection.eval(loadScriptString("script.lua"), keys, argv); } // 加載Lua代碼 private String loadScriptString(String fileName) throws IOException { Reader reader = new InputStreamReader(Client.class.getClassLoader().getResourceAsStream(fileName)); return CharStreams.toString(reader); }
Lua 嵌入 Redis 優點: java