Кэшировать данные с помощью lua-скрипта, но получить RedisCommandExecutionException с доступом к нелокальному ключу в узле кластера

У меня есть данные карты для кэширования в кластере Redis с использованием сценария lua в проекте Springboot, например:

{
    "demoKey:{1}":"value1",
    "demoKey:{2}":"value2",
    "demoKey:{3}":"value3"
}

луа-скрипт такой:

local addMap = cjson.decode(ARGV[1]);

for fieldKey, fieldValue in pairs(addMap) do
    redis.call("SET", fieldKey, fieldValue);
end

ЯВА-КОД:

final DefaultRedisScript<?> redisScript = new DefaultRedisScript<>();
redisScript.setScriptSource(LUA_SCRIPT);
redisClient.execute(redisScript, new ArrayList<>(), JsonUtil.toString(addMap));

Я установил ключ hash tag в Redis, но все равно получаю исключение при запуске программы.

org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR Error running script (call to f_7cce57ffe5b0b94fa78680955c993e808ffa5f16):
 @user_script:7: @user_script: 7: Lua script attempted to access a non local key in a cluster node

Признателен за любую помощь.


person Holinc    schedule 15.01.2021    source источник


Ответы (1)


Сценарий LUA не позволяет нам получить доступ к ключам, которые не находятся на той же машине Redis, где запущен сценарий LUA.

Одним из решений является пометка KEYS, чтобы она попала на правильный узел Redis, пометка ключа означает, что все ключи будут принадлежать одному и тому же экземпляру Redis.

Кажется, вы сделали теги, используя {1}, {2} и {3}, но все они потенциально могут хэшироваться в другой экземпляр Redis, что приводит к ошибке. Ваш тег должен быть таким же, например, вы можете использовать userId, recordId и т. д. в качестве тега.

Для вашего примера, если вы можете изменить свою карту ниже, она должна работать нормально.

{
    "demoKey_1:{demoKey}":"value1",
    "demoKey_2:{demoKey}":"value2",
    "demoKey_3:{demoKey}":"value3"
}
person sonus21    schedule 16.01.2021
comment
Это работает нормально. Есть еще вопрос. Все данные будут кэшироваться в одном и том же слоте, если весь этот главный и подчиненный сервер redis отключится, могу ли я больше запрашивать данные? - person Holinc; 18.01.2021
comment
Если все экземпляры Redis отключены, вы не можете получить доступ к данным. - person sonus21; 18.01.2021
comment
Да, это так. Я имею в виду, что все экземпляры Redis, хранящие {demoKey} данные, отключены. Пометка ключа означает, что все ключи будут принадлежать одному и тому же экземпляру Redis. Что, если этот экземпляр Redis, включая главный и подчиненный, отключен, могу ли я получить доступ к данным {demoKey}? - person Holinc; 18.01.2021
comment
Даже если вы не пометите, если узлы, имеющие слоты, не работают, ничего не вернут. Вот почему в некоторых случаях мы используем локальный кеш, чтобы можно было допустить сбой в несколько миллисекунд. Redis автоматически начнет перераспределять слоты ключей, поэтому потенциально может произойти то, что слот ключа может быть назначен какому-то другому новому выбранному мастеру. - person sonus21; 18.01.2021