Начало работы со сценариями Redis Lua

Redis Lua

1. Введение

Redis — это высокопроизводительная база данных памяти KV.Помимо основной роли промежуточного ПО для кэширования, она имеет множество применений.Например, толстый брат поделился ранее.Вычисление информации о геолокации Redis GEO. Redis предоставляет множество команд, которые мы можем использовать для выполнения некоторых вычислений. Одна команда Redis является атомарной.Иногда мы хотим иметь возможность комбинировать несколько команд Redis, чтобы эта комбинация выполнялась атомарно и даже использовалась повторно. Разработчики Redis поняли, что этот сценарий все еще очень распространен, и представили функцию для решения этой проблемы в версии 2.6, которая заключается в выполнении Redis сценариев Lua.

2. Lua

Lua также считается древним языком, и игрокам World of Warcraft не должно быть странно, что плагин WOW использует скрипты Lua. Lua Shine широко используется в высококонкурентных онлайн-играх.

Lua широко используется в качестве встроенного скрипта в других языках, особенно в C/C++.Синтаксис простой и небольшой, а исходный код составляет всего более 200 КБ, что может быть причиной того, что Redis официально выбрал его.

Другое звездное программное обеспечение, Nginx, также поддерживает Lua, и многие полезные функции могут быть реализованы с помощью Lua.

3. Луа не сложный

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

Чтобы реализовать функцию, необходимо выучить язык, который, кажется, обескураживает людей. На самом деле, Lua несложно изучить, и в этой статье нам не нужно изучать все возможности Lua,Чтобы использовать облегченный язык Lua в Redis.这对掌握了Java这种重量级语言的你来说根本不算难事。这里胖哥只对Redis中的涉及到的基本语法说一说。

Простой синтаксис Lua

В скрипте Lua Redis я лично рекомендую вам использовать только следующие типы:

  1. nilнулевой
  2. booleanЛогическое значение
  3. numberномер
  4. stringнить
  5. tableповерхность

тип объявления

Объявленный тип очень прост, не носит тип.

--- 全局变量 
name = 'felord.cn'
--- 局部变量
local age = 18

Скрипты Redis на практике не используют глобальные переменные, локальные переменные более эффективны.

тип таблицы

Первые четыре очень легко понять, пятыйtableНужно кратко сказать, что это одновременно и массив, и аналогичный массиву в Java.HashMap(словарь), который является единственной структурой данных в Lua.

