Computer >> 컴퓨터 >  >> 프로그래밍 >> Redis

마스터 Redis Lua 스크립팅:성능 향상을 위한 실용 가이드

마스터 Redis Lua 스크립팅:성능 향상을 위한 실용 가이드

안드레이 체르니코프 저

Redis는 프로세스 간 통신 및 데이터 저장에 사용되는 널리 사용되는 인 메모리 그리드입니다. Lua 스크립트를 실행할 수 있다는 말을 들어보셨겠지만, 아직 그 이유를 잘 모르겠습니다. 당신도 이에 해당한다면 계속 읽어보세요.

마스터 Redis Lua 스크립팅:성능 향상을 위한 실용 가이드

전제조건

이 가이드를 따르려면 시스템에 Redis가 설치되어 있어야 합니다. 읽는 동안 Redis 명령 참조를 확인하는 것이 도움이 될 수 있습니다.

Lua 스크립트가 왜 필요한가요?

한마디로 성능 향상입니다. Redis에서 수행하는 대부분의 작업에는 여러 단계가 포함됩니다. 애플리케이션 언어로 이러한 단계를 수행하는 대신 Lua를 사용하여 Redis 내에서 수행할 수 있습니다.

  • 이렇게 하면 성능이 향상될 수 있습니다.
  • 또한 스크립트 내의 모든 단계는 원자적인 방식으로 실행됩니다. 스크립트가 실행되는 동안에는 다른 Redis 명령을 실행할 수 없습니다.

예를 들어 Lua 스크립트를 사용하여 Redis에 저장된 JSON 문자열을 변경합니다. 이 기사의 마지막 부분에서 이에 대해 자세히 설명하겠습니다.

그런데 저는 Lua를 전혀 모릅니다

마스터 Redis Lua 스크립팅:성능 향상을 위한 실용 가이드 루아를 전혀 모르는 사람

걱정하지 마세요. Lua는 이해하기 어렵지 않습니다. C 계열의 언어를 알고 있다면 Lua를 사용해도 괜찮을 것입니다. 또한 이 기사에서는 실제 사례를 제공하고 있습니다.

예를 보여주세요

redis-cli를 통해 스크립트를 실행해 보겠습니다. . 다음으로 시작하세요:

redis-cli

이제 다음 명령을 실행하세요:

eval “redis.call(‘set’, KEYS[1], ARGV[1])” 1 key:name value

EVAL 명령은 Redis에게 다음에 나오는 스크립트를 실행하도록 지시하는 것입니다. ”redis.call(‘set’, KEYS[1], ARGV[1])” string은 Redis의 set과 기능적으로 동일한 스크립트입니다. 명령. 스크립트 텍스트 뒤에는 세 개의 매개변수가 있습니다:

  1. 제공된 키 개수
  2. 키 이름
  3. 첫 번째 인수

스크립트 인수는 KEYS라는 두 그룹으로 나뉩니다. 및 ARGV .

스크립트에 바로 뒤에 오는 숫자를 사용하여 필요한 키 수를 지정합니다. 이 예에서는 1입니다. . 이 번호 바로 뒤에 이러한 키를 차례로 제공해야 합니다. KEYS로 액세스할 수 있습니다. 스크립트 내의 테이블. 우리의 경우에는 단일 값 key:name가 포함되어 있습니다. 색인 1 .

Lua 색인 테이블은 index로 시작한다는 점에 유의하세요 1, 아닙니다 0 .

키 뒤에 인수를 얼마든지 제공할 수 있으며, 이는 Lua에서 ARGV로 사용할 수 있습니다. 테이블. 이 예에서는 단일 ARGV를 제공합니다. -인수:문자열 value . 이미 추측한 대로 위 명령은 key:name 키를 설정합니다. 값 value .

스크립트가 KEYS로 사용하는 키를 제공하는 것이 좋습니다. , 기타 모든 인수는 ARGV . 따라서 KEYS를 지정하면 안 됩니다. 0으로 설정한 다음 ARGV 내에 모든 키를 제공하세요. 테이블.

