1.redis介紹
Nosql數據庫作為關系型數據庫的補充,在互聯網公司已經得到廣泛的運用。redis便是其中的代表之一,redis是一種(key,value)基於內存的數據庫,並支持多種數據結構,如List,HashSet,string等,並能夠支持的數據的持久化存儲,redis如何做內存數據到磁盤的同步將分單獨的章節講解。既然redis是基於內存的數據庫,那么它將應用在對性能要求高的場合,如做數據緩存,可以減少數據庫訪問的壓力。同時redis可以應用在統計分析類的Web應用,統計分析類Web應用,一般情況下會從數據庫中讀取大量的數據並進行相關計算,因此,可以通過數據預處理的方式將數據提前計算,並以(key,value)的形式保存在redis中,從而能夠極大的改善查詢性能。
2.redis 在windows下的使用。
redis在linux下廣泛使用。官方網站為:http://redis.io/,window下redis官方並不提供支持,但是可以在http://redis.io/download下載windows64版redis,是由microsoft open tech 組開發和維護,開源代碼以發布在GitHub上:https://github.com/MSOpenTech/redis。另外在提供一個.exe可執行文件下載地址,支持32bit和64bit:https://github.com/rgl/redis/downloads。
下載redis.exe文件后,安裝redis后,會在對應的Redis根目錄中出現:redis-cli.exe,redis-server.exe,redis-service.exe,分別對應redis客戶端,服務端和redis服務啟動程序。打開分別redis-server.exe和redis-cli.exe后,在redis-cli命令行中輸入相關命令向redis服務器發送讀寫命令,可以看到redis-server命令行中顯示客戶端的連接情況。如下圖所示:
圖1.redis-server運行圖
圖2.redis-cli運行圖
接下來我們通過簡單的c# console程序來讀寫redis server數據庫。
3.c# 連接redis server數據庫。
目前比較常用的redis client c#類庫主要有:StackExchange.Redis和ServiceStack.Redis,本文主要使用的是StackExchange.Redis,StackExchange是一個高性能客戶端類庫,同時提供同步和異步操作。通過nuget來安裝StackExchange后,可以通過其連接redis server。
StackExchange中提供了一個ConnectionMultiplexer類,該對象屏蔽了底層多Redis服務器連接的細節,該對象的連接建立被設計成可以被客戶端多個調用者之間共享及復用。因此,不必在每次對redis操作時建立新的ConnectionMultiplexer對象。與此同時,該對象的操作被設計成線程安全的。為了建立到Redis server的連接,我們可以使用如下的方式:
ConnectionMultiplexer con = ConnectionMultiplexer.Connect("localhost:6379"),redis server默認端口為6379.
為了復用ConnectionMultiplexer對象,我們可以通過定義靜態的屬性,通過返回ConnectionMultiplexer的實例來使用該對象。接下來我們寫個簡單的單例模式來獲取ConnectionMultiplexer對象。代碼如下:
public class RedisConnection { private static readonly Lazy<ConnectionMultiplexer> _connection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect("localhost:6379")); public static ConnectionMultiplexer Connection { get { return _connection.Value; } } }
通過墮式加載的方式來創建ConnectionMultiplexer實例,該實例的初始化的創建是線程安全的。
接下來我們通過定義個簡單的client來測試對redis 服務器的讀寫操作。
class Program { static void Main(string[] args) { ConnectionMultiplexer con = RedisConnection.Connection; IDatabase db = con.GetDatabase();//默認是連接到數據庫0 db.StringSet("name", "tom"); string value = db.StringGet("name"); Console.WriteLine("name:"+value); } }
程序的執行結果為:name:tom.
接下來我們寫一個簡單的對象在redis中的存儲。
首先我們定義一個Student類:
public class Student { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string School { get; set; } }
因為redis在存儲對象前需要首先將對象進行序列化,讀取對象時需要進行反序列話,接下來,我們將定義兩個IDatabase的擴展方法。
public static class RedisExtension { public static TResult Get<TResult>(this IDatabase cache, string key) { return Deserialize<TResult>(cache.StringGet(key)); } public static void Set<TIn>(this IDatabase cache, string key, TIn value) { cache.StringSet(key, Serialize(value)); } static byte[] Serialize(object o) { if (o == null) return null; BinaryFormatter binaryFormatter = new BinaryFormatter(); using (MemoryStream mStream = new MemoryStream()) { binaryFormatter.Serialize(mStream,o); byte[] objectDataAsStream = mStream.ToArray(); return objectDataAsStream; } } static TResult Deserialize<TResult>(byte[] stream) { if (stream == null) return default(TResult); BinaryFormatter formatter = new BinaryFormatter(); using (MemoryStream memStream = new MemoryStream(stream)) { TResult result = (TResult)formatter.Deserialize(memStream); return result; } } }
接下來我們在定義一個Client來測試redis對象的讀寫的使用:
class Program { static void Main(string[] args) { ConnectionMultiplexer con = RedisConnection.Connection; IDatabase db = con.GetDatabase(); Student st = new Student { Age = 12, Name = "tom", School = "mit" }; db.Set("student", st); Console.WriteLine("name:" + st.Name + " Age:" + st.Age); } }
運行程序后,程序拋出異常,提示Student沒有表示Serializable,在Student類上加上[Serializable]屬性后,運行程序后,結果輸出:name:tom Age:12。
接下來我們在寫個簡單的web api 的例子來演示redis作為緩存在web api中的使用,基本上與c# console中使用redis相同,除了在對象的返回上需要做些額外的處理。
在VS中新建一個web api項目后,我們簡單的建一個StudentController。
在該例子中使用的類方法的調用與前面的例子是一樣的。並且為了方便,我將所有的操作都寫在了Controller中。
namespace MvcApplication3.Controllers { public class StudentController :ApiController { public Student Get(int id) { string cacheKey = "GetStudent:" + id; ConnectionMultiplexer con = RedisConnection.Connection; IDatabase db = con.GetDatabase(1); Student stObj = db.Get<Student>(cacheKey); if (stObj != null) { return stObj; } Student st = new Student { Id = 1, Age = 12, Name = "tom", School = "ustc" }; db.Set(cacheKey,st); return st; } } }
我們通過fiddler來查看服務器端返回的對象結果。在url框中輸入:http://localhost:8536/api/Student/1,查看服務器端返回的JSON數據結果:
我們可以看到了返回的字段的信息,這其實並不是我們期望的信息,因為我們在定義Sudent類的時候使用的是自動的set get屬性,在c#編譯器編譯成il代碼時會生成對應屬性的字段的信息,這些生成的字段名字就是上圖對應的信息。默認情況下,web api會在對象返回前對對象字段及自動屬性進行序列化,當我們為類表示[Serializable]屬性時,只會序列化字段信息,為了序列化對應的屬性,返回我們需要的信息我們需要定義如下的Student類:
[Serializable] [DataContract] public class Student { [DataMember] public int Id { get; set; } [DataMember] public string Name { get; set; } [DataMember] public int Age { get; set; } [DataMember] public string School { get; set; } }
這時,我們在運行應用,輸入url:http://localhost:8536/api/Student/1,返回的Json數據如下:
得到了我們需要的結果,當然,在web api中我們也可以通過如下的方式。是默認的json序列化器忽略[Serializable]屬性:
通過在Global.aspx的App_start方法中進行如下設置:
var serializerSettings = GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings; var contractResolver = (DefaultContractResolver)serializerSettings.ContractResolver; contractResolver.IgnoreSerializableAttribute = true;
至此,redis的在c#中的簡單運用就介紹到這!