Массив не разделен на конкретные типы, а демонстрационные данные следующие.

Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
> arr_table = {'felord.cn','Felordcn',1}
> print(arr_table[1])
felord.cn
> print(arr_table[3])
1
> print(#arr_table)
3

как словарь:

Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
> arr_table = {name = 'felord.cn', age = 18}
> print(arr_table['name'])
felord.cn
> print(arr_table.name)
felord.cn
> print(arr_table[1])
nil
> print(arr_table['age'])
18
> print(#arr_table)
0

Режим смешивания:

Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
> arr_table = {'felord.cn','Felordcn',1,age = 18,nil}
> print(arr_table[1])
felord.cn
> print(arr_table[4])
nil
> print(arr_table['age'])
18
> print(#arr_table)
3

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

судить

Суждение очень просто, формат:

local a = 10
if a < 10  then
	print('a小于10')
elseif a < 20 then
	print('a小于20,大于等于10')
else
	print('a大于等于20')
end

цикл массива

local arr = {1,2,name='felord.cn'}

for i, v in ipairs(arr) do
    print('i = '..i)
    print('v = '.. v)
end

print('-------------------')

for i, v in pairs(arr) do
    print('p i = '..i)
    print('p v = '.. v)
end

распечатать результат:

i = 1
v = 1
i = 2
v = 2
-----------------------
p i = 1
p v = 1
p i = 2
p v = 2
p i = name
p v = felord.cn

возвращаемое значение

Как и Python, Lua также может возвращать несколько значений. Однако не рекомендуется использовать эту функцию в Lua-скриптах Redis.Если у вас есть это требование, инкапсулируйте его в виде структуры массива. Правила возвращаемого значения, которые поддерживают сценарии в Spring Data Redis, можно проанализировать здесь:

public static ReturnType fromJavaType(@Nullable Class<?> javaType) {

   if (javaType == null) {
      return ReturnType.STATUS;
   }
   if (javaType.isAssignableFrom(List.class)) {
      return ReturnType.MULTI;
   }
   if (javaType.isAssignableFrom(Boolean.class)) {
      return ReturnType.BOOLEAN;
   }
   if (javaType.isAssignableFrom(Long.class)) {
      return ReturnType.INTEGER;
   }
   return ReturnType.VALUE;
}

Толстый брат будет использовать на практикеList,Boolean,LongВ-третьих, чтобы избежать появления мотыльков.

На данный момент очки знаний, необходимые для сценариев Redis Lua, завершены, и другие функции, сопрограммы и другие функции не должны появляться в сценариях Redis Lua.Если вы используете встроенные функции, просто выполните поиск и запрос.

Когда вы вступаете в контакт с новой технологией, вы должны использовать ее обычным образом.Если вы хотите играть, это означает более высокую стоимость обучения.

4. Луа в Redis

Далее идет фактическая работа скрипта Redis Lua.

ОЦЕНКА команда

Используется в RedisEVALкоманда для прямого выполнения указанного Lua-скрипта.

EVAL luascript numkeys key [key ...] arg [arg ...]
  • EVALКлючевое слово для команды.
  • luascriptЛуа скрипт.
  • numkeysКоличество ключей, которое необходимо обработать указанному Lua-скрипту, что на самом делеkeyДлина массива.
  • keyПередайте к Lua скрипт ноль или более ключей, разделенные пробелами, проходят в скрипте LUAKEYS[INDEX]Для получения соответствующего значения, в котором1 <= INDEX <= numkeys.
  • argноль или более дополнительных аргументов, передаваемых сценарию, разделенных пробелами, в сценариях Lua черезARGV[INDEX]чтобы получить соответствующее значение, где1 <= INDEX <= numkeys.

Далее я просто продемонстрирую получение ключаhelloСтоит простой скрипт:

127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> get hello
"world"
127.0.0.1:6379> EVAL "return redis.call('GET',KEYS[1])" 1 hello
"world"
127.0.0.1:6379> EVAL "return redis.call('GET','hello')"
(error) ERR wrong number of arguments for 'eval' command
127.0.0.1:6379> EVAL "return redis.call('GET','hello')" 0
"world"

Обнаружено из демо-кода выше,KEYS[1]Можно заменить напрямуюhello,Однако в официальной документации Redis указано, что это не рекомендуется, цель состоит в том, чтобы проанализировать команду до ее выполнения, чтобы убедиться, что Redis Cluster может перенаправить команду на соответствующий узел кластера..

numkeysОбязательный параметр команды во всех случаях.

функция вызова и функция pcall

В приведенном выше примере мы передаемredis.call()выполнитьSETкоманду, на самом деле, мы также можем заменить ее наredis.pcall(). Единственная разница между ними заключается в способе обработки ошибок: первый возвращает ошибку непосредственно вызывающей стороне при выполнении команды error, а второй оборачивает ошибку как ошибку, как мы упоминали выше.tableлист:

127.0.0.1:6379> EVAL "return redis.call('no_command')" 0
(error) ERR Error running script (call to f_1e6efd00ab50dd564a9f13e5775e27b966c2141e): @user_script:1: @user_script: 1: Unknown Redis command called from Lua script
127.0.0.1:6379> EVAL "return redis.pcall('no_command')" 0
(error) @user_script: 1: Unknown Redis command called from Lua script

Это похоже на то, как когда Java сталкивается с исключением, первая выдает исключение напрямую, а вторая обрабатывает исключение как JSON и возвращает его.

преобразование стоимости

Поскольку в Redis есть две разные операционные среды, Redis и Lua, при передаче данных Redis и Lua должны выполняться соответствующие операции преобразования, которые на практике нельзя игнорировать. Например, если Lua-скрипт возвращает Redis десятичное число, он теряет десятичную точность и его можно безопасно преобразовать в строку.

127.0.0.1:6379> EVAL "return 3.14" 0
(integer) 3
127.0.0.1:6379> EVAL "return tostring(3.14)" 0
"3.14"

По опыту Pange передать строку, целое число, безопасно,Другие требуют, чтобы вы внимательно изучили официальную документацию и выполнили фактическую проверку..

Атомное исполнение

Скрипты Lua выполняются атомарно в Redis и выполняются на сервере Redis.EVALКогда приказали,До того, как команда будет выполнена и результат будет возвращен вызывающей стороне, будет выполнена только вся логика, содержащаяся в Lua-скрипте, указанном текущей командой, а команды, отправленные другими клиентами, будут заблокированы.,до того какEVALпока команда не будет выполнена. Поэтому не рекомендуется писать какую-то слишком сложную логику в LUA-скрипте, а работоспособность Lua-скрипта должна быть максимально обеспечена, иначе это повлияет на других клиентов.

Управление скриптами

SCRIPT LOAD

Загружайте скрипты в кеш для многократного использования, не тратьте пропускную способность на многократную загрузку, и каждый скрипт будет возвращать уникальный строковый идентификатор через проверку SHA. нужно сотрудничатьEVALSHAкоманда для выполнения кэшированного скрипта.

127.0.0.1:6379> SCRIPT LOAD "return 'hello'"
"1b936e3fe509bcbc9cd0664897bbe8fd0cac101b"
127.0.0.1:6379> EVALSHA 1b936e3fe509bcbc9cd0664897bbe8fd0cac101b 0
"hello"

SCRIPT FLUSH

Раз есть кеш, то есть и очистка кеша, но, к сожалению, кеш скриптов не удаляется по SHA, а очищаются все кеши скриптов, поэтому эта команда в продакшене вообще не используется.

SCRIPT EXISTS

Проверьте наличие одного или нескольких кэшей с идентификатором SHA в качестве параметра.

127.0.0.1:6379> SCRIPT EXISTS 1b936e3fe509bcbc9cd0664897bbe8fd0cac101b  1b936e3fe509bcbc9cd0664897bbe8fd0cac1012
1) (integer) 1
2) (integer) 0

SCRIPT KILL

Завершить исполнительный скрипт.Но для того, чтобы команда целостность этих данных не гарантирует, что это будет успешно завершено. Эта команда не работает, если сценарий выполняет часть написанной логики и должен быть завершен. нужно выполнитьSHUTDOWN nosaveЗавершите работу сервера без сохранения данных для завершения сценария завершения.

некоторые другие моменты

Знание вышеперечисленных знаний в основном достаточно для разработки некоторых простых Lua-скриптов. Но есть еще несколько важных моментов в фактическом развитии.

  • Обязательно полностью протестируйте Lua-скрипт, чтобы убедиться в надежности его логики.Когда Lua-скрипт сталкивается с исключением, выполняемая логика не будет откатываться.
  • Старайтесь не использовать случайные функции, предоставляемые Lua, см. соответствующие официальные документы.
  • Не пишите на Lua-скриптахfunctionДля функций весь скрипт действует как тело функции.
  • Используются все переменные, объявленные в скрипте.localключевые слова.
  • Используйте сценарии Lua в кластере, чтобы убедиться, что все логическиеkeyВыделенные на той же машине, то есть в одном слоте, вы можете использоватьRedis Hash TagТехнологии.
  • Опять же, Lua-скрипты не должны содержать чрезмерно трудоемкую и слишком сложную логику.

5. Резюме

В этой статье дается подробное объяснение и демонстрация сценария сценария Redis Lua и синтаксиса программирования Lua, необходимого для сценария Redis Lua, а также приводятся некоторые моменты, на которые необходимо обратить внимание при фактической разработке сценария Redis Lua. Надеюсь, это поможет вам освоить эту технику. На сегодня это все, в следующий раз я расскажу, как использовать Lua-скрипты в реальной разработке Redis, так что эта статья должна быть освоена. Уделять больше внимания:Код Фермер Маленький Толстый БратПолучите больше знаний о программировании галантереи.

关注公众号:Felordcn获取更多资讯

Личный блог: https://felord.cn