Redis Lua脚本执行原理和语法示例

news2024/11/16 3:22:58

Redis Lua脚本语法示例

文章目录

  • Redis Lua脚本语法示例
  • 0. 前言
    • 参考资料
  • 1. Redis 执行Lua脚本原理
    • 1.1. 对Redis源码中嵌入Lua解释器的简要解析:
    • 1.2. Redis Lua 脚本缓存机制
  • 2. Redis Lua脚本示例
    • 1.1. 场景示例
      • 1. 请求限流
      • 2. 原子性地从一个list移动元素到另一个list:
      • 3. 原子性地更新hash值并返回旧值:
      • 4. 如果键不存在,则设置键值:
      • 5. 检查一个值是否在set中,并在不存在时添加:
      • 6. 删除Sorted Set中的一些元素:
      • 7. 原子性地为多个hash字段设置值:
      • 8. 列出并删除所有具有特定前缀的键:
      • 9. 在不超过最大数量的情况下,向list中添加元素:
      • 10. 在Sorted Set中添加元素,但是元素的数量不能超过特定的数量,如果超过则删除分数最低的元素:
    • 1.2. 常用示例
      • 1. 批量设置多个键的值:
      • 2. 使用Lua的math库函数进行数学计算:
      • 3. 遍历集合的元素:
      • 4. 使用Lua的string库函数进行字符串操作:
      • 5. 获取有序集合中指定成员的排名:
      • 6. 使用Lua的table库函数对Lua表进行操作:
      • 7. 遍历有序集合的成员和分数(按分数递减排序):
      • 8. 获取哈希表的字段数量:
      • 9. 集合运算(求差集):
      • 10. 使用Lua的os库函数进行操作系统相关操作:
      • 11. 对Redis键进行模式匹配:
      • 12. 获取有序集合指定范围内的成员和分数(按分数递减排序):
      • 13. 设置哈希表中不存在的字段的值:
      • 14. 获取有序集合指定范围内的成员和分数(按分数递减排序,并限制数量):
      • 15. 使用Redis Lua脚本计算布隆过滤器的插入和查询操作:
      • 16. 使用Redis Lua脚本实现简单的计数器:
      • 17. 获取Redis服务器信息:
      • 18. 对列表进行批量插入操作:
      • 19. 使用Lua的coroutine库进行协程操作:
      • 20. 执行Lua脚本时传递参数:
      • 21. 使用Redis Lua脚本计算哈希表的字段数量:
      • 22. 使用Lua的io库进行文件操作:
      • 23. 使用Redis Lua脚本计算集合的并集的数量:
      • 24. 使用Lua的debug库进行调试操作:
      • 25. 使用Redis Lua脚本计算有序集合的成员总数:
      • 26. 使用Lua的os库进行系统命令执行:
      • 27. 在有序集合中插入成员的同时设置其分数:
      • 28. 使用Lua的string库进行字符串分割操作:
      • 29. 设置Redis键的过期时间(以毫秒为单位):
      • 30. 使用Redis Lua脚本计算有序集合指定分数范围内的成员数量:
      • 31. 使用Lua的bit库进行位操作:
      • 32. 迭代哈希表的字段和值:
      • 33. 获取有序集合指定范围内的成员(按分数递减排序,并限制数量):
      • 34. 使用Lua的math库函数生成随机数:
      • 35. 获取列表的长度:
      • 36. 使用Lua的string库函数进行字符串查找操作:
      • 37. 从有序集合中移除指定分数范围内的成员:
      • 38. 使用Lua的table库函数进行表的深度复制:
      • 39. 检查Redis键是否存在:
      • 40. 使用Lua的os库函数进行时间戳转换:
      • 41. 获取列表中指定范围内的元素:
      • 42. 使用Lua的debug库函数获取当前函数信息:
      • 43. 判断字符串是否为数字:
      • 44. 获取有序集合指定成员的分数:
      • 45. 使用Lua的string库函数进行字符串替换操作:
      • 46. 遍历哈希表的字段:
      • 47. 获取集合的基数(元素数量):
      • 48. 使用Lua的io库进行文件写入操作:
      • 49. 使用Redis Lua脚本计算有序集合指定分数范围内的成员(包括分数):
      • 50. 获取哈希表的所有值:
      • 51. 使用Lua的string库函数进行字符串大小写转换:
      • 52. 获取有序集合指定范围内的成员(按分数递增排序):
      • 53. 使用Lua的table库函数对Lua表进行遍历:
      • 54. 移除列表中的元素:
      • 55. 使用Lua的string库函数进行字符串连接操作:
      • 56. 迭代有序集合的成员和分数(按分数递增排序):
      • 57. 获取列表指定索引位置的元素:
      • 58. 使用Lua的coroutine库进行协程操作:
      • 59. 获取哈希表的所有字段和值:
      • 60. 使用Lua的bit库进行位移操作:
      • 61. 执行Redis事务操作:
      • 62. 获取有序集合指定成员的排名(按分数递增排序):
      • 63. 使用Lua的os库函数获取当前时间:
      • 64. 使用Redis Lua脚本计算列表的所有元素之和:
      • 65. 使用Lua的string库函数进行字符串截取操作:
      • 66. 获取有序集合的指定排名范围内的成员(按分数递增排序):
      • 67. 使用Lua的math库函数进行四舍五入操作:
      • 68. 删除哈希表的字段:
      • 69. 使用Lua的string库函数进行字符串比较操作:
      • 70. 获取有序集合中指定成员的分数排名:
    • 分布式锁
  • 3. Redis从入门到精通系列文章

