五分钟讲透 Redis Lua脚本,以及Redis cluster集群模式下的 command keys must in same slot 解决方案 redis hash tag

这篇具有很好参考价值的文章主要介绍了五分钟讲透 Redis Lua脚本,以及Redis cluster集群模式下的 command keys must in same slot 解决方案 redis hash tag。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. Lua脚本

lua是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用 程序中,从而为应用程序提供灵活的扩展和定制功能。 Lua应用场景:游戏开发、独立应用脚本、Web应用脚本、扩展和数据库插件。

OpenRestry:一个可伸缩的基于Nginx的Web平台,是在nginx之上集成了lua模块的第三方服务器

OpenResty是一个通过Lua扩展Nginx实现的可伸缩的Web平台,内部集成了大量精良的Lua库、第三方 模块以及大多数的依赖项。 用于方便地搭建能够处理超高并发(日活千万级别)、扩展性极高的动态Web应用、Web服务和动态网关。 功能和nginx类似,就是由于支持lua动态脚本,所以更加灵活,可以实现鉴权、限流、分流、日志记 录、灰度发布等功能。 OpenResty通过Lua脚本扩展nginx功能,可提供负载均衡、请求路由、安全认证、服务鉴权、流量控 制与日志监控等服务。 类似的还有Kong(Api Gateway)、tengine(阿里)

2. Lua环境协作组件

从Redis2.6.0版本开始,通过内置的lua编译/解释器,可以使用EVAL命令对lua脚本进行求值。

脚本的命令是原子的,RedisServer在执行脚本命令中,不允许插入新的命令

脚本的命令可以复制,RedisServer在获得脚本后不执行,生成标识返回,Client根据标识就可以随时执行

3. EVAL/EVALSHA命令实现

3.1 EVAL命令

通过执行redis的eval命令,可以运行一段lua脚本。

EVAL script numkeys key [key ...] arg [arg ...]

命令说明:

  • script参数: 是一段Lua脚本程序,它会被运行在Redis服务器上下文中,这段脚本不必(也不应该) 定义为一个Lua函数。
  • numkeys参数: 用于指定键名参数的个数。
  • key [key …]参数: 从EVAL的第三个参数开始算起,使用了numkeys个键(key),表示在脚本中所用到的那些Redis键(key),这些键名参数可以在Lua中通过全局变量KEYS数组,用1为基址的形 式访问( KEYS[1] , KEYS[2] ,以此类推)。
  • arg [arg …]参数:可以在Lua中通过全局变量ARGV数组访问,访问的形式和KEYS变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)。
eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second

3.2 lua脚本中调用Redis命令

  • redis.call():
    • 返回值就是redis命令执行的返回值
    • 如果出错,则返回错误信息,不继续执行
  • redis.pcall():
    • 返回值就是redis命令执行的返回值
    • 如果出错,则记录错误信息,继续执行
  • 注意事项
    • 在脚本中,使用return语句将返回值返回给客户端,如果没有return,则返回nil

eval "return redis.call('set',KEYS[1],ARGV[1])" 1 n1 zhaoyun

3.3 EVALSHA

EVAL 命令要求你在每次执行脚本的时候都发送一次脚本主体(script body)。

传送脚本主体并不是最佳选择。 为了减少带宽的消耗, Redis 实现了 EVALSHA 命令,它的作用和 EVAL 一样,都用于对脚本求值,但 它接受的第一个参数不是脚本,而是脚本的 SHA1 校验和(sum)

SCRIPT命令

  • SCRIPT FLUSH :清除所有脚本缓存

  • SCRIPT EXISTS:根据给定的脚本校验和,检查指定的脚本是否存在于脚本缓存

  • SCRIPT LOAD: 将一个脚本装入脚本缓存,返回SHA1摘要,但并不立即运行它

    192.168.24.131:6380> script load "return redis.call('set',KEYS[1],ARGV[1])"
    "c686f316aaf1eb01d5a4de1b0b63cd233010e63d"
    192.168.24.131:6380> evalsha c686f316aaf1eb01d5a4de1b0b63cd233010e63d 1 n2
    zhangfei
    OK
    192.168.24.131:6380> get n2
    
  • SCRIPT KILL :杀死当前正在运行的脚本

参考

https://redis.io/commands/eval/

脚本管理命令实现

使用redis-cli直接执行lua脚本。

  • test.lua

    return redis.call('set',KEYS[1],ARGV[1])
    ./redis-cli -h 127.0.0.1 -p 6379 --eval test.lua name:6 , 'caocao' #,两边有空
    
  • list.lua

    local key=KEYS[1]
    local list=redis.call("lrange",key,0,-1);
    return list;
    ./redis-cli --eval list.lua list
    

    利用Redis整合Lua,主要是为了性能以及事务的原子性。因为redis帮我们提供的事务功能太差。

