专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

Redisson lua脚本踩坑-序列化

Redisson lua

Redis支持使用lua脚本来执行原子操作,Redisson中也提供了RScript接口,用于执行lua脚本,并提供了实现类RedissonScript。

1. API举例:

RedissonScript.eval(Mode mode, String luaScript, ReturnType returnType, List keys, Object… values); 在lua脚本中可以用KEYS、ARGV数组(两个数组下标均从1开始)来接收keys和values,需要注意的是value会进行序列化(并不是RScript的ARGV如此,redisson在存储时,都会对value进行序列化)。

2. redisson序列化特性

假设有一个hash结构,key是room,field是roomId,value是Long型的{roomId}。那么通过redisson API写入可以观察到redis中的field和value结构分别如下图所示:

89_1.png

特别强调的是,图中的首尾的双引号字符以及反斜杠,在实际的field和value中并不存在,这只是通过redis cli查询时显示效果。

实际上redis中的field是:

"roomId"

value是:

["java.lang.Long",123456]

中括号[]中两个值分别表示value的类型和取值

3. 脚本示例

示例1:(1)在lua中使用KEYS和ARGV数组,(2)在lua中构造序列化的value

  • redisson只有key没有做序列化,各种数据结构中field、value都进行了序列化。

如下代码展示了使用lua脚本写和读hash结构。key是roomId,field是roomId(实际存储的是”roomId”),value是123456(实际存储的是[”java.lang.Long”,123456])。

@Test
public void testLuaScript() {
    RedissonClient redissonClient = redissonService.redissonClient();
    RScript rScript = redissonClient.getScript();
    Long roomId = 123456L;
   String hsetRoomId = "redis.call('HSET', KEYS[1], ARGV[1], ARGV[2]);" +
                "return redis.call('HGET', KEYS[1], '\"roomId\"');";
    Long result = rScript.eval(RScript.Mode.READ_WRITE, hsetRoomId, RScript.ReturnType.INTEGER,
            Lists.newArrayList("room"),
            Lists.newArrayList("roomId", roomId).toArray());
    Assert.assertTrue(roomId.equals(result));
}

第一行lua脚本,使用ARGV[1]作为field进行写入,第二行使用lua字符串作为field进行读取,结果验证了lua会在存储时进行序列化特性。

  • 需要注意的是第二行lua脚本多写了反斜杠是为了转义。

示例2:在lua中处理获得的value

lua脚本中获取到序列化的value,并进行处理。 由于我不擅长lua脚本,也不清楚在redisson中 lua是否可以使用一些json库,所以简单的使用lua的字符串API进行处理。处理代码示例:

local roomId = string.sub(roomIdJson, string.find(roomIdJson, ',') + 1, string.len(roomIdJson) - 1);

测试代码:

@Test
public void testLuaScript2() {
    Long roomId = 123456L;

    // 准备数据结构:(1)存储roomId,key为room, field为roomId, value为123456
    // (2)存储123456房间中用户列表,key为roomId.123456, value为字符串数组对象
    redisService.hsetWithThrow("room", "roomId", roomId, true);
    redisService.setWithThrow("roomId.123456", Lists.newArrayList("Jack", "Rose"));

    RedissonClient redissonClient = redissonService.redissonClient();
    RScript rScript = redissonClient.getScript();
    String getRoomUserList =
            // roomIdJson = ["java.lang.Long",123456]
            "local roomIdJson = redis.call('HGET', KEYS[1], '\"roomId\"'); " +
            "local roomId = " +
            "       string.sub(roomIdJson, string.find(roomIdJson, ',') + 1, string.len(roomIdJson) - 1); " +
            "return redis.call('GET', 'roomId' .. '.' .. roomId); ";
    ArrayList result = rScript.eval(RScript.Mode.READ_WRITE, getRoomUserList, RScript.ReturnType.VALUE,
            Lists.newArrayList("room"),
            new Object[0]);
    Assert.assertTrue(result.contains("Jack"));
}

文章永久链接:https://tech.souyunku.com/36714

未经允许不得转载:搜云库技术团队 » Redisson lua脚本踩坑-序列化

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们