Введение
В этой лабораторной работе вы изучите Redis Lua Scripting, сосредоточившись на выполнении Lua-скриптов непосредственно в Redis для эффективного выполнения сложных операций. Эта лабораторная работа охватывает использование команды EVAL для выполнения скриптов, передачу аргументов скриптам, загрузку скриптов с помощью SCRIPT LOAD и запуск загруженных скриптов с помощью EVALSHA.
Мы начнем с выполнения простого Lua-скрипта, который увеличивает счетчик Redis с помощью EVAL, демонстрируя, как указать скрипт, количество ключей, к которым он обращается, и имена ключей. Затем мы узнаем, как загружать скрипты в Redis и выполнять их, используя их SHA1-хеш, что повышает производительность, избегая повторной передачи скрипта.
Выполнение Lua-скрипта с помощью EVAL
В этом шаге мы рассмотрим, как выполнять Lua-скрипты непосредственно в Redis с помощью команды EVAL. Это позволяет выполнять сложные операции с вашими данными в одном запросе, снижая задержку сети и повышая производительность.
Прежде чем мы начнем, давайте разберемся с основами EVAL. Команда EVAL принимает два основных аргумента:
- Сам Lua-скрипт в виде строки.
- Количество ключей, к которым скрипт будет обращаться, за которым следуют фактические имена ключей и любые дополнительные аргументы, которые вы хотите передать скрипту.
Вот простой пример для начала. Мы создадим Lua-скрипт, который увеличивает счетчик Redis и возвращает новое значение.
Откройте свой терминал и подключитесь к серверу Redis, используя интерфейс командной строки Redis (
redis-cli).redis-cliТеперь давайте выполним Lua-скрипт с помощью
EVAL. Этот скрипт увеличит счетчик с именемmycounterи вернет увеличенное значение.EVAL "local current = redis.call('INCR', KEYS[1]); return current" 1 mycounterДавайте разберем эту команду:
EVAL "local current = redis.call('INCR', KEYS[1]); return current": Это сам Lua-скрипт. Он используетredis.call('INCR', KEYS[1])для увеличения значения ключа, указанного вKEYS[1]. МассивKEYSсодержит имена ключей, переданные скрипту. Наконец, он возвращает увеличенное значение.1: Это указывает, что скрипт будет обращаться к одному ключу.mycounter: Это имя ключа, к которому будет обращаться скрипт.
Вы должны увидеть вывод, подобный этому:
(integer) 1Если вы запустите ту же команду снова, вы увидите увеличение счетчика:
EVAL "local current = redis.call('INCR', KEYS[1]); return current" 1 mycounterВывод:
(integer) 2Давайте проверим значение ключа
mycounterс помощью командыGET:GET mycounterВывод:
"2"Как видите, Lua-скрипт успешно увеличил счетчик.
Теперь давайте попробуем другой пример. На этот раз мы создадим скрипт, который устанавливает ключ в определенное значение, если он еще не существует.
EVAL "if redis.call('EXISTS', KEYS[1]) == 0 then redis.call('SET', KEYS[1], ARGV[1]); return 1 else return 0 end" 1 mykey myvalueВ этой команде:
EVAL "if redis.call('EXISTS', KEYS[1]) == 0 then redis.call('SET', KEYS[1], ARGV[1]); return 1 else return 0 end": Это Lua-скрипт. Он проверяет, существует ли ключKEYS[1]. Если нет, он устанавливает ключ в значениеARGV[1]и возвращает1. В противном случае он возвращает0.1: Это указывает, что скрипт будет обращаться к одному ключу.mykey: Это имя ключа.myvalue: Это значение, которое нужно установить, если ключ не существует.
Вы должны увидеть вывод, подобный этому:
(integer) 1Это указывает на то, что ключ
mykeyбыл установлен вmyvalue.Давайте проверим значение
mykey:GET mykeyВывод:
"myvalue"Если вы запустите команду
EVALснова:EVAL "if redis.call('EXISTS', KEYS[1]) == 0 then redis.call('SET', KEYS[1], ARGV[1]); return 1 else return 0 end" 1 mykey myvalueВывод:
(integer) 0На этот раз скрипт вернул
0, потому что ключ уже существовал.Выйдите из
redis-cli. Это важно для регистрации изменений.exit
Передача аргументов в скрипт с помощью EVAL
На предыдущем шаге мы узнали, как выполнять Lua-скрипты с помощью EVAL и получать доступ к ключам. Теперь давайте рассмотрим, как передавать аргументы этим скриптам. Это позволяет создавать более динамичные и многократно используемые скрипты.
Напомним, что команда EVAL принимает следующие аргументы:
- Сам Lua-скрипт в виде строки.
- Количество ключей, к которым скрипт будет обращаться.
- Имена ключей.
- Любые дополнительные аргументы, которые вы хотите передать скрипту. Эти аргументы доступны в Lua-скрипте с помощью массива
ARGV.
Начнем с примера. Мы создадим Lua-скрипт, который добавляет значение к счетчику Redis. Ключ счетчика и значение для добавления будут переданы в качестве аргументов.
Подключитесь к серверу Redis, используя интерфейс командной строки Redis (
redis-cli).redis-cliТеперь давайте выполним Lua-скрипт с помощью
EVAL, который увеличивает счетчик на указанную величину.EVAL "local current = redis.call('INCRBY', KEYS[1], ARGV[1]); return current" 1 mycounter 5Давайте разберем эту команду:
EVAL "local current = redis.call('INCRBY', KEYS[1], ARGV[1]); return current": Это Lua-скрипт. Он используетredis.call('INCRBY', KEYS[1], ARGV[1])для увеличения значения ключа, указанного вKEYS[1], на величину, указанную вARGV[1].1: Это указывает, что скрипт будет обращаться к одному ключу.mycounter: Это имя ключа, к которому будет обращаться скрипт.5: Это аргумент, который будет передан скрипту и доступен какARGV[1].
Вы должны увидеть вывод, подобный этому (предполагая, что
mycounterбыл равен 2 из предыдущего шага):(integer) 7Скрипт увеличил ключ
mycounterна 5.Давайте проверим значение ключа
mycounterс помощью командыGET:GET mycounterВывод:
"7"Теперь давайте попробуем другой пример со строковыми аргументами. Мы создадим скрипт, который устанавливает ключ в значение, где и ключ, и значение передаются в качестве аргументов.
EVAL "redis.call('SET', KEYS[1], ARGV[1]); return ARGV[1]" 1 mynewkey mynewvalueВ этой команде:
EVAL "redis.call('SET', KEYS[1], ARGV[1]); return ARGV[1]": Это Lua-скрипт. Он устанавливает ключKEYS[1]в значениеARGV[1]и возвращает значение.1: Это указывает, что скрипт будет обращаться к одному ключу.mynewkey: Это имя ключа.mynewvalue: Это значение для установки.
Вы должны увидеть вывод, подобный этому:
"mynewvalue"Давайте проверим значение
mynewkey:GET mynewkeyВывод:
"mynewvalue"Скрипт успешно установил ключ
mynewkeyв значениеmynewvalue.Вы можете передавать несколько аргументов скрипту. Например, давайте создадим скрипт, который объединяет две строки, переданные в качестве аргументов, и устанавливает результат в ключ.
EVAL "local result = ARGV[1] .. ARGV[2]; redis.call('SET', KEYS[1], result); return result" 1 combinedkey hello worldВ этой команде:
EVAL "local result = ARGV[1] .. ARGV[2]; redis.call('SET', KEYS[1], result); return result": Это Lua-скрипт. Он объединяетARGV[1]иARGV[2]с помощью оператора.., устанавливает ключKEYS[1]в результат и возвращает результат.1: Это указывает, что скрипт будет обращаться к одному ключу.combinedkey: Это имя ключа.hello: Это первый строковый аргумент.world: Это второй строковый аргумент.
Вы должны увидеть вывод, подобный этому:
"helloworld"Давайте проверим значение
combinedkey:GET combinedkeyВывод:
"helloworld"Выйдите из
redis-cli. Это важно для регистрации изменений.exit
Загрузка скрипта с помощью SCRIPT LOAD
На предыдущих шагах мы выполняли Lua-скрипты непосредственно с помощью команды EVAL. Хотя это полезно для простых скриптов, это может стать обременительным для более крупных и сложных скриптов. Redis предоставляет команду SCRIPT LOAD для загрузки скриптов в кеш скриптов (script cache) сервера Redis. Это позволяет выполнять скрипт несколько раз без необходимости каждый раз отправлять весь скрипт, что повышает производительность.
Команда SCRIPT LOAD принимает один аргумент: сам Lua-скрипт. Она возвращает SHA1-хеш скрипта, который затем можно использовать для выполнения скрипта с помощью команды EVALSHA (которую мы рассмотрим на следующем шаге).
Давайте посмотрим, как это работает.
Подключитесь к серверу Redis, используя интерфейс командной строки Redis (
redis-cli).redis-cliТеперь давайте загрузим Lua-скрипт с помощью
SCRIPT LOAD. Мы будем использовать тот же скрипт из предыдущего шага, который увеличивает счетчик на указанную величину.SCRIPT LOAD "local current = redis.call('INCRBY', KEYS[1], ARGV[1]); return current"Эта команда загрузит скрипт в кеш скриптов сервера Redis и вернет SHA1-хеш скрипта. Вы должны увидеть вывод, подобный этому:
"6b1e8dd2999cb08546e74339c0c9489f9f89a84b"Это SHA1-хеш скрипта. Запишите этот хеш, так как он понадобится вам на следующем шаге. Точное значение хеша может отличаться.
Теперь давайте загрузим скрипт, который устанавливает ключ в значение, где и ключ, и значение передаются в качестве аргументов.
SCRIPT LOAD "redis.call('SET', KEYS[1], ARGV[1]); return ARGV[1]"Вы должны увидеть вывод, подобный этому:
"a8b2b3648969459a8198262a9166e945e890987c"Опять же, запишите этот хеш.
Давайте загрузим скрипт, который объединяет две строки, переданные в качестве аргументов, и устанавливает результат в ключ.
SCRIPT LOAD "local result = ARGV[1] .. ARGV[2]; redis.call('SET', KEYS[1], result); return result"Вы должны увидеть вывод, подобный этому:
"d2a800a974ca96849295220424f9a0664a495345"Запишите и этот хеш.
Вы можете проверить, загружены ли скрипты, с помощью команды
SCRIPT EXISTS. Эта команда принимает один или несколько SHA1-хешей в качестве аргументов и возвращает массив из 0 и 1, где 1 указывает, что скрипт с соответствующим хешем загружен, а 0 указывает, что он не загружен.Например, чтобы проверить, загружен ли первый скрипт, который мы загрузили, используйте следующую команду, заменив хеш на тот, который вы получили на шаге 2:
SCRIPT EXISTS 6b1e8dd2999cb08546e74339c0c9489f9f89a84bВывод:
1) (integer) 1Это указывает на то, что скрипт загружен.
Если вы попытаетесь проверить скрипт, который не загружен:
SCRIPT EXISTS 0000000000000000000000000000000000000000Вывод:
1) (integer) 0Это указывает на то, что скрипт не загружен.
Выйдите из
redis-cli. Это важно для регистрации изменений.exit
Запуск загруженного скрипта с помощью EVALSHA
На предыдущем шаге мы узнали, как загружать Lua-скрипты в кеш скриптов (script cache) сервера Redis с помощью команды SCRIPT LOAD. Теперь мы узнаем, как выполнять эти загруженные скрипты с помощью команды EVALSHA.
Команда EVALSHA принимает следующие аргументы:
- SHA1-хеш загруженного скрипта.
- Количество ключей, к которым скрипт будет обращаться.
- Имена ключей.
- Любые дополнительные аргументы, которые вы хотите передать скрипту.
Использование EVALSHA более эффективно, чем EVAL, когда вам нужно выполнить один и тот же скрипт несколько раз, поскольку это позволяет избежать отправки всего скрипта на сервер каждый раз.
Давайте посмотрим, как это работает.
Подключитесь к серверу Redis, используя интерфейс командной строки Redis (
redis-cli).redis-cliТеперь давайте выполним Lua-скрипт, который увеличивает счетчик на указанную величину, используя
EVALSHA. Помните SHA1-хеш, который вы получили на предыдущем шаге для скриптаlocal current = redis.call('INCRBY', KEYS[1], ARGV[1]); return current? Если нет, вам нужно будет снова загрузить скрипт с помощьюSCRIPT LOAD. Для этого примера мы будем считать, что хеш равен6b1e8dd2999cb08546e74339c0c9489f9f89a84b.EVALSHA 6b1e8dd2999cb08546e74339c0c9489f9f89a84b 1 mycounter 5Давайте разберем эту команду:
EVALSHA 6b1e8dd2999cb08546e74339c0c9489f9f89a84b: Это указывает, что мы хотим выполнить скрипт с SHA1-хешем6b1e8dd2999cb08546e74339c0c9489f9f89a84b.1: Это указывает, что скрипт будет обращаться к одному ключу.mycounter: Это имя ключа, к которому будет обращаться скрипт.5: Это аргумент, который будет передан скрипту и доступен какARGV[1].
Вы должны увидеть вывод, подобный этому (предполагая, что
mycounterбыл равен 7 из предыдущего шага):(integer) 12Скрипт увеличил ключ
mycounterна 5.Давайте проверим значение ключа
mycounterс помощью командыGET:GET mycounterВывод:
"12"Теперь давайте выполним скрипт, который устанавливает ключ в значение, используя
EVALSHA. Помните SHA1-хеш, который вы получили на предыдущем шаге для скриптаredis.call('SET', KEYS[1], ARGV[1]); return ARGV[1]? Если нет, вам нужно будет снова загрузить скрипт с помощьюSCRIPT LOAD. Для этого примера мы будем считать, что хеш равенa8b2b3648969459a8198262a9166e945e890987c.EVALSHA a8b2b3648969459a8198262a9166e945e890987c 1 anotherkey anothervalueВы должны увидеть вывод, подобный этому:
"anothervalue"Давайте проверим значение
anotherkey:GET anotherkeyВывод:
"anothervalue"Если вы попытаетесь выполнить скрипт с недействительным SHA1-хешем, вы получите ошибку:
EVALSHA 0000000000000000000000000000000000000000 1 mykey myvalueВывод:
(error) NOSCRIPT No matching script. Please use EVAL.Это указывает на то, что скрипт с указанным SHA1-хешем не загружен.
Выйдите из
redis-cli. Это важно для регистрации изменений.exit
Резюме
В этой лабораторной работе вы изучили скриптинг Lua в Redis, сосредоточившись на выполнении скриптов непосредственно с помощью команды EVAL. Мы узнали, что EVAL принимает Lua-скрипт в виде строки, количество ключей, к которым осуществляется доступ, и сами имена ключей в качестве аргументов. Мы попрактиковались в увеличении счетчика Redis с помощью Lua-скрипта внутри EVAL, наблюдая, как скрипт получает доступ и изменяет указанный ключ.
Кроме того, мы узнали, как передавать аргументы в Lua-скрипты, загружать скрипты в Redis с помощью SCRIPT LOAD и выполнять загруженные скрипты с помощью EVALSHA. Не забывайте выходить из redis-cli после каждого шага, чтобы ваши команды регистрировались правильно. Это обеспечивает более эффективное выполнение сложных скриптов.