在这里插入图片描述

0. 前言

在学习本文之前,我是强烈建议大家了解一下我的其他两篇博客

  1. 《Redis 从入门到精通【进阶篇】一文学会Lua脚本》
  2. 《Redis 从入门到精通【进阶篇】之Lua脚本详解》

Redis通过嵌入Lua解释器,实现了对Lua脚本的执行。在执行过程中,Redis保证了脚本的原子性和阻塞性,同时通过脚本缓存和访问限制来提高性能和安全性。这使得Lua脚本成为在Redis中实现复杂逻辑的有效手段

  1. 嵌入式Lua解释器:Redis内部集成了Lua解释器,这使得Redis可以直接执行Lua脚本。Lua是一种轻量级的脚本语言,性能较高,且易于嵌入到其他程序中。通过嵌入Lua解释器,Redis可以实现更复杂的逻辑,同时保持高性能。

  2. 原子性Redis执行Lua脚本时,会保证脚本的原子性。这意味着在执行脚本期间,Redis不会处理其他客户端的请求。这样可以确保脚本执行过程中的数据一致性,避免并发问题这个很关键,他保证了,我们执行命令的时候是原子执行,这个是实现分布式锁的前提。

  3. 阻塞性:由于Redis是单线程模型,执行Lua脚本时会阻塞其他客户端的请求。因此,为了保持Redis的高性能,需要确保Lua脚本的执行时间尽量短。如果脚本执行时间过长,可能会导致Redis性能下降。

  4. 脚本缓存:为了提高执行效率,Redis会缓存已执行过的Lua脚本。当客户端再次请求执行相同的脚本时,Redis可以直接从缓存中获取脚本,而无需重新加载和编译。这有助于减少脚本执行的开销。

  5. 限制访问:出于安全和性能的考虑,Redis对Lua脚本的访问权限进行了限制。在Lua脚本中,只能访问到传入的键和参数,不能访问Redis的全局状态。此外,脚本中不能执行一些可能导致阻塞或影响性能的命令,如BLPOPSUBSCRIBE

参考资料

  1. Redis官方文档:https://redis.io/
  2. Redis Lua脚本教程:https://redis.io/commands/eval
  3. 分布式锁的各种实现方式:https://www.cnblogs.com/linjiqin/p/8003838.html
  4. Redis分布式锁的正确实现方式(Redlock):http://redis.io/topics/distlock
  5. 分布式系统中的锁:https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html
  6. 如何在Redis中实现分布式锁:https://www.cnblogs.com/liuyang0/p/6747257.html
  7. 使用Redis和Lua脚本实现分布式锁:https://segmentfault.com/a/1190000012919740
  8. 使用Redis实现分布式锁:https://www.cnblogs.com/0201zcr/p/5942748.html

1. Redis 执行Lua脚本原理

Redis 执行Lua脚本的核心源码位于src/scripting.c 地址:https://github.com/redis/redis/blob/6.0/src/scripting.c

Redis嵌入Lua解释器是通过将Lua源码与Redis源码结合,进行封装和适配实现的。Redis通过注册特殊的Lua命令,并调用Lua解释器的API函数,实现了Lua脚本在Redis中的执行和与Redis的交互。这样,用户可以在Redis中编写复杂的Lua脚本,利用Lua的强大功能进行数据处理和业务逻辑的实现。

1.1. 对Redis源码中嵌入Lua解释器的简要解析:

我们通过官网和源码浅析一下Redis可以执行Lua脚本的原理,其实和nginx 可以执行lua脚本的原理类似。

  1. Lua源码和头文件:Redis使用的是Lua编程语言的官方实现,即LuaJIT或Lua。Redis的源代码中包含了Lua源码文件和相关的头文件,这些文件位于src/scripting/目录下。

  2. Redis对Lua的封装:Redis通过封装Lua的API,提供了一套与Redis命令交互的接口。这些封装函数位于src/scripting.c文件中。