3.4 脚本复制

Redis 传播 Lua 脚本,在使用主从模式和开启AOF持久化的前提下:

当执行lua脚本时,Redis 服务器有两种模式:脚本传播模式和命令传播模式。

脚本传播模式

脚本传播模式是 Redis 复制脚本时默认使用的模式 Redis会将被执行的脚本及其参数复制到 AOF 文件以及从服务器里面。

执行以下命令:

eval "redis.call('set',KEYS[1],ARGV[1]);redis.call('set',KEYS[2],ARGV[2])" 2 n1 n2
zhaoyun1 zhaoyun2

那么主服务器将向从服务器发送完全相同的 eval 命令:

eval "redis.call('set',KEYS[1],ARGV[1]);redis.call('set',KEYS[2],ARGV[2])" 2 n1 n2
zhaoyun1 zhaoyun2

注意:在这一模式下执行的脚本不能有时间、内部状态、随机函数(spop)等。执行相同的脚本以及参数 必须产生相同的效果。在Redis5,也是处于同一个事务中。

命令传播模式

处于命令传播模式的主服务器会将执行脚本产生的所有写命令用事务包裹起来,然后将事务复制到 AOF 文件以及从服务器里面。

因为命令传播模式复制的是写命令而不是脚本本身,所以即使脚本本身包含时间、内部状态、随机函数 等,主服务器给所有从服务器复制的写命令仍然是相同的。

为了开启命令传播模式,用户在使用脚本执行任何写操作之前,需要先在脚本里面调用以下函数:

redis.replicate_commands()

redis.replicate_commands() 只对调用该函数的脚本有效:在使用命令传播模式执行完当前脚本之后, 服务器将自动切换回默认的脚本传播模式。

如果我们在主服务器执行以下命令:

eval
"redis.replicate_commands();redis.call('set',KEYS[1],ARGV[1]);redis.call('set',KEYS[2],ARGV[2])" 2 n1 n2 zhaoyun11 zhaoyun22

那么主服务器将向从服务器复制以下命令:

EXEC
*1
$5
MULTI
*3
$3
set
$2
n1
$9
zhaoyun11
*3
$3
set
$2
n2
$9
zhaoyun22
*1
$4
EXEC

3.5 管道(pipeline),事务和脚本(lua)三者的区别

三者都可以批量执行命令

管道无原子性,命令都是独立的,属于无状态的操作

事务和脚本是有原子性的,其区别在于脚本可借助Lua语言可在服务器端存储的便利性定制和简化操作

脚本的原子性要强于事务,脚本执行期间,另外的客户端其它任何脚本或者命令都无法执行,脚本的执行时间应该尽量短,不能太耗时的脚本

4. 在redis集群中使用Lua脚本

但是测试环境的redis是单机版的,而线上服务器确是集群版。导致同样的代码在线上服务器一直报错,经过测试发现集群版lua脚本的使用并不同于单机版。

command keys must in same slot

为了保持事务,同一个lua脚本访问应该访问同一个slot,但是redis集群会根据KEY进行hash并取模,因此如果采用默认hash的话,那么就会产生下面的错误。

redis集群 lua,redis,lua,redis,哈希算法

redis集群 lua,redis,lua,redis,哈希算法

点击查看Redis 官方说明

解决方案(Hash tags)

redis支持写法,可以实现对KEY的部分字符串进行hash,这样就能保证同一个lua脚本被同一个slot执行,从而保持事务的一致性。

如下图 三个key {top}_turnover_rate{top}_rank,coin_{top}_coin 会按 crc16(top) % 16384 的方式取模

redis集群 lua,redis,lua,redis,哈希算法

总结

  • redis集群版的lua脚本,可以通过key的部分字符串hash来解决
  • redis集群版的分布式是会根据KEY进行hash取模然后打到不同的slot,这种思想是典型的分而治之。分治,分流,降级。

以上是关于lua在redis集群中的解决方案-- command keys must in same slot的主要内容文章来源地址https://www.toymoban.com/news/detail-621488.html