이제 스크립트가 성공적으로 완료되었는지 확인해 보겠습니다. Redis에서 키를 가져오는 다른 스크립트를 실행하여 이 작업을 수행하겠습니다.

eval "return redis.call('get', KEYS[1])" 1 키:이름

출력은 ”value”여야 합니다. , 이는 이전 스크립트가 “key:name” 키를 성공적으로 설정했음을 의미합니다. .

스크립트를 설명해 주실 수 있나요?

마스터 Redis Lua 스크립팅:성능 향상을 위한 실용 가이드 위 스크립트를 보고 총독

첫 번째 스크립트는 redis.call라는 단일 문으로 구성됩니다. 기능:

redis.call(‘set’, KEYS[1], ARGV[1])

redis.call 사용 Redis 명령을 실행할 수 있습니다. 첫 번째 인수는 이 명령의 이름이고 그 뒤에 해당 매개변수가 옵니다. set의 경우 명령에서 이 인수는 핵심입니다. 및 가치 . 모든 Redis 명령이 지원됩니다. 문서에 따르면:

Redis는 동일한 Lua 인터프리터를 사용하여 모든 명령을 실행합니다

두 번째 스크립트는 단일 명령을 실행하는 것 이상의 기능을 수행하며 값도 반환합니다:

eval “return redis.call(‘get’, KEYS[1])” 1 key:name

스크립트에서 반환된 모든 내용은 호출 프로세스로 전송됩니다. 우리의 경우 이 프로세스는 redis-cli입니다. 그러면 터미널 창에 결과가 표시됩니다.

좀 더 복잡한 것인가요?

마스터 Redis Lua 스크립팅:성능 향상을 위한 실용 가이드 복잡한 Redis 스크립트를 구축하려는 사람

나는 Lua 스크립트를 사용하여 해시 맵의 요소를 특정 순서로 반환한 적이 있습니다. 순서 자체는 정렬된 세트에 저장된 해시 키로 지정되었습니다.

먼저 redis-cli에서 다음 명령을 실행하여 데이터를 설정해 보겠습니다. :

hmset hkeys key:1 value:1 key:2 value:2 key:3 value:3 key:4 value:4 key:5 value:5 key:6 value:6
zadd order 1 key:3 2 key:1 3 key:2

이 명령은 hkeys 키에 해시 맵을 생성합니다. 키 order에 있는 정렬된 세트 hkeys에서 선택한 키가 포함되어 있습니다. 특정 순서로.

확인해 보세요 hmset 그리고 자드 자세한 내용은 명령 참조

다음 스크립트를 실행해 보겠습니다:

eval “local order = redis.call(‘zrange’, KEYS[1], 0, -1); return redis.call(‘hmget’,KEYS[2],unpack(order));” 2 order hkeys

다음과 같은 출력이 표시됩니다:

“value:3”
“value:1”
“value:2”

이는 우리가 원하는 키 값을 올바른 순서로 얻었음을 의미합니다.

실행하려면 전체 스크립트 텍스트를 지정해야 하나요?

안돼! Redis를 사용하면 SCRIPT LOAD를 사용하여 스크립트를 메모리에 미리 로드할 수 있습니다. 명령:

script load “return redis.call(‘get’, KEYS[1])”

다음과 같은 출력이 표시됩니다:

“4e6d8fc8bb01276962cce5371fa795a7763657ae”

이는 EVALSHA에 제공해야 하는 스크립트의 고유 해시입니다. 스크립트를 실행하는 명령:

evalsha 4e6d8fc8bb01276962cce5371fa795a7763657ae 1 key:name

참고:실제를 사용해야 합니다 SHA1 해시가 반환됨 스크립트 로드 명령, 위 해시는 단지 예시일 뿐입니다.

JSON 변경에 관해 무엇을 언급하셨나요?

때때로 사람들은 Redis에 JSON 객체를 저장합니다. 좋은 생각인지 아닌지는 별개의 이야기지만 실제로는 이런 일이 많이 발생합니다.

이 JSON 객체의 키를 변경해야 하는 경우 Redis에서 가져와 구문 분석하고 키를 변경한 다음 직렬화하고 다시 Redis로 설정해야 합니다. 이 접근 방식에는 몇 가지 문제가 있습니다:

  1. 동시성. 또 다른 프로세스는 get 및 set 작업 사이에서 이 JSON을 변경할 수 있습니다. 이 경우 변경사항이 손실됩니다.
  2. 성능. 이러한 변경을 자주 수행하고 개체가 상당히 큰 경우 앱의 병목 현상이 발생할 수 있습니다. Lua에서 이 논리를 구현하면 어느 정도 성능을 얻을 수 있습니다.

obj 키 아래 Redis에 테스트 JSON 문자열을 추가해 보겠습니다. :

set obj ‘{“a”:”foo”,”b”:”bar”}’

이제 스크립트를 실행해 보겠습니다:

EVAL ‘local obj = redis.call(“get”,KEYS[1]); local obj2 = string.gsub(obj,”(“ .. ARGV[1] .. “\”:)([^,}]+)”, “%1” .. ARGV[2]); return redis.call(“set”,KEYS[1],obj2);’ 1 obj b bar2

이제 obj 키 아래에 다음 개체가 있습니다. :

{“a”:”foo”,”b”:”bar2"}

대신 SCRIPT LOAD를 사용하여 이 스크립트를 로드할 수 있습니다. 명령:

SCRIPT LOAD ‘local obj = redis.call(“get”,KEYS[1]); local obj2 = string.gsub(obj,”(“ .. ARGV[1] .. “\”:)([^,}]+)”, “%1” .. ARGV[2]); return redis.call(“set”,KEYS[1],obj2);’

그런 다음 다음과 같이 실행하세요:

EVALSHA <your_script_sha> 1 obj b bar2

몇 가지 참고 사항:

  • .. Lua의 문자열 연결 연산자입니다.
  • RegEx 패턴을 사용하여 키를 일치시키고 해당 값을 바꿉니다. 이 정규식을 이해하지 못한다면 최근 가이드를 확인하세요.
  • 대부분의 다른 버전과 Lua RegEx 버전의 한 가지 차이점은 %을 사용한다는 것입니다. RegEx 특수 기호에 대한 역참조 표시 및 이스케이프 문자로 사용됩니다.
  • 우리는 여전히 을 탈출합니다 \%가 아닙니다. RegEx 특수 기호가 아닌 Lua 문자열 구분 기호를 이스케이프하기 때문입니다.

항상 Lua 스크립트를 사용해야 하나요?

아니요. 더 나은 성능을 가져온다는 것을 증명할 수 있는 경우에만 사용하는 것이 좋습니다. 항상 벤치마크를 먼저 실행하세요.

원하는 것이 원자성이라면 대신 Redis 트랜잭션을 확인해야 합니다.

또한 스크립트가 너무 길어서는 안 됩니다. 스크립트가 실행되는 동안 다른 모든 것은 스크립트가 완료되기를 기다리고 있다는 점을 기억하십시오. 스크립트에 시간이 많이 걸리면 성능이 향상되기는커녕 병목 현상이 발생할 수 있습니다. 제한 시간(기본적으로 5초)에 도달하면 스크립트가 중지됩니다.

마스터 Redis Lua 스크립팅:성능 향상을 위한 실용 가이드 Redis 스크립트는 시간이 너무 많이 걸려서는 안 됩니다.

마지막 말씀

Lua에 대한 자세한 내용은 lua.org를 확인하세요.

Lua 스크립트의 몇 가지 예를 보려면 GitHub의 node.js 라이브러리를 확인하세요(src/lua 참조). 폴더). Lua 스크립트를 직접 작성하지 않고도 node.js에서 이 라이브러리를 사용하여 JSON 개체를 변경할 수도 있습니다.

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

이 기사를 읽어주셔서 감사합니다. 질문과 의견을 보내주시면 감사하겠습니다. 당신도 나를 팔로우할 수 있습니다 트위터 .

무료로 코딩을 배우세요. freeCodeCamp의 오픈 소스 커리큘럼은 40,000명 이상의 사람들이 개발자로 취업하는 데 도움을 주었습니다. 시작하세요