在这里插入图片描述

  1. Redis命令的注册:Redis将Lua脚本作为一种特殊类型的命令进行处理。在src/scripting.c文件中,Redis通过redisCommandTable数组注册了与Lua相关的命令,例如EVALEVALSHA等。这些命令与Lua脚本的执行和管理相关。

  2. Redis命令的执行:当执行Lua脚本相关的命令时,Redis首先会解析命令参数,获取Lua脚本的内容和参数。然后,Redis将Lua脚本传递给Lua解释器进行解析和执行。

  3. Lua解释器的初始化:在Redis的服务器初始化过程中,会调用luaInit()函数进行Lua解释器的初始化。该函数位于src/scripting.c文件中。在初始化过程中,Redis会创建Lua解释器实例,并进行相关的设置和配置。

  4. Lua脚本的执行:当执行Lua脚本相关的命令时,Redis会调用evalGenericCommand()函数来处理命令。该函数位于src/scripting.c文件中。在该函数中,Redis会将Lua脚本和参数传递给Lua解释器,并调用Lua的API执行脚本。

  5. Redis与Lua的交互:在Lua脚本执行期间,Redis与Lua之间可以进行数据的交互。Redis提供了一些API函数,例如redis.call()redis.pcall(),用于在Lua脚本中调用Redis命令。这些API函数允许Lua脚本直接访问Redis的键值存储和其他功能。

  6. evalGenericCommand():执行Lua脚本相关的命令(如EVALEVALSHA)。该方法接收Lua脚本和参数,并将它们传递给Lua解释器进行执行。

  7. luaCreateScriptingCommand():注册Lua脚本相关的命令。该方法通过调用Redis的命令注册函数,将Lua脚本命令添加到Redis的命令表中。

  8. evalCommand():解析和执行EVAL命令。该方法会解析命令参数,获取Lua脚本和参数,并将它们传递给evalGenericCommand()方法进行执行。

  9. loadCachedScript():加载缓存的Lua脚本。在执行EVALSHA命令时,Redis会尝试从缓存中获取已加载的Lua脚本,以提高执行效率。

1.2. Redis Lua 脚本缓存机制

Redis的Lua脚本缓存机制主要包含以下步骤:

  1. 当一个Lua脚本被发送到Redis服务器并执行时,Redis不仅会执行这个脚本,同时它还会计算该脚本的SHA1哈希值,并将这个哈希值和对应的Lua脚本内容添加至缓存中。这个过程通常是在使用EVAL命令执行脚本时自动完成的。

  2. 当我们再次执行相同的Lua脚本时,可以使用EVALSHA命令,只需要发送之前计算出的SHA1哈希值,而无需再次发送整个脚本内容。

  3. Redis会根据EVALSHA命令中的哈希值在缓存中搜索对应的Lua脚本,如果找到则直接执行,如果未找到则返回错误。

  4. 通过这种方式,我们可以避免重复发送大型的Lua脚本,从而减少网络传输的开销。同时,因为Redis直接执行缓存中的脚本,也无需再次解析脚本,从而提高了执行效率。

注意,虽然Redis的缓存可以提高Lua脚本的执行效率,但是它并不会缓存脚本的执行结果。这意味着,即使是相同的Lua脚本,每次执行时都会根据当前的数据重新计算结果。当前Redis并没有提供直接的方式来查看缓存的Lua脚本,也没有提供直接的方式来清除脚本缓存。当我们需要修改脚本时,只能重新计算修改后的脚本的哈希值,并使用新的哈希值来执行脚本。

2. Redis Lua脚本示例

Lua脚本是在Redis服务器上执行的脚本,它可以通过使用Redis提供的特定命令和库函数来与Redis进行交互。以下是一些常见的Redis Lua脚本示例:

1.1. 场景示例

1. 请求限流

使用Lua脚本完成原子递增并设置过期时间,用于API请求限流。

local current = tonumber(redis.call('get', KEYS[1]) or "0") -- 获取当前计数
local max_limit = tonumber(ARGV[1]) -- 最大计数限制
if current + 1 > max_limit then -- 如果超过最大限制则返回0
    return 0
else
    redis.call('incrby', KEYS[1], ARGV[2]) -- 否则计数+1
    redis.call('expire', KEYS[1], ARGV[3]) -- 设置过期时间
    return current + 1
end

2. 原子性地从一个list移动元素到另一个list:

local element = redis.call('rpop', KEYS[1]) -- 从list1右侧pop出元素
if element then
    redis.call('lpush', KEYS[2], element) -- 如果元素存在则push到list2
end
return element -- 返回被移动的元素