到了这里,关于五分钟讲透 Redis Lua脚本,以及Redis cluster集群模式下的 command keys must in same slot 解决方案 redis hash tag的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Redis 主从复制 + 哨兵模式 + Cluster 集群

    redis群集有三种模式: 分别是主从同步/复制、哨兵模式、Cluster,下面会讲解一下三种模式的工作方式,以及如何搭建cluster群集 主从复制是高可用Redis的基础,哨兵和集群都是在主从复制基础上实现高可用的。主从复制主要实现了数据的多机备份,以及对于读操作的负载均衡

    2024年02月09日
    浏览(28)
  • 【Redis】三种集群模式(主从复制、哨兵模式、Cluster)

    redis有三种集群模式,其中主从是最常见的模式。Sentinel 哨兵模式是为了弥补主从复制集群中主机宕机后,主备切换的复杂性而演变出来的。哨兵顾名思义,就是用来监控的,主要作用就是监控主从集群,自动切换主备,完成集群故障转移。cluster 模式是redis官方提供的集群模

    2024年01月21日
    浏览(52)
  • redis7部署集群:包含主从模式、哨兵模式、Cluster集群模式等三种模式

    前言: redis部署集群常见的一般有三种模式:主从模式,Sentinel(哨兵模式),Redis Cluster(高可用Cluster集群),根据不同的需求可自定义选择部署方式。 Redis 主从模式(Replication) 优点: 数据备份:主节点的数据会复制到从节点,提供了数据冗余和一定程度的故障恢复能力

    2024年01月20日
    浏览(68)
  • Redis追本溯源(四)集群:主从模式、哨兵模式、cluster模式

    Redis 有多种集群搭建方式,比如,主从模式、哨兵模式、Cluster 模式。 Redis 主从模式还解决了单点的问题。Redis 主库在进行修改操作的时候,会把相应的写入命令近乎实时地同步给从库,从库回放这些命令,就可以保证自己的数据与主库保持一致。那么,当主库发生宕机的时

    2024年02月14日
    浏览(32)
  • redis高可用——主从复制、哨兵模式、cluster集群

    目录 1、redis群集有三种模式 2、主从复制 2.1、概述: 2.2、Redis主从复制有以下几个重要作用: 2.3、主从复制流程: 2.4、redis主从复制实验 3、哨兵模式. 3.1、概述: 3.2、 哨兵的核心功能: 3.3、哨兵模式原理: 3.6、 哨兵模式的作用; 3.7、故障转移机制 3.8、主节点的选举: 3.9、主

    2024年02月09日
    浏览(28)
  • Redis 7 第八讲 集群模式(cluster)架构篇

    Redis 集群架构图         Redis 集群是一个提供在多个Redis节点间共享数据的程序集;Redis集群可以支持多个master  Redis集群支持多个master,每个master又可以挂载多个slave 读写分离 支持数据的高可用 支持海量数据的读写存储操作 集群自带Sentinel的故障转移机制,内置支持高可用,

    2024年02月10日
    浏览(27)
  • Redis高可用(主从复制、哨兵模式和Cluster集群)

    目录 一、Redis高可用 1.持久化 2.主从复制 3.哨兵 4.Cluster集群 二、主从复制 1.概念 2.作用 3.主从复制流程 4.配置主从复制 三、哨兵模式 1.功能 2.作用 3.组成 4.故障转移机制 5.主节点选举依据 6.配置哨兵模式 7.故障模拟 8.恢复故障节点 四、Cluster群集 1.简介 2.作用 (1)数据分区

    2024年02月15日
    浏览(32)
  • redis — redis cluster集群模式下如何实现批量可重入锁?

    一、redis cluster 集群版 在Redis 3.0版本以后,Redis发布了Redis Cluster。该集群主要支持搞并发和海量数据处理等优势,当 Redis 在集群模式下运行时,它处理数据存储的方式与作为单个实例运行时不同。这是因为它应该准备好跨多个节点分发数据,从而实现水平可扩展性。具体能力表

    2024年01月21日
    浏览(34)
  • SpringBoot Redis 多数据源集成支持哨兵模式和Cluster集群模式

    大家都知道Redis在6.0版本之前是单线程工作的,这导致在一个项目中有大量读写操作的情况下,Redis单实例的性能被其他业务长时间占据,导致部分业务出现延迟现象,为了解决这个问题,部分公司项目选择使用多个Redis实例分别存储不同的业务数据和使用场景,比如IoT网关写

    2024年02月15日
    浏览(30)
  • lua脚本的基本语法,以及Redis中简单使用

    Lua 脚本的基本语法如下: 变量与赋值: 变量名可以是字母、数字和下划线的组合,以字母或下划线开头。Lua 是动态类型语言,无需事先声明变量类型。 控制结构: a) 条件语句: b) 循环语句: 函数定义: 函数可以有参数和返回值。 表(table): 表是 Lua 中的一种数据结构

    2024年02月04日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包