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

서비스 중단 없이 Redis에서 SQL 쿼리를 실행하는 방법

Redis에서 SQL 쿼리를 실행하는 일은 생각보다 어렵지 않습니다. 몇 년 전, 한 소매 기업에서 데이터 웨어하우스 솔루션을 관리하던 친구와 나눈 대화에서 이 주제가 처음 등장했습니다. 그는 자신이 겪고 있던 문제를 설명하다가 자연스럽게 Redis의 쿼리 기능에 대해 이야기를 나누게 되었습니다.

데이터 웨어하우스 솔루션에서 골치 아픈 문제가 있습니다. 데이터를 실시간으로 기록하고 분석 연산을 수행해야 하는 use case가 있는데, 결과를 얻는 데 가끔 몇 분씩 걸립니다. Redis가 도움이 될 수 있을까요? 단, 기존의 SQL 기반 솔루션을 한 번에 갈아엎을 수는 없습니다. 한 번에 한 걸음씩만 옮겨갈 수 있는 상황입니다.

친구와 같은 고민을 하고 계신다면 좋은 소식이 있습니다. 현재 운영 중인 SQL 기반 솔루션을 중단하지 않고도 Redis 쿼리를 실행하고 아키텍처에 Redis를 점진적으로 도입할 수 있는 방법이 여러 가지 있기 때문입니다.

이번 글에서는 그 방법들을 하나씩 살펴보겠습니다. 본격적으로 시작하기에 앞서, Redis 해커톤 참가자가 SQL로 Redis 데이터를 조회할 수 있는 앱을 직접 개발한 사례를 담은 영상을 먼저 확인해 보세요.

테이블을 Redis 데이터 구조로 재설계하기

관계형 테이블을 Redis 데이터 구조로 매핑하는 것은 생각보다 간단합니다. 특히 유용하게 활용되는 데이터 구조는 다음 세 가지입니다.

  • Hash
  • Sorted Set
  • Set

한 가지 방법은 테이블의 각 행(row)을 Hash로 저장하되, 키는 테이블의 기본 키(primary key)를 기반으로 생성하고, 해당 키를 Set 또는 Sorted Set에 함께 저장하는 것입니다.

그림 1은 테이블을 Redis 데이터 구조로 매핑하는 예시입니다. 여기에는 Products라는 테이블이 있으며, 모든 행은 Hash 데이터 구조로 매핑됩니다.

예를 들어 기본 키가 10001인 행은 product:10001이라는 키를 가진 Hash로 저장됩니다. 이 예시에는 두 개의 Sorted Set이 사용되는데, 하나는 기본 키 순서로 전체 데이터셋을 순회하기 위한 것이고, 다른 하나는 가격 조건으로 데이터를 조회하기 위한 것입니다.

서비스 중단 없이 Redis에서 SQL 쿼리를 실행하는 방법


이 방식을 적용하려면 SQL 명령 대신 Redis 쿼리를 사용하도록 코드를 일부 수정해야 합니다. 아래는 동일한 작업을 수행하는 SQL 명령과 Redis 명령의 비교 예시입니다.

A. 데이터 삽입

SQL:
insert into Products (id, name, description, price)
values = (10200, “ZXYW”,“Description for ZXYW”, 300);
Redis:
MULTI
HMSET product:10200 name ZXYW desc “Description for ZXYW” price 300
ZADD product_list 10200 product:10200
ZADD product_price 300 product:10200
EXEC

B. 제품 ID로 조회

SQL:
select * from Products where id = 10200
Redis:
HGETALL product:10200

C. 가격으로 조회

SQL:
select * from Product where price < 300
Redis: 
ZRANGEBYSCORE product_price 0 300 

위 명령은 product:10001, product:10002, product:10003 키를 반환합니다. 이후 각 키에 대해 HGETALL을 실행하면 실제 데이터를 가져올 수 있습니다.