3. 原子性地更新hash值并返回旧值:

local old_val = redis.call('hget', KEYS[1], ARGV[1]) -- 获取旧值
redis.call('hset', KEYS[1], ARGV[1], ARGV[2]) -- 设置新值
return old_val -- 返回旧值

4. 如果键不存在,则设置键值:

local exists = redis.call('exists', KEYS[1]) -- 检查键是否存在
if exists == 0 then
    redis.call('set', KEYS[1], ARGV[1]) -- 如果不存在则设置键值
end
return exists -- 返回键是否存在

5. 检查一个值是否在set中,并在不存在时添加:

local exists = redis.call('sismember', KEYS[1], ARGV[1]) -- 检查值是否在set中
if exists == 0 then
    redis.call('sadd', KEYS[1], ARGV[1]) -- 如果不存在则添加
end
return exists -- 返回值是否在set中

6. 删除Sorted Set中的一些元素:

local count = 0
for i, member in ipairs(ARGV) do
    count = count + redis.call('zrem', KEYS[1], member) -- 删除Sorted Set中的元素
end
return count -- 返回被删除元素的数量

7. 原子性地为多个hash字段设置值:

for i = 1, #ARGV, 2 do
    redis.call('hset', KEYS[1], ARGV[i], ARGV[i + 1]) -- 设置多个hash字段的值
end
return true

8. 列出并删除所有具有特定前缀的键:

local keys = redis.call('keys', ARGV[1]) -- 列出所有具有特定前缀的键
for i, key in ipairs(keys) do
    redis.call('del', key) -- 删除这些键
end
return keys -- 返回被删除的键

9. 在不超过最大数量的情况下,向list中添加元素:

local size = redis.call('llen', KEYS[1]) -- 获取list的长度
if size < tonumber(ARGV[2]) then
    redis.call('rpush', KEYS[1], ARGV[1]) -- 如果未超过最大数量则添加元素
end
return size -- 返回list的长度

10. 在Sorted Set中添加元素,但是元素的数量不能超过特定的数量,如果超过则删除分数最低的元素:

redis.call('zadd', KEYS[1], ARGV[2], ARGV[1]) -- 在Sorted Set中添加元素
if redis.call('zcard', KEYS[1]) > tonumber(ARGV[3]) then -- 如果元素的数量超过最大数量
    return redis.call('zremrangebyrank', KEYS[1], 0, 0) -- 则删除分数最低的元素
end
return true

1.2. 常用示例

1. 批量设置多个键的值:

local keysValues = {'key1', 'value1', 'key2', 'value2', 'key3', 'value3'}
redis.call('MSET', unpack(keysValues))

2. 使用Lua的math库函数进行数学计算:

local result = math.sqrt(16)

3. 遍历集合的元素:

local members = redis.call('SMEMBERS', 'set')
for i, member in ipairs(members) do
    -- 处理元素
end

4. 使用Lua的string库函数进行字符串操作:

local substring = string.sub('hello world', 1, 5)

5. 获取有序集合中指定成员的排名:

local rank = redis.call('ZRANK', 'zset', 'member')

6. 使用Lua的table库函数对Lua表进行操作:

local myTable = {key1 = 'value1', key2 = 'value2', key3 = 'value3'}
table.insert(myTable, 'value4')

7. 遍历有序集合的成员和分数(按分数递减排序):

local members = redis.call('ZREVRANGE', 'zset', 0, -1, 'WITHSCORES')
for i = 1, #members, 2 do
    local member = members[i]
    local score = members[i + 1]
    -- 处理成员和分数
end

8. 获取哈希表的字段数量:

local count = redis.call('HLEN', 'hash')

9. 集合运算(求差集):

local difference = redis.call('SDIFF', 'set1', 'set2')

10. 使用Lua的os库函数进行操作系统相关操作:

local currentTime = os.date('%Y-%m-%d %H:%M:%S')

11. 对Redis键进行模式匹配:

local keys = redis.call('KEYS', 'pattern*')
for i, key in ipairs(keys) do
    -- 处理匹配到的键
end

12. 获取有序集合指定范围内的成员和分数(按分数递减排序):

local members = redis.call('ZREVRANGEBYSCORE', 'zset', maxScore, minScore, 'WITHSCORES')

13. 设置哈希表中不存在的字段的值:

redis.call('HSETNX', 'hash', 'field', 'value')

14. 获取有序集合指定范围内的成员和分数(按分数递减排序,并限制数量):

local members = redis.call('ZREVRANGE', 'zset', 0, 10, 'WITHSCORES')

15. 使用Redis Lua脚本计算布隆过滤器的插入和查询操作:

