19人参与 • 2025-10-20 • Redis
redis 的 lua 脚本可以极大提升操作的原子性和效率,特别适用于需要多个 redis 命令组合执行的场景。以下是一些常见的使用场景,并结合代码进行详细说明。
redis 的 lua 脚本常用于实现分布式锁,以确保多个客户端在并发访问时的互斥性。
-- 获取锁
local lock_key = keys[1]
local lock_value = argv[1]
local ttl = tonumber(argv[2])
if redis.call("setnx", lock_key, lock_value) == 1 then
redis.call("pexpire", lock_key, ttl)
return 1
else
return 0
end
redis-cli eval "local lock_key = keys[1]; local lock_value = argv[1]; local ttl = tonumber(argv[2]); if redis.call('setnx', lock_key, lock_value) == 1 then redis.call('pexpire', lock_key, ttl); return 1; else return 0; end" 1 mylock lock_value 30000
-- 释放锁
local lock_key = keys[1]
local lock_value = argv[1]
if redis.call("get", lock_key) == lock_value then
redis.call("del", lock_key)
return 1
else
return 0
end
redis-cli eval "local lock_key = keys[1]; local lock_value = argv[1]; if redis.call('get', lock_key) == lock_value then redis.call('del', lock_key); return 1; else return 0; end" 1 mylock lock_value
实现自增、自减等计数器功能。
local key = keys[1]
local increment = tonumber(argv[1])
local current = redis.call("get", key)
if current == false then
current = 0
else
current = tonumber(current)
end
local new_value = current + increment
redis.call("set", key, new_value)
return new_value
redis-cli eval "local key = keys[1]; local increment = tonumber(argv[1]); local current = redis.call('get', key); if current == false then current = 0; else current = tonumber(current); end; local new_value = current + increment; redis.call('set', key, new_value); return new_value;" 1 mycounter 1
lua 脚本可以确保多条命令的原子性,避免使用事务的复杂性。
local from_account = keys[1]
local to_account = keys[2]
local amount = tonumber(argv[1])
local from_balance = tonumber(redis.call("get", from_account))
local to_balance = tonumber(redis.call("get", to_account))
if from_balance >= amount then
redis.call("decrby", from_account, amount)
redis.call("incrby", to_account, amount)
return 1
else
return 0
end
redis-cli eval "local from_account = keys[1]; local to_account = keys[2]; local amount = tonumber(argv[1]); local from_balance = tonumber(redis.call('get', from_account)); local to_balance = tonumber(redis.call('get', to_account)); if from_balance >= amount then redis.call('decrby', from_account, amount); redis.call('incrby', to_account, amount); return 1; else return 0; end" 2 account1 account2 100
操作有序集合(sorted sets)实现排行榜功能。
local key = keys[1]
local limit = tonumber(argv[1])
return redis.call("zrange", key, 0, limit - 1, "withscores")
redis-cli eval "local key = keys[1]; local limit = tonumber(argv[1]); return redis.call('zrange', key, 0, limit - 1, 'withscores');" 1 leaderboard 10
通过列表(list)实现任务队列。
-- 推送任务到队列
local queue_key = keys[1]
local task = argv[1]
redis.call("rpush", queue_key, task)
return redis.call("llen", queue_key)
redis-cli eval "local queue_key = keys[1]; local task = argv[1]; redis.call('rpush', queue_key, task); return redis.call('llen', queue_key);" 1 task_queue "task1"
-- 弹出任务
local queue_key = keys[1]
local task = redis.call("lpop", queue_key)
if not task then
return nil
else
return task
end
redis-cli eval "local queue_key = keys[1]; local task = redis.call('lpop', queue_key); if not task then return nil; else return task; end" 1 task_queue
实现简单的限流器,用于控制请求频率。
local key = keys[1]
local limit = tonumber(argv[1])
local interval = tonumber(argv[2])
local current = tonumber(redis.call("get", key) or "0")
if current + 1 > limit then
return false
else
redis.call("incr", key)
if current == 0 then
redis.call("expire", key, interval)
end
return true
end
redis-cli eval "local key = keys[1]; local limit = tonumber(argv[1]); local interval = tonumber(argv[2]); local current = tonumber(redis.call('get', key) or '0'); if current + 1 > limit then return false; else redis.call('incr', key); if current == 0 then redis.call('expire', key, interval); end; return true; end" 1 rate_limit_key 10 60
redis 的 lua 脚本强大且灵活,适用于多种场景。通过合理使用 lua 脚本,可以确保操作的原子性、减少网络开销和提高系统性能。上述示例涵盖了常见的分布式锁、计数器、事务性操作、排行榜、队列操作和限流器等场景,为这些应用场景提供了高效、可靠的解决方案。
到此这篇关于redis中lua脚本的常见场景的文章就介绍到这了,更多相关redis lua脚本常见场景内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论