【輪子狂魔】手把手教你自造Redis Client,狂魔redis
為什麼做Redis Client?
Redis Client顧名思義,redis的客戶端,主要是封裝了一些對於Redis的操作。
而目前用的比較廣泛的 ServiceStack.Redis 不學好,居然開始收費了。
作為輪子狂魔,是可忍孰不可忍啊。於是我決定自己造輪子了。
Redis通信協議
先給個Redis官方的通信協議地址:http://redisdoc.com/topic/protocol.html

關鍵是我截圖的部分,我們可以得到以下幾個信息:
1.tcp協議
2.默認端口6379
3.命令以 \r\n 結尾
實現Redis交互(Get、Set)
Set命令說明:http://redisdoc.com/string/set.html
Get命令說明:http://redisdoc.com/string/get.html
C#的Tcp交互選用TcpClient
實現Set指令
代碼意圖大概說一下:
1.創建TcpClient
2.連接Redis (127.0.0.1:6379)
3.發送指令 set test csharp\r\n (注意\r\n是一開始通信協議就提到的,命令以\r\n結尾)
4.使用UTF8來編碼和解碼
5.接收返回信息
PS:get指令類似,我就不貼出來了

![]()
1 var tcpClient = new System.Net.Sockets.TcpClient();
2
3 tcpClient.Connect("127.0.0.1", 6379);
4
5 string setCommand = "set test csharp\r\n";
6 tcpClient.Client.Send(Encoding.UTF8.GetBytes(setCommand));
7 System.Diagnostics.Trace.Write(setCommand);
8 byte[] buffer = new byte[256];
9 tcpClient.Client.Receive(buffer);
10 System.Diagnostics.Trace.Write(Encoding.UTF8.GetString(buffer).Replace("\0", ""));
View Code
想象中的調用方式
1.第一行有個關鍵思維是單例模式,即我希望全局只有一個Redis Client。(多個的話可以直接用RedisClient)
2.RedisClient的連接地址可自由指定
3. 從單例中取出Client就可以簡單粗暴的上ta。client.Set(key,value)
1 var client = RedisSingleton.GetInstance.Client = new Client.RedisClient("127.0.0.1", 6379);
2 client.Set("test", "Framework.Redis");
3 var value = client.Get("test");
4 Trace.Write("client get:" + value);
重構一個RedisManager和RedisClient
RedisManager 其實就是個簡單的單例模式,封裝了一個全局唯一的對象而已。如果不想全局唯一,直接用RedisClient就可以了。

![]()
1 public class RedisSingleton
2 {
3 #region 單例
4
5 private static RedisSingleton _redisSingleton = null;
6 private static object _locker = new object();
7
8 public static RedisSingleton GetInstance
9 {
10 get
11 {
12 if (_redisSingleton == null)
13 {
14 lock (_locker)
15 {
16 if (_redisSingleton == null)
17 {
18 _redisSingleton = new RedisSingleton();
19 }
20 }
21 }
22
23 return _redisSingleton;
24 }
25 }
26
27 #endregion
28
29 public RedisClient Client { get; set; }
30 }
View Code
RedisClient 是真正的與Redis交互的代碼(因為這只是個簡單粗暴的Demo,所以代碼不太美觀,見諒!之後會繼續完善我的這個自造的Redis)

![]()
1 public class RedisClient
2 {
3 private TcpClient _tcpClient = null;
4
5 public RedisClient(string serverIP, int serverPort)
6 {
7 _tcpClient = new TcpClient();
8 _tcpClient.Connect(serverIP, serverPort);
9 }
10
11 public void Set(string key, string value)
12 {
13 string setCommand = "set " + key + " " + value + "\r\n";
14 _tcpClient.Client.Send(Encoding.UTF8.GetBytes(setCommand));
15 Logger.Info(setCommand);
16 var result = GetRaw();
17 if (result != "+OK")
18 {
19 throw new Exception("redis error:" + result);
20 }
21 }
22
23 public string Get(string key)
24 {
25 string setCommand = "get " + key + "\r\n";
26 _tcpClient.Client.Send(Encoding.UTF8.GetBytes(setCommand));
27 Logger.Info(setCommand);
28 string value = GetRaw();
29 Logger.Info("get " + key + " value:" + value);
30 return value.Split(new string[] { "\r\n" }, StringSplitOptions.None)[1];
31 }
32
33 private string GetRaw()
34 {
35 byte[] buffer = new byte[256];
36 _tcpClient.Client.Receive(buffer);
37 string value = Encoding.UTF8.GetString(buffer).Replace("\0", "").TrimEnd("\r\n".ToCharArray());
38 return value;
39 }
40 }
View Code
最後是大家喜歡的廣告環節
全部代碼就這麼多我就不分享我的oschina上的項目地址了,因為目前正在做一個開源的mvc項目需要使用Redis,所以自己造了這麼個輪子。
如果你有興趣加入我們,請加群:7424099
哦,不好意思,補上有圖有真相