redis.call('EVAL', 'local bf = redis.call("BFINSERT", "filter", "item"); local result = redis.call("BFCHECK", "filter", "item"); return result;', 0)

16. 使用Redis Lua脚本实现简单的计数器:

local count = redis.call('INCR', 'counter')

17. 获取Redis服务器信息:

local info = redis.call('INFO')

18. 对列表进行批量插入操作:

local values = {'value1', 'value2', 'value3'}
redis.call('RPUSH', 'list', unpack(values))

19. 使用Lua的coroutine库进行协程操作:

local co = coroutine.create(function()
    -- 执行协程操作
end)
coroutine.resume(co)

20. 执行Lua脚本时传递参数:

local key = KEYS[1]
local value = ARGV[1]
redis.call('SET', key, value)

21. 使用Redis Lua脚本计算哈希表的字段数量:

local fieldsCount = 0
local fields = redis.call('HGETALL', 'hash')
for i = 1, #fields, 2 do
    fieldsCount = fieldsCount + 1
end
return fieldsCount

22. 使用Lua的io库进行文件操作:

local file = io.open('/path/to/file', 'r')
local content = file:read('*a')
file:close()

23. 使用Redis Lua脚本计算集合的并集的数量:

local union = redis.call('SUNION', 'set1', 'set2')
return #union

24. 使用Lua的debug库进行调试操作:

local info = debug.getinfo(2)

25. 使用Redis Lua脚本计算有序集合的成员总数:

local count = redis.call('ZCARD', 'zset')

26. 使用Lua的os库进行系统命令执行:

local result = os.execute('command')

27. 在有序集合中插入成员的同时设置其分数:

redis.call('ZADD', 'zset', score, 'member')

28. 使用Lua的string库进行字符串分割操作:

local str = 'hello world'
local parts = {}
for part in string.gmatch(str, '%S+') do
    table.insert(parts, part)
end

29. 设置Redis键的过期时间(以毫秒为单位):

redis.call('PEXPIRE', 'key', 1000)

30. 使用Redis Lua脚本计算有序集合指定分数范围内的成员数量:

local count = redis.call('ZCOUNT', 'zset', minScore, maxScore)

31. 使用Lua的bit库进行位操作:

local result = bit.band(7, 3)

32. 迭代哈希表的字段和值:

local fieldsValues = redis.call('HGETALL', 'hash')
for i = 1, #fieldsValues, 2 do
    local field = fieldsValues[i]
    local value = fieldsValues[i + 1]
    -- 处理字段和值
end

33. 获取有序集合指定范围内的成员(按分数递减排序,并限制数量):

local members = redis.call('ZREVRANGE', 'zset', 0, 10)

34. 使用Lua的math库函数生成随机数:

local random = math.random(1, 100)

35. 获取列表的长度:

local length = redis.call('LLEN', 'list')

36. 使用Lua的string库函数进行字符串查找操作:

local index = string.find('hello world', 'world')

37. 从有序集合中移除指定分数范围内的成员:

redis.call('ZREMRANGEBYSCORE', 'zset', minScore, maxScore)

38. 使用Lua的table库函数进行表的深度复制:

local tableCopy = table.deepcopy(originalTable)

39. 检查Redis键是否存在:

local exists = redis.call('EXISTS', 'key')

40. 使用Lua的os库函数进行时间戳转换:

local timestamp = os.time()
local date = os.date('%Y-%m-%d %H:%M:%S', timestamp)

41. 获取列表中指定范围内的元素:

local elements = redis.call('LRANGE', 'list', start, stop)

42. 使用Lua的debug库函数获取当前函数信息:

local info = debug.getinfo(1, 'n')

43. 判断字符串是否为数字:

local isNumber = tonumber('123')

44. 获取有序集合指定成员的分数:

local score = redis.call('ZSCORE', 'zset', 'member')

45. 使用Lua的string库函数进行字符串替换操作:

local replacedString = string.gsub('hello world', 'world', 'redis')

46. 遍历哈希表的字段:

local fields = redis.call('HKEYS', 'hash')
for i, field in ipairs(fields) do
    -- 处理字段
end

47. 获取集合的基数(元素数量):

local cardinality = redis.call('SCARD', 'set')

48. 使用Lua的io库进行文件写入操作:

local file = io.open('/path/to/file', 'w')
file:write('content')
file:close()

49. 使用Redis Lua脚本计算有序集合指定分数范围内的成员(包括分数):

local members = redis.call('ZRANGEBYSCORE', 'zset', minScore, maxScore, 'WITHSCORES')

50. 获取哈希表的所有值:

local values = redis.call('HVALS', 'hash')

51. 使用Lua的string库函数进行字符串大小写转换:

local lowercase = string.lower('HELLO')
local uppercase = string.upper('world')

