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

#java #spring-boot #redis #redis-cluster

#java #весенняя загрузка #redis #redis-cluster

Вопрос:

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

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

сценарий lua, подобный этому:

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

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

КОД JAVA:

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

Я установил ключ hash tag in 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
 

Благодарен за любую помощь.

Ответ №1:

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

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

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

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

 {
    "demoKey_1:{demoKey}":"value1",
    "demoKey_2:{demoKey}":"value2",
    "demoKey_3:{demoKey}":"value3"
}
 

Комментарии:

1. Это работает нормально. Есть еще один вопрос. Данные будут кэшироваться в одном и том же слоте, если все эти ведущие и ведомые сервера redis завершат работу, могу ли я запросить данные еще?

2. Если все экземпляры redis завершены, вы не сможете получить доступ к данным.

3. Да, это так. Я имею в виду, что все экземпляры redis, хранящие {demoKey} данные, завершают работу. Пометка ключа означает, что все ключи будут принадлежать одному экземпляру redis, что, если этот экземпляр redis, включая master и slave, отключен, могу ли я получить доступ {demoKey} к данным?

4. Даже если вы не пометите, если узлы, имеющие слоты, не работают, ничего не вернут. Вот почему мы используем локальный кэш в некоторых случаях, чтобы мы могли терпеть сбой в течение нескольких миллисекунд. Redis автоматически начнет перераспределять слоты ключей, поэтому потенциально может случиться так, что слот ключа может быть назначен какому-либо другому новому избранному мастеру.