[C#] Redis 데이터베이스를 접속해서 사용하는 방법 (StackExchange.Redis 라이브러리 사용법)
안녕하세요. 명월입니다.
이 글은 C#에서 Redis 데이터베이스를 접속해서 사용하는 방법에 대한 글입니다.
Redis 데이터베이스는 RDB 종류가 아닌 NoSQL 종류의 Key-Value타입의 데이터베이스입니다. 간단하게 공유 메모리 데이터베이스입니다.
이전 글에서 Linux 환경에서 설치 및 사용하는 방법에 대해 설명한 적 있습니다.
링크 - [CentOS] Redis 데이터베이스 설치와 명령어 사용법
그 Redis 데이터베이스를 C#에서 사용해 보겠습니다.
먼저 C#에서 사용하기 위해서는 Nuget을 이용해서 StackExchange.Redis 라이브러리를 설치합니다.
그럼 라이브러리가 설치되었으면 Redis 데이터베이스에 값을 저장하고 취득하겠습니다.
using System;
using StackExchange.Redis;
namespace ConsoleApp1
{
class Program
{
// 실행 함수
static void Main(string[] args)
{
// redis 접속한다.
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(new ConfigurationOptions
{
EndPoints = { "192.168.1.200:6379" }
});
// 기본 데이터베이스 취득
var db = redis.GetDatabase();
// ping pong 확인
var pong = db.Ping();
// 콘솔 출력
Console.WriteLine(pong);
// test 키로 hello world 값을 넣는다. 만료시간은 10분입니다.
db.StringSet("test", "hello world", TimeSpan.FromMinutes(10));
// test 키로 데이터를 취득한다.
string data = db.StringGet("test");
// 콘솔 출력
Console.WriteLine(data);
// 아무 키나 누르면 종료
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
위 소스에서 test의 키로 hello world를 넣었습니다. 그리고 10분 뒤에는 자동으로 key-value가 사라집니다.
그리고 test키로 취득하니 입력한 값이 콘솔에 출력이 되네요.
관련 함수에 관해서는 API 도큐멘트를 참조하세요.
링크 - https://stackexchange.github.io/StackExchange.Redis/
위에는 단순히 key 값으로 데이터를 넣어서 취득하는 기본적인 처리입니다.
그럼 실제 프로그램 작성할 때 자주 사용할 만한 처리식을 만들어 보겠습니다.
using System;
using System.IO;
using StackExchange.Redis;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
namespace ConsoleApp1
{
class Program
{
// 직렬화 타입
[Serializable]
// 예제 클래스
class Node
{
// 맴버 변수
private string data;
// 생성자
public Node(string data)
{
// 맴버 변수 설정
this.data = data;
}
// 출력 함수
public void Print()
{
// 콘솔 출력
Console.WriteLine(this.data);
}
}
// Node 클래스를 직렬화하여 binary로 바꾼뒤 String 타입으로 변환
static String ConvertToStringFromClass(Node node)
{
// 직렬화 클래스
var formatter = new BinaryFormatter();
// 클래스를 직렬화하여 보관할 데이터
byte[] data;
// 메모리 스트림
using (MemoryStream stream = new MemoryStream())
{
// 클래스를 직렬화하여 stream으로 변환
formatter.Serialize(stream, node);
// 스트림을 byte[] 데이터로 변환한다.
data = stream.GetBuffer();
}
// 값의 변형이 없게 ASCII 코드로 String 타입으로 변환
return Encoding.ASCII.GetString(data);
}
// 실행 함수
static void Main(string[] args)
{
// redis 접속한다.
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(new ConfigurationOptions
{
EndPoints = { "192.168.1.200:6379" }
});
// 기본 데이터베이스 취득
var db = redis.GetDatabase();
// 인스턴스 생성
var node = new Node("Test");
// Node 인스턴스를 string 타입으로 변환
var data = ConvertToStringFromClass(node);
// Redis 데이터베이스에 test 키로 저장 (만료시간 10분)
db.StringSet("test", data, TimeSpan.FromMinutes(10));
// 아무 키나 누르면 종료
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
위 소스에서 Node 클래스의 인스턴스를 직렬화로 이용하여 byte로 바꾸고 다시 String 타입으로 변환하여 Redis 데이터베이스에 입력했습니다.
그럼 이걸 다른 형식의 프로그램에서 취득할 수 있을까?
using System;
using System.IO;
using StackExchange.Redis;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
namespace ConsoleApp1
{
class Program
{
// 직렬화 타입
[Serializable]
// 예제 클래스
class Node
{
// 맴버 변수
private string data;
// 생성자
public Node(string data)
{
// 맴버 변수 설정
this.data = data;
}
// 출력 함수
public void Print()
{
// 콘솔 출력
Console.WriteLine(this.data);
}
}
// String 타입으로 byte로 변환하여 직렬화를 통해 인스턴스로 변환
static Node ConvertToClassFromString(String val)
{
// String을 통해서 byte로 변환
var binary = Encoding.ASCII.GetBytes(val);
// 직렬화 클래스
var formatter = new BinaryFormatter();
// 메모리 스트림
using (MemoryStream stream = new MemoryStream(binary))
{
// stream을 직렬화하여 인스턴스로 변환
return (Node)formatter.Deserialize(stream);
}
}
// 실행 함수
static void Main(string[] args)
{
// redis 접속한다.
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(new ConfigurationOptions
{
EndPoints = { "192.168.1.200:6379" }
});
// 기본 데이터베이스 취득
var db = redis.GetDatabase();
// test 키로 데이터를 취득한다.
var data = db.StringGet("test");
// string 타입을 Node 인스턴스로 변환
var node = ConvertToClassFromString(data);
// Node 클래스의 Print 함수 호출
node.Print();
// 아무 키나 누르면 종료
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
다른 프로그램에서 생성된 Node 인스턴스를 redis 데이터베이스에 넣고, 다시 다른 프로그램에서 취득하여 인스턴스로 변환하여 사용할 수 있는 것을 확인했습니다.
이 뜻은 직렬화를 통해서 클래스 형식으로 여러 프로그램에서 값을 공유할 수 있다는 뜻입니다. C#의 직렬화이니 다른 언어 프로그램에서는 사용할 수 없고 같은 언어인 C#에서만 사용이 가능하겠네요..
다른 언어간에 사용하려면 Json 타입으로 변환해서 사용하게 되면 언어가 다른 경우에도 값을 공유할 수 있겠네요.
using System;
using StackExchange.Redis;
using Newtonsoft.Json;
namespace ConsoleApp1
{
class Program
{
// 예제 클래스
class Node
{
// 맴버 변수
public string Data { get; set; }
// 생성자
public Node(string data)
{
// 맴버 변수 설정
this.Data = data;
}
// 출력 함수
public void Print()
{
// 콘솔 출력
Console.WriteLine(this.Data);
}
}
// 실행 함수
static void Main(string[] args)
{
// redis 접속한다.
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(new ConfigurationOptions
{
EndPoints = { "192.168.1.200:6379" }
});
// 기본 데이터베이스 취득
var db = redis.GetDatabase();
// 인스턴스 생성
var node = new Node("Test");
// 인스턴스를 Json 타입으로 변환
var data = JsonConvert.SerializeObject(node);
// Redis 데이터베이스에 test1 키로 저장 (만료시간 10분)
db.StringSet("test1", data, TimeSpan.FromMinutes(10));
// 아무 키나 누르면 종료
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
위 직렬화를 통해서 String으로 변환하여 Redis 데이터베이스에 저장한 것과 비슷합니다만 이번에는 직렬화가 아닌 Json 구조 타입으로 변환해서 입력했습니다.
using System;
using StackExchange.Redis;
using Newtonsoft.Json;
namespace ConsoleApp1
{
class Program
{
// 예제 클래스
class Node
{
// 맴버 변수
public string Data { get; set; }
// 생성자
public Node(string data)
{
// 맴버 변수 설정
this.Data = data;
}
// 출력 함수
public void Print()
{
// 콘솔 출력
Console.WriteLine(this.Data);
}
}
// 실행 함수
static void Main(string[] args)
{
// redis 접속한다.
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(new ConfigurationOptions
{
EndPoints = { "192.168.1.200:6379" }
});
// 기본 데이터베이스 취득
var db = redis.GetDatabase();
// test1 키로 데이터를 취득한다.
var data = db.StringGet("test1");
// Json 타입의 String타입을 인스턴스로 변환
var node = JsonConvert.DeserializeObject<Node>(data);
// Node 클래스의 Print 함수 호출
node.Print();
// 아무 키나 누르면 종료
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
Redis 데이터베이스에서 test1의 key값으로 Json 타입의 String값을 취득한 후 Node 인스턴스로 변환했습니다.
역시 Print 함수를 호출하니 위에서 입력한 Test 값이 콘솔에 출력이 되었습니다.
다음은 Redis에서 사용될 List와 Map, SortedSet 형식의 자료형입니다.
using System;
using StackExchange.Redis;
namespace ConsoleApp1
{
class Program
{
// 실행 함수
static void Main(string[] args)
{
// redis 접속한다.
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(new ConfigurationOptions
{
EndPoints = { "192.168.1.200:6379" }
});
// 기본 데이터베이스 취득
var db = redis.GetDatabase();
// List 형식 오른쪽 Push
db.ListRightPush("list", "1");
// List 형식 왼쪽 Push
db.ListLeftPush("list", "2");
// 2,1
db.ListSetByIndex("list", 1, "3");
// 2,3
// List 왼쪽부터 출력
Console.WriteLine(db.ListLeftPop("list"));
Console.WriteLine(db.ListLeftPop("list"));
// 개행
Console.WriteLine();
// Hash 형식의 key-value 값 입력
db.HashSet("map", "a", "1");
db.HashSet("map", "b", "2");
db.HashSet("map", "c", "3");
// {{"a","1"},{"b","2"},{"c","3"}}
// map의 b 키로 출력
Console.WriteLine(db.HashGet("map", "b"));
// 개행
Console.WriteLine();
// SortedSet 형식의 값 입력
db.SortedSetAdd("SortedSet", "aaa", 1);
db.SortedSetAdd("SortedSet", "bbb", 0);
// 입력 순서대로 sort
foreach(var sort in db.SortedSetScan("SortedSet"))
{
// 콘솔 출력
Console.WriteLine(sort);
}
// 개행
Console.WriteLine();
// Score 순위로 sort
foreach (var sort in db.SortedSetRangeByRank("SortedSet"))
{
// 콘솔 출력
Console.WriteLine(sort);
}
// 개행
Console.WriteLine();
// aaa의 Socre
Console.WriteLine(db.SortedSetScore("SortedSet", "aaa"));
// 아무 키나 누르면 종료
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
위는 Redis에서 list와 map, SortedSet 형식으로 사용되는 타입입니다.
사실 저는 잘 사용하지 않는 타입이기도 합니다.
Redis 프로그램의 알고리즘이 나쁘다고는 생각하지는 않지만 Redis 데이터베이스의 성능에 대한 병목 현상이나 알고리즘의 성능이 C#의 기본 List나 Dictionary보다 더 좋다고 생각되지는 않아서 가능하면 데이터를 그대로 넣고 취득해서 프로그램 내부에서 처리합니다.
제가 아직 Redis의 경험이 많지 않아서 정확하게는 잘 모르겠네요.
여기까지 C#에서 Redis 데이터베이스를 접속해서 사용하는 방법에 대한 글이었습니다.
궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.