메훌 모한 저
Redis는 캐싱 및 속도 제한과 같은 다양한 프로젝트에 사용되는 인기 있는 인메모리 데이터베이스입니다.
이 블로그 게시물에서는 Redis를 인메모리 데이터베이스로 사용하는 방법과 Redis를 사용하려는 이유를 살펴보고 마지막으로 데이터베이스의 몇 가지 중요한 기능에 대해 논의하겠습니다. 시작해 보겠습니다.
인메모리 데이터베이스란 무엇인가요?
기존 데이터베이스는 더 빠른 액세스를 위해 데이터베이스의 일부(일반적으로 "핫"하거나 자주 액세스하는 인덱스)를 메모리에 보관하고 나머지 데이터베이스는 디스크에 보관합니다.
반면 Redis는 대기 시간과 데이터의 빠른 검색 및 저장에 중점을 둡니다. 따라서 저장장치(SSD/HDD)가 아닌 메모리(RAM)에서 완전히 작동합니다. 속도가 중요합니다!
Redis는 키-값 데이터베이스입니다. 하지만 이것이 단순한 데이터베이스라고 생각하도록 속여서는 안 됩니다. 이러한 키와 값을 저장하고 검색하는 방법은 많습니다.
Redis가 필요한 이유는 무엇인가요?
Redis를 다양한 방법으로 사용할 수 있습니다. 하지만 제가 생각하는 두 가지 주된 이유는 다음과 같습니다:
- 코드 레이어를 상태 비저장으로 만들려는 애플리케이션을 만들고 있습니다. 왜? - 코드가 상태 비저장(stateless)이면 수평 확장이 가능하기 때문입니다. 따라서 Redis를 중앙 스토리지 시스템으로 사용하고 코드에서 로직만 처리하도록 할 수 있습니다.
- 여러 앱이 데이터를 공유해야 하는 애플리케이션을 만들고 있습니다. 예를 들어, 누군가가
payments.codedamn.com에서 귀하의 사이트를 무차별 대입 공격하려고 한다면 어떻게 될까요? , 감지한 후에는login.codedamn.com에서 차단하고 싶을 수도 있습니다. ? Redis를 사용하면 연결이 끊어지거나 느슨하게 연결된 여러 서비스가 공통 메모리 공간을 공유할 수 있습니다.
Redis는 알아야 할 명령이 소수에 불과하므로 배우기가 비교적 간단합니다. 다음 몇 섹션에서는 몇 가지 주요 Redis 개념과 몇 가지 유용한 일반 명령을 다루겠습니다.
Redis CLI
Redis에는 명령줄의 REPL 버전인 CLI가 있습니다. 당신이 쓴 것은 무엇이든 평가될 것입니다.
위 이미지는 간단한 PING를 수행하는 방법을 보여줍니다. 또는 Redis의 Hello World in Redis 과정 연습 중 하나를 사용하세요(과정을 확인하려면 마지막에 링크되어 있습니다).
이 Redis REPL은 애플리케이션에서 데이터베이스 작업을 할 때 몇 가지 키나 Redis 상태를 빠르게 확인해야 할 때 매우 유용합니다.
일반적인 Redis 명령
codedamn 과정에서 Redis CLI에 대한 일반적인 명령 시험해 보기
다음은 Redis의 작동 방식을 자세히 알아보는 데 도움이 되는 매우 일반적으로 사용되는 몇 가지 명령입니다.
설정
SET을 사용하면 Redis에서 키를 값으로 설정할 수 있습니다.
작동 방식의 예는 다음과 같습니다.
SET mehul "developer from india"
그러면 키 mehul가 설정됩니다. developer from india 값으로 .
받기
GET을 사용하면 설정한 키를 가져올 수 있습니다.
구문은 다음과 같습니다:
GET mehul
그러면 위에서 설정한 "developer from india"라는 문자열이 반환됩니다.
SETNX
이 키는 키가 존재하지 않는 경우에만 값을 설정합니다. 이 명령에는 이미 존재할 수 있는 키 값을 실수로 덮어쓰지 않는 것을 포함하여 다양한 사용 사례가 있습니다.
작동 방식은 다음과 같습니다:
SET key1 value1
SETNX key1 value2
SETNX key2 value2
이 예제를 실행한 후 key1 값은 value1입니다. 그리고 key2 value2로 . 이는 두 번째 명령이 key1와 같이 아무런 효과가 없기 때문입니다. 이미 존재했습니다.
MSET
MSET은 SET과 비슷하지만 하나의 명령으로 여러 키를 함께 설정할 수 있습니다. 작동 방식은 다음과 같습니다:
MSET key1 "value1" key2 "value2" key3 "value3"
지금은 key을 사용하고 있습니다. 및 value 키와 값의 접두사로 사용됩니다. 그러나 실제로 이러한 코드를 작성하면 긴 명령에서 키가 무엇인지, 값이 무엇인지 추적하기가 쉽습니다.
따라서 할 수 있는 한 가지는 항상 큰따옴표를 사용하여 값을 인용하고 키를 따옴표 없이 두는 것입니다(따옴표 없이 유효한 키 이름인 경우).
MGET
MGET은 GET과 유사하지만 다음과 같이 한 번에 여러 값을 반환할 수 있습니다.
MGET key1 key2 key3 key4
그러면 4개의 값이 배열로 반환됩니다:value1 , value2 , value3 및 null . key4을 얻었습니다 우리는 그것을 설정하지 않았기 때문에 null로 간주합니다.
델
이 명령은 키를 삭제합니다. 아주 간단하죠?
예를 들면 다음과 같습니다:
SET key value
GET key # gives you "value"
DEL key
GET key # null
증가 및 감소
이 두 명령을 사용하여 숫자인 키를 늘리거나 줄일 수 있습니다. Redis는 GET 키와 SET 키를 키 + 1로 한 번에 두 가지 작업을 수행할 수 있기 때문에 매우 유용하고 많이 사용하게 될 것입니다.
이렇게 하면 상위 애플리케이션으로의 왕복을 방지하고 트랜잭션을 사용하지 않고도 작업을 안전하게 수행할 수 있습니다(나중에 자세히 설명)
작동 방식은 다음과 같습니다:
SET favNum 10
INCR favNum # 11
INCR favNum # 12
DECR favNum # 11
만료
EXPIRE 명령은 키에 만료 타이머를 설정하는 데 사용됩니다. 기술적으로 타이머는 아니지만 다시 설정하지 않는 한 키가 항상 null을 반환하는 종료 타임스탬프입니다.
SET bitcoin 100
EXPIRE bitcoin 10
GET bitcoin # 100
# after 10 seconds
GET bitcoin # null
EXPIRE 해당 키를 전체적으로 저장하기 위해 약간 더 많은 메모리를 사용합니다(왜냐하면 이제 해당 키가 만료되어야 하는 시기도 저장해야 하기 때문입니다). 하지만 아마도 그 오버헤드에 대해서는 전혀 신경 쓰지 않을 것입니다.
TTL
이 명령을 사용하면 키의 수명을 알 수 있습니다.
예:
SET bitcoin 100
TTL bitcoin # -1
TTL somethingelse # -2
EXPIRE bitcoin 5
# wait 2 seconds
TTL bitcoin # returns 3
# after 1 second
GET bitcoin # null
TTL bitcoin # -2
그렇다면 이 코드에서 무엇을 배울 수 있을까요?
- TTL은
-1을 반환합니다. 키가 존재하지만 만료일이 없는 경우 - TTL은
-2을 반환합니다. 키가 존재하지 않는 경우 - 키가 존재하고 만료되는 경우 TTL은 TTL(Time to Live)을 초 단위로 반환합니다.
세텍스
SET을 수행할 수 있습니다. 및 만료 SETEX과 함께 .
다음과 같습니다:
SETEX key 10 value
여기서 키는 "key"이고 값은 "value"이며 TTL(Time To Live)은 10입니다. 이 키는 10초 후에 설정 해제됩니다.
이제 기본 Redis 명령과 CLI 작동 방식에 대한 기본적인 지식을 갖추었으므로 몇 가지 프로젝트를 빌드하고 이러한 도구를 실제 생활에서 사용해 보겠습니다.
프로젝트 1 – Redis를 사용하여 API 캐싱 시스템 구축
codedamn에 대한 API 캐싱 시스템 구축 실습 미리보기
이 프로젝트에는 Redis를 사용하여 API 캐싱 시스템을 설정하는 작업이 포함됩니다. 여기서 타사 서버의 결과를 캐시하고 일정 기간 동안 사용할 수 있습니다.
이는 해당 제3자에 의해 요금이 제한되지 않도록 하는 데 유용합니다. 또한 캐싱은 사이트 속도를 향상시키므로 올바르게 구현하면 모두에게 이익이 됩니다.
Node.js를 사용하여 브라우저 내부의 codedamn에서 대화형으로 이 프로젝트를 빌드할 수 있습니다. 관심이 있으시면 API 캐싱 연구실을 무료로 사용해 보실 수 있습니다.
솔루션에만 관심이 있고 직접 구축하지 않는 경우 Node.js에서 핵심 로직이 작동하는 방식은 다음과 같습니다.
app.post('/data', async (req, res) => {
const repo = req.body.repo
const value = await redis.get(repo)
if (value) {
// means we got a cache hit
res.json({
status: 'ok',
stars: value
})
return
}
const response = await fetch(`https://api.github.com/repos/${repo}`).then((t) => t.json())
if (response.stargazers_count != undefined) {
await redis.setex(repo, 60, response.stargazers_count)
}
res.json({
status: 'ok',
stars: response.stargazers_count
})
})
여기서 무슨 일이 일어나고 있는지 살펴보겠습니다:
repo을 얻으려고 합니다. (전달된 저장소 형식 -facebook/react) Redis 캐시에서. 있다면 좋습니다! Redis 캐시에서 별 개수를 반환하여 GitHub 서버로의 왕복 시간을 절약합니다.- 캐시에서 찾지 못하면 GitHub 서버에 요청하여 별 개수를 가져옵니다. 별 개수가 정의되지 않았는지 확인합니다(저장소가 존재하지 않거나 비공개인 경우). 값이 있으면
setex시간 제한이 60초인 값입니다. - 시간이 지남에 따라 오래된 값을 제공하고 싶지 않기 때문에 시간 제한을 설정했습니다. 이렇게 하면 별표 수를 최소한 1분에 한 번씩 새로 고치는 데 도움이 됩니다.
전체 소스 코드는 다음과 같습니다:
프로젝트 2 - Redis를 사용한 속도 제한 API
Redis를 사용한 속도 제한 API 미리보기
이 프로젝트에는 악의적인 행위자로부터 보호하기 위해 특정 엔드포인트의 속도를 제한한 다음 해당 특정 API에 대한 액세스를 차단하는 작업이 포함됩니다.
이는 한 사람이 수천 건의 요청으로 엔드포인트를 공격하는 것을 원하지 않는 로그인 및 민감한 API 엔드포인트에 매우 유용합니다.
본 실습에서는 IP 주소별로 속도 제한을 수행합니다. 이 Codelab을 시도하고 싶다면 codedamn에서 무료로 사용해 볼 수 있습니다.
솔루션에만 관심이 있고 직접 구축하지 않는 경우 Node.js에서 핵심 로직이 작동하는 방식은 다음과 같습니다.
app.post('/api/route', async (req, res) => {
// add data here
const ip = req.headers['x-forwarded-for'] || req.ip
const reqs = await redis.incr(ip)
await redis.expire(ip, 2)
if (reqs > 15) {
return res.json({
status: 'rate-limited'
})
} else if (reqs > 10) {
return res.json({
status: 'about-to-rate-limit'
})
} else {
res.json({
status: 'ok'
})
}
})
이 코드 블록을 이해해 봅시다:
x-forwarded-for에서 IP를 추출하려고 합니다. 헤더(또는req.ip를 사용할 수 있음) 우리는 express를 사용하고 있기 때문에)- 우리는
INCRIP 주소 필드. Redis의 키가 존재하지 않는 경우 INCR은 자동으로 키를 0으로 설정하고 증가하여 최종적으로 1로 설정됩니다. - 키가 2초 후에 만료되도록 설정했습니다. 이상적으로는 더 큰 값을 원할 것입니다. 그러나 이것이 위에서 지정한 코드 빌어먹을 문제이므로 여기까지입니다.
- 마지막으로 요청 개수를 확인하고, 특정 임계값보다 큰 경우 요청이 기본 기능 본문에 도달하는 것을 차단합니다.
전체 솔루션은 다음과 같습니다.
Redis에 대한 추가 정보
Redis는 지금까지 배운 것보다 훨씬 더 많은 기능을 제공합니다. 하지만 좋은 점은 우리가 이미 작업을 시작할 만큼 충분히 배웠다는 것입니다!
이 섹션에서는 Redis의 기본 사항을 몇 가지 더 살펴보겠습니다.
Redis는 단일 스레드입니다
Redis는 멀티 스레딩을 지원하는 다중 코어 시스템에서도 단일 스레드 프로세스로 실행됩니다. 이는 성능상의 악몽은 아니지만 다중 스레드 환경에서 일관되지 않은 읽기/쓰기에 대한 안전 조치입니다.
Redis가 다중 스레드인 경우 단일 키에 액세스할 때 스레드 안전을 보장하기 위해 결국에는 단일 스레드/순차 액세스보다 성능이 떨어지는 일부 잠금 메커니즘으로 해결되었을 것입니다.
Redis 트랜잭션
물론 단일 명령으로 Redis의 모든 작업을 수행할 수는 없습니다. 그러나 한 번에 여러 명령 블록을 수행하도록 요청할 수는 있습니다(즉, Redis가 해당 블록을 실행하는 동안 다른 누구도 Redis와 대화하지 않습니다). MULTI을 사용하여 그렇게 할 수 있습니다. 명령을 내리세요.
작동 방식은 다음과 같습니다:
MULTI
SET hello world
SET yo lo
SET number 1
INCR number
EXPIRE hello 10
EXPIRE yo 5
EXEC
이는 모든 작업을 한 번에 수행합니다. 즉, 않습니다. MULTI 이후에는 무엇이든 실행하세요. , EXEC이 표시되는 순간 모든 것을 한 번에 실행합니다. 키워드.
Redis에는 고급 사용 사례를 위한 목록 및 세트에 대한 지원이 포함되어 있습니다. Redis를 게시하는 브로드캐스팅 서비스로 사용할 수도 있습니다. 채널 및 구독한 다른 사용자에게 채널에 알림을 받습니다. 이는 다중 클라이언트 아키텍처에서 매우 유용합니다.
결론
Redis에 대한 소개가 마음에 드셨기를 바랍니다. 이 블로그 게시물은 codedamn의 새로운 대화형 과정인 Redis + Node.js 캐싱의 일부입니다. 여기서 이러한 개념에 대해 배울 뿐만 아니라 이동 중에도 브라우저에서 연습할 수 있습니다.
자유롭게 강좌를 시도해 보시고 여러분의 생각을 알려주세요. 피드백을 보내려면 트위터에서 저를 찾으세요 :)
무료로 코딩을 배우세요. freeCodeCamp의 오픈 소스 커리큘럼은 40,000명 이상의 사람들이 개발자로 취업하는 데 도움을 주었습니다. 시작하세요