HGETALL product:10001
HGETALL product:10002
HGETALL product:10003

DataFrame으로 테이블을 Redis 데이터 구조에 자동 매핑하기

솔루션의 SQL 인터페이스는 그대로 유지하면서, 내부 데이터 저장소만 Redis로 교체해 성능을 끌어올리고 싶다면 Apache Spark와 Spark-Redis 라이브러리를 활용하면 됩니다.

Spark-Redis 라이브러리를 사용하면 DataFrame API를 통해 Redis 데이터를 저장하고 조회할 수 있습니다. 즉, SQL 명령으로 데이터를 삽입·수정·조회하면서도, 실제 데이터는 내부적으로 Redis 데이터 구조에 자동으로 매핑됩니다.

서비스 중단 없이 Redis에서 SQL 쿼리를 실행하는 방법

먼저 spark-redis를 다운로드하여 빌드한 뒤 jar 파일을 확보해야 합니다. 예를 들어 spark-redis 2.3.1 버전을 빌드하면 spark-redis-2.3.1-SNAPSHOT-jar-with-dependencies.jar 파일을 얻을 수 있습니다.

다음으로 Redis 인스턴스가 실행 중인지 확인합니다. 이 예시에서는 localhost의 기본 포트 6379에서 Redis를 구동합니다.
Apache Spark 엔진 위에서도 동일하게 쿼리를 실행할 수 있습니다. 다음은 그 과정을 보여주는 예시입니다.

$ spark-shell --jars spark-redis-2.3.1-SNAPSHOT-jar-with-dependencies.jar
scala> import org.apache.spark.sql.SparkSession

scala> val spark = SparkSession
.builder()
.appName("redis-sql")
.master("local[*]")
.config("spark.redis.host","localhost")
.config("spark.redis.port","6379").getOrCreate()

scala> import spark.sql

scala> import spark.implicits._

scala> sql("create table if not exists products(id string, name string, description string, price int) using org.apache.spark.sql.redis options (table 'product')")

scala> sql("insert into products values = ('10200','ZXYW','Description of ZXYW', 300)")

scala> val results = sql("select * from products")

scala> results.show()
+-----+----+-------------------+-----+
| id|name| description|price|
+-----+----+-------------------+-----+
|10200|ZXYW|Description of ZXYW| 300|
+-----+----+-------------------+-----+

이제 Redis 클라이언트를 통해서도 이 데이터를 Redis 데이터 구조 형태로 그대로 조회할 수 있습니다.

127.0.0.1:6379> keys product*
1) "product:2e3f8611dbe94a588706a2aaea547caa"

다만 더 효율적인 방법은 scan 명령을 사용하는 것입니다. scan은 데이터를 탐색하는 과정에서 페이지네이션을 지원하기 때문에 대량의 키를 다룰 때 안정적입니다.

127.0.0.1:6379> scan 0 match product*
1) "3"
2) 1) "product:2e3f8611dbe94a588706a2aaea547caa"
127.0.0.1:6379> hgetall product:2e3f8611dbe94a588706a2aaea547caa
1) "name"
2) "ZXYW"
3) "price"
4) "300"
5) "description"
6) "Description of ZXYW"
7) "id"
8) "10200"

지금까지 살펴본 것처럼, 기존 시스템을 중단하지 않고 Redis SQL 쿼리를 실행할 수 있는 두 가지 간단한 방법을 확인했습니다. 한 단계 더 나아가고 싶다면 새 백서 Why Your SQL Server Needs Redis(왜 SQL 서버에는 Redis가 필요한가)를 확인해 보시기 바랍니다.

Redis를 활용한 실시간 데이터 처리는 이것이 전부가 아닙니다. Redis는 실시간 경험을 제공하기 위해 활용할 수 있는 방법이 무궁무진한 플랫폼입니다.

Redis가 실시간 데이터 전송을 어떻게 보장하는지 궁금하시다면 언제든지 문의해 주세요.