안드레이 체르니코프 저
Redis는 프로세스 간 통신 및 데이터 저장에 사용되는 널리 사용되는 인 메모리 그리드입니다. Lua 스크립트를 실행할 수 있다는 말을 들어보셨겠지만, 아직 그 이유를 잘 모르겠습니다. 당신도 이에 해당한다면 계속 읽어보세요.
전제조건
이 가이드를 따르려면 시스템에 Redis가 설치되어 있어야 합니다. 읽는 동안 Redis 명령 참조를 확인하는 것이 도움이 될 수 있습니다.
Lua 스크립트가 왜 필요한가요?
한마디로 성능 향상입니다. Redis에서 수행하는 대부분의 작업에는 여러 단계가 포함됩니다. 애플리케이션 언어로 이러한 단계를 수행하는 대신 Lua를 사용하여 Redis 내에서 수행할 수 있습니다.
- 이렇게 하면 성능이 향상될 수 있습니다.
- 또한 스크립트 내의 모든 단계는 원자적인 방식으로 실행됩니다. 스크립트가 실행되는 동안에는 다른 Redis 명령을 실행할 수 없습니다.
예를 들어 Lua 스크립트를 사용하여 Redis에 저장된 JSON 문자열을 변경합니다. 이 기사의 마지막 부분에서 이에 대해 자세히 설명하겠습니다.
그런데 저는 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과 기능적으로 동일한 스크립트입니다. 명령. 스크립트 텍스트 뒤에는 세 개의 매개변수가 있습니다:
- 제공된 키 개수
- 키 이름
- 첫 번째 인수
스크립트 인수는 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.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-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로 설정해야 합니다. 이 접근 방식에는 몇 가지 문제가 있습니다:
- 동시성. 또 다른 프로세스는 get 및 set 작업 사이에서 이 JSON을 변경할 수 있습니다. 이 경우 변경사항이 손실됩니다.
- 성능. 이러한 변경을 자주 수행하고 개체가 상당히 큰 경우 앱의 병목 현상이 발생할 수 있습니다. 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에 대한 자세한 내용은 lua.org를 확인하세요.
Lua 스크립트의 몇 가지 예를 보려면 GitHub의 node.js 라이브러리를 확인하세요(src/lua 참조). 폴더). Lua 스크립트를 직접 작성하지 않고도 node.js에서 이 라이브러리를 사용하여 JSON 개체를 변경할 수도 있습니다.
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
이 기사를 읽어주셔서 감사합니다. 질문과 의견을 보내주시면 감사하겠습니다. 당신도 나를 팔로우할 수 있습니다 트위터 .
무료로 코딩을 배우세요. freeCodeCamp의 오픈 소스 커리큘럼은 40,000명 이상의 사람들이 개발자로 취업하는 데 도움을 주었습니다. 시작하세요