52. 获取有序集合指定范围内的成员(按分数递增排序):

local members = redis.call('ZRANGE', 'zset', minScore, maxScore)

53. 使用Lua的table库函数对Lua表进行遍历:

local myTable = {key1 = 'value1', key2 = 'value2', key3 = 'value3'}
for key, value in pairs(myTable) do
    -- 处理键和值
end

54. 移除列表中的元素:

redis.call('LREM', 'list', count, 'element')

55. 使用Lua的string库函数进行字符串连接操作:

local concatenatedString = string.concat('hello', 'world')

56. 迭代有序集合的成员和分数(按分数递增排序):

local members = redis.call('ZRANGE', 'zset', 0, -1, 'WITHSCORES')
for i = 1, #members, 2 do
    local member = members[i]
    local score = members[i + 1]
    -- 处理成员和分数
end

57. 获取列表指定索引位置的元素:

local element = redis.call('LINDEX', 'list', index)

58. 使用Lua的coroutine库进行协程操作:

local co = coroutine.create(function()
    -- 执行协程操作
end)
coroutine.resume(co)

59. 获取哈希表的所有字段和值:

local fieldsValues = redis.call('HGETALL', 'hash')

60. 使用Lua的bit库进行位移操作:

local result = bit.lshift(7, 2)

61. 执行Redis事务操作:

redis.call('MULTI')
redis.call('SET', 'key1', 'value1')
redis.call('SET', 'key2', 'value2')
redis.call('EXEC')

62. 获取有序集合指定成员的排名(按分数递增排序):

local rank = redis.call('ZRANK', 'zset', 'member')

63. 使用Lua的os库函数获取当前时间:

local currentTime = os.time()

64. 使用Redis Lua脚本计算列表的所有元素之和:

local sum = 0
local elements = redis.call('LRANGE', 'list', 0, -1)
for i, element in ipairs(elements) do
    sum = sum + tonumber(element)
end
return sum

65. 使用Lua的string库函数进行字符串截取操作:

local substring = string.sub('hello world', 7)

66. 获取有序集合的指定排名范围内的成员(按分数递增排序):

local members = redis.call('ZRANGEBYRANK', 'zset', startRank, endRank)

67. 使用Lua的math库函数进行四舍五入操作:

local roundedNumber = math.round(3.7)

68. 删除哈希表的字段:

redis.call('HDEL', 'hash', 'field')

69. 使用Lua的string库函数进行字符串比较操作:

local result = string.compare('hello', 'world')

70. 获取有序集合中指定成员的分数排名:

local rank = redis.call('ZREVRANK', 'zset', 'member')

分布式锁

不同的语言和类库已经基于Redis实现了分布式锁,大家可以用作参考。

Redlock-rb(Ruby实现)。还有一个Redlock-rb的分支,增加了一个gem以便于分发。
Redlock-py(Python实现)。
Pottery(Python实现)。
Aioredlock(Asyncio Python实现)。
Redlock-php(PHP实现)。
PHPRedisMutex(进一步的PHP实现)。
cheprasov/php-redis-lock(PHP锁库)。
rtckit/react-redlock(异步PHP实现)。
Redsync(Go实现)。
Redisson(Java实现)。
Redis::DistLock(Perl实现)。
Redlock-cpp(C++实现)。
Redis-plus-plus(C++实现)。
Redlock-cs(C#/.NET实现)。
RedLock.net(C#/.NET实现)。包括异步和锁扩展支持。
ScarletLock(C# .NET实现,具有可配置的数据存储)。
Redlock4Net(C# .NET实现)。
node-redlock(NodeJS实现)。包括对锁扩展的支持。
Deno DLM(Deno实现)
Rslock(Rust实现)。包括异步和锁扩展支持。

3. Redis从入门到精通系列文章

  1. 《Redis 从入门到精通【进阶篇】之Lua脚本详解》
  2. 《Redis 从入门到精通【实践篇】SpringBoot Redis 配置多数据源》
  3. 《Redis 从入门到精通【进阶篇】三分钟了解Redis地理位置数据结构GeoHash》
  4. 《Redis 从入门到精通【进阶篇】一文学会Lua脚本》
  5. 《Redis使用Lua脚本和Redisson来保证库存扣减中的原子性和一致性》
  6. 《SpringBoot Redis 使用Lettuce和Jedis配置哨兵模式》
  7. 《Redis【应用篇】之RedisTemplate基本操作》
  8. 《Redis 从入门到精通【实践篇】之SpringBoot配置Redis多数据源》
  9. 《Redis 从入门到精通【进阶篇】之三分钟了解Redis HyperLogLog 数据结构》
  10. 《Redis 从入门到精通【进阶篇】之三分钟了解Redis地理位置数据结构GeoHash》
  11. 《Redis 从入门到精通【进阶篇】之高可用哨兵机制(Redis Sentinel)详解》
  12. 《Redis 从入门到精通【进阶篇】之redis主从复制详解》
  13. 《Redis 从入门到精通【进阶篇】之Redis事务详解》
  14. 《Redis从入门到精通【进阶篇】之对象机制详解》
  15. 《Redis从入门到精通【进阶篇】之消息传递发布订阅模式详解》
  16. 《Redis从入门到精通【进阶篇】之持久化 AOF详解》
  17. 《Redis从入门到精通【进阶篇】之持久化RDB详解》
  18. 《Redis从入门到精通【高阶篇】之底层数据结构字典(Dictionary)详解》
  19. 《Redis从入门到精通【高阶篇】之底层数据结构快表QuickList详解》
  20. 《Redis从入门到精通【高阶篇】之底层数据结构简单动态字符串(SDS)详解》
  21. 《Redis从入门到精通【高阶篇】之底层数据结构压缩列表(ZipList)详解》
  22. 《Redis从入门到精通【进阶篇】之数据类型Stream详解和使用示例》
    在这里插入图片描述

大家好,我是冰点,今天的Redis Lua脚本执行原理和语法示例,全部内容就是这些。如果你有疑问或见解可以在评论区留言。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/907628.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

matlab使用教程(18)—多项式的定义和运算

1.创建并计算多项式 此示例说明如何在 MATLAB 中将多项式表示为向量以及根据相关点计算多项式。 1.1 表示多项式 MATLAB 将多项式表示为行向量&#xff0c;其中包含按降幂排序的系数。例如&#xff0c;三元素向量 p [p2 p1 p0]; 表示多项式 创建一个向量以表示二次多项式…

一文看懂!数据管道和数据流在数据分析中的作用

当我们谈论数据分析时&#xff0c;我们通常会想到一系列的步骤&#xff0c;包括数据收集、数据清洗、数据分析和数据可视化等。然而&#xff0c;在这些步骤中&#xff0c;有两个非常重要的概念&#xff1a;数据管道和数据流。这两个概念在数据分析过程中起着至关重要的作用。本…

Vue3组合式API详解 - 大型应用的高端写法

目录 01-setup方法与script_setup及ref响应式02-事件方法_计算属性_reactive_toRefs03-生命周期_watch_watchEffect04-跨组件通信方案provide_inject05-复用组件功能之use函数06-利用defineProps与defineEmits进行组件通信 01-setup方法与script_setup及ref响应式 在Vue3.1版本…

图片怎么转换成pdf格式?可以试试这样转换

图片怎么转换成pdf格式&#xff1f;图片转换成PDF格式是一个常见的需求&#xff0c;无论是为了方便存储还是为了分享文件&#xff0c;将图片转换成PDF格式都是一个不错的选择。有许多软件和在线工具可以帮助你完成这个任务&#xff0c;下面就给大家介绍一款转换工具。 【迅捷PD…

中期国际:MT4交易平台介绍:功能、优势与适用范围

在外汇市场中&#xff0c;MetaTrader 4(简称MT4)被广泛认可为最受欢迎的交易平台之一。它具备丰富的功能和独特的优势&#xff0c;不仅适用于个人零售交易者&#xff0c;也广泛应用于金融机构和专业交易员。本文将介绍MT4交易平台的关键功能、独有优势以及适用范围。 首先&…

隔断让你的办公室变得更加智能、环保、人性化

隔断可以在办公室中起到多种重要作用&#xff0c;使办公室更加智能、环保和人性化。以下是一些可能的方式&#xff1a; 1. 智能办公室控制系统&#xff1a;可以通过隔断集成智能办公室控制系统&#xff0c;实现办公室照明、温度和空调等设备的自动调节&#xff0c;提高能效和舒…

Linux系统下检验Tensorflow 2.xx版本和1.xx版本是否安装成功

目录 版本问题Tensorflow 1.xx的测试代码&#xff1a;Tensorflow 2.xx的测试代码&#xff1a;Tensorflow 2.6版本实际的测验结果 总结 版本问题 查询资料发现&#xff0c;多数检验Tensorflow是否安装成功的方法&#xff0c;多数方法都是1.xx版本的&#xff0c;直接使用1.xx版本…

【Linux】IO模型

【Linux】IO模型 文章目录 【Linux】IO模型1、模型概念1.1 IO概念1.2 模型应用 2、模型种类2.1 阻塞IO2.2 非阻塞IO2.3 信号驱动IO2.4 IO多路转接2.5 异步IO 3、概念对比3.1 同步、异步通信3.2 阻塞、非阻塞 4、fcntl4.1 函数原型4.2 指令参数4.3 实现非阻塞IO 5、IO多路转接5.…

AlmaLinux 向红帽示好,被拒绝了

导读AlmaLinux 向红帽示好&#xff0c;被拒绝了。 红帽关闭 CentOS&#xff0c;推行 CentOS Stream 成为 RHEL 上游&#xff0c;其中一个理由是希望社区来参与 CentOS Stream/RHEL 的开发&#xff0c;并指责 AlmaLinux 等 RHEL 克隆品只是简单的重建&#xff0c;而没有做出任何…

6-模板初步使用

官网: 中文版: 介绍-Jinja2中文文档 英文版: Template Designer Documentation — Jinja Documentation (2.11.x) 模板语法 1. 模板渲染 (1) app.py 准备数据 import jsonfrom flask import Flask,render_templateimport settingsapp Flask(__name__) app.config.from_obj…

基于STM32的OLED多级菜单GUI实现(简化版智能手表)

前言&#xff1a;本文的OLED多级菜单UI为一个综合性的STM32小项目&#xff0c;使用多传感器与OLED显示屏实现智能终端的效果。项目中的多级菜单UI使用了较为常见的结构体索引法去实现功能与功能之间的来回切换&#xff0c;搭配DHT11&#xff0c;RTC&#xff0c;LED&#xff0c;…

git创建分支和合并分支

1.创建分支 git创建分支只需要使用switch 命令就行&#xff1a; git switch -c 分支名 创建分支并切换到该分支 后面括号里面的内容发生改变就是修改了分支 。 然后想要合并分支就在 创建的分支中 进行提交修改的内容&#xff0c;还是通过&#xff1a;add 命令和commit命令…

node没有自动安装npm时,如何手动安装 npm

之前写过一篇使用 nvm 管理 node 版本的文章&#xff0c;node版本管理&#xff08;Windows&#xff09; 有时候&#xff0c;我们使用 nvm 下载 node 时&#xff0c;node 没有自动下载 npm &#xff0c;此时就需要我们自己手动下载 npm 1、下载 npm下载地址&#xff1a;&…

m3u8视频怎么保存到本地?这个小妙招了解下

m3u8是一种视频文件格式&#xff0c;通常用于流媒体服务&#xff0c;可以将大型视频文件分割成较小的TS分段进行传输&#xff0c;从而使得视频的传输更加流畅和高效。。m3u8文件包含了一个视频播放列表&#xff0c;其中包含了所有的TS分段的URL地址&#xff0c;以及每个分段的时…

暑期高铁站大量遗失物品,FindMy帮助寻找

近日&#xff0c;一女子在上海坐高铁时&#xff0c;将户口本、房产证遗落安检处的新闻引起网友的关注。然后业内人士表示&#xff1a;常事&#xff0c;车站什么都能捡到。 据中国铁路透露&#xff0c;暑运期间&#xff0c;上海虹桥站客流增加&#xff0c;日均发送旅客20多万人…

四川玖璨电商:2023怎样运营短视频?

​短视频的兴起和流行让越来越多的人关注和运营短视频号。如何运营短视频号&#xff0c;吸引更多的观众和粉丝&#xff1f;下面四川玖璨电商小编将介绍几个关键点。 首先&#xff0c;确定短视频的定位和主题非常重要。根据自己的兴趣和特长&#xff0c;确定一个独特的主题&…

通过远程访问解决家人的电脑难题

家里老人使用电脑、手机等设备遇到问题&#xff0c;子女在其他城市没法现场解决&#xff0c;远程沟通很困难。有没有一种方法可以随时远程帮助家人解决电脑、手机相关问题&#xff1f; 通过远程桌面软件&#xff0c;你可以与父母一起实时解决问题。这样他们就不会一遍遍给你打…

ARM开发(LED点灯实验)

1.汇编实现开发板三盏灯点亮熄灭&#xff1b; .text .global _start _start: /**********LED123点灯**************/RCC_INIT:1使能PE10 PF10 PE8RCC..寄存器,E[4]1 F[5]1 0x50000a28ldr r0,0x50000a28ldr r1,[r0]orr r1,r1,#(0x3 << 4)str r1,[r0]LED1_INET:2初始化LED…

三分钟上手! 一文看懂 Git 的底层工作原理

目录 1. 三分钟上手! 一文看懂 Git 的底层工作原理1.1. Git 目录结构1.2. Git 三大对象1.3. Git Brach 和 Tag 1. 三分钟上手! 一文看懂 Git 的底层工作原理 1.1. Git 目录结构 Git 的本质是一个文件系统(很重要, 记住这句话, 理解这句话), 工作目录中的所有文件的历史版本以…