目录
入门
启动Redis服务: docker run --name redis-in-action -p 6379:6379 -d redis
redis-cli
EVAL "return {KEYS[1], KEYS[2], ARGV[1], ARGV[2]}" 2 1 2 3 4
1) "1"
2) "2"
3) "3"
4) "4"
echo "return { KEYS[1], KEYS[2], ARGV[1], ARGV[2] }" >> hello.lua
redis-cli --eval hello.lua 1 2 , 3 4
1) "1"
2) "2"
3) "3"
4) "4"
关于Lua更多介绍 参考Lua简明教程
秒杀
-
高并发 - Redis内存
-
原子性 - Redis单线程
vim seckilling.lua
local n = tonumber(ARGV[1])
if not n or n == 0 then
return 0
end
local vals = redis.call("HMGET", KEYS[1], "Total", "Booked")
local total = tonumber(vals[1])
local blocked = tonumber(vals[2])
if not total or not blocked then
return 0
end
if blocked + n <= total then
redis.call("HINCRBY", KEYS[1], "Booked", n)
return n;
end
return 0
redis-cli script load "$(cat seckilling.lua)" # 58652c43df5e7752b7bb1f8e65e382299b5bd8b6
redis-cli
HMSET goodsId Total 100 Booked 0
HMGET goodsId Total Booked
1) "100"
2) "1"
SCRIPT EXISTS 58652c43df5e7752b7bb1f8e65e382299b5bd8b6
EVALSHA 58652c43df5e7752b7bb1f8e65e382299b5bd8b6 1 goodsId 1
HMGET goodsId Total Booked
1) "100"
2) "1"
关于Redis单线程模型的更多讨论 可以参考为什么redis 是单线程的? & Redis单线程优势 & Redis is single threaded. How can I exploit multiple CPU / cores?
队列
-
发布-订阅 - Redis队列
-
缓存 - 高速Redis + MySQL
vim seckilling.lua
local n = tonumber(ARGV[1])
if not n or n == 0 then
return 0
end
local vals = redis.call("HMGET", KEYS[1], "Total", "Booked")
local total = tonumber(vals[1])
local blocked = tonumber(vals[2])
if not total or not blocked then
return 0
end
if blocked + n <= total then
redis.call("HINCRBY", KEYS[1], "Booked", n)
redis.call("LPUSH", KEYS[2], "Booked "..n)
return n;
end
return 0
redis-cli script load "$(cat seckilling.lua)" # b191ffa49361dac8f9142f0eac552cecd0df2489
redis-cli
SCRIPT EXISTS b191ffa49361dac8f9142f0eac552cecd0df2489
EVALSHA b191ffa49361dac8f9142f0eac552cecd0df2489 2 goodsId orderList 1
HMGET goodsId Total Booked
1) "100"
2) "2"
BRPOP orderList 60
1) "orderList"
2) "Booked 1"
这里只是将orderList的数据取出 实际项目中可以结合关系数据库处理该订单
服务
egg-init --type=simple server
cd server && cnpm i
cnpm i --save egg-redis
vim config/plugin.js
'use strict';
exports.redis = {
enable: true,
package: 'egg-redis',
};
vim config/config.default.js
'use strict';
module.exports = appInfo => {
const config = exports = {};
// use for cookie sign key, should change to your own and keep security
config.keys = appInfo.name + '_1537341461009_7706';
// add your config here
config.middleware = [];
config.redis = {
client: {
host: '127.0.0.1',
port: 6379,
password: '',
db: '0',
}
};
return config;
};
vim app/controller/home.js
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
const { ctx, app } = this;
const code =
`
local n = tonumber(ARGV[1])
if not n or n == 0 then
return 0
end
local vals = redis.call("HMGET", KEYS[1], "Total", "Booked")
local total = tonumber(vals[1])
local blocked = tonumber(vals[2])
if not total or not blocked then
return 0
end
if blocked + n <= total then
redis.call("HINCRBY", KEYS[1], "Booked", n)
redis.call("LPUSH", KEYS[2], "Booked "..n)
return n;
end
return 0
`;
app.redis.defineCommand('seckilling', {
lua: code
});
ctx.body = await app.redis.seckilling(2, 'goodsId', 'orderList', '1');
}
}
module.exports = HomeController;
cnpm run dev # localhost:7001
测试
redis-cli
HMSET goodsId Total 100 Booked 0
DEL orderList
sudo apt update
sudo apt install -y apache2-utils
ulimit -n 10000
ab -n 50000 -c 5000 http://192.168.56.1:7001/
关于ab的更多介绍 可以参考超实用压力测试工具-ab工具
redis-cli
HMGET goodsId Total Booked
1) "100"
2) "100"
网友评论