首頁  >  文章  >  資料庫  >  Redis該怎麼使用

Redis該怎麼使用

WBOY
WBOY轉載
2023-06-03 12:48:001151瀏覽

使用場景

在我的專案裡,有一個提供給Autocomplete的功能,資料量大概在幾萬。這篇文章裡我用名字檢索的例子來說明,列表請戳來自Redis作者的Demo。

在這樣的列表裡全是用戶名,例如我們的系統裡有一個用戶對象:

public Class User
{     public string Id{get; set;}  
     public string Name {get; set;}
     ....     public string UserHead {get; set;}    
}

系統裡需要一個用戶的下拉列表,由於數據量大不能一次顯示完,於是就加上了一個AutoComplete功能。快取可以在本地記憶體中直接存儲,不必使用像Redis這樣的集中式緩存,這樣快取結構會更加簡單

var users = new List<User>{...};//读到一个用户列表MemoryCache.Set("capqueen:users", users);//放入内存//读取var users = MemoryCache.Get<List<User>>("capqueen:users");

因為都是在記憶體裡,所以直接存List就可以了,搜尋的時候也可以直接的如下:

var findUsers = users.Where(user => user.Name.StartWith("A")).ToList();例如输入的字符是 “A“

相當簡單,完全不用考慮如何存儲,儲存的資料結構。然而,一旦轉向使用Redis這樣的集中式快取服務,我們需要重新考慮如何儲存。

方案一:類似記憶體式的快取實作。

本文所使用的Redis連結函式庫是StactkExchange.Redis,出自StackOverFlow的開源產品。

var db = redis.GetDataBase();//获取0数据库var usersJson = JsonConvert.SerializeObject(users)//序列化db.StringSet("capqueen:users", usersJson);//存储var usersString = db.StringGet("capqueen:users");
var userList = JsonConvert.DeserializeObject<List<User>>(users);//反序列化

上面的方式邏輯上是沒有問題的,編譯也可以通過。但仔細想想,Redis作為獨立的快取服務和appSever是分開來的,這樣的讀取方式對redis伺服器的IO是個負擔,甚至這樣的讀取比本地記憶體快取慢了太多了。

那要如何解決呢?試想key-value的精髓是在於Key,那麼對於List來說應該要把item分開來存放。

方案二:Keys模糊匹配。

在翻閱Redis的指令文件(見參考資料4)後,他驚訝地發現了Keys指令,這讓他立刻修改了自己的方案。首先我們需要把要搜尋的關鍵字建立為key,這裡我把key定義為 "capqueen:user:{id}:{name}",其中{}內的是要用item對應屬性取代的。程式碼如下:

var redis = ConnectionMultiplexer.Connect("localhost");var db = redis.GetDatabase();           
var users = new List<User> { new User{Id = 6, Name = "aaren", Age=10},    new User{Id = 7, Name = "issy", Age=11},    new User{Id = 8, Name = "janina", Age=13},    new User{Id = 9, Name = "karena", Age=14}
};

users.ForEach(item => { 
   var key = string.Format("capqueen:user:{0}:{1}", item.Id, item.Name);   var value = JsonConvert.SerializeObject(item);
   db.StringSet(key, value);
});

所有的user都以單獨的Key-Value方式存儲,那麼如何利用Keys搜尋呢?我們來看下Redis的Keys指令:

KEYS pattern

查找所有符合给定模式 pattern 的 key 。

KEYS * 匹配数据库中所有 key 。
KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
KEYS h*llo 匹配 hllo 和 heeeeello 等。
KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo 。
特殊符号用 \ 隔开

也就是說Keys能夠進行簡單的模糊匹配,那麼我們這裡的搜尋就可以換成如下的方式:

var redis = ConnectionMultiplexer.Connect("192.168.10.178");var db = redis.GetDatabase();var server = redis.GetServer("192.168.10.178", 6379);var keys = server.Keys(pattern: "capqueen:user:*:a*");var values = db.StringGet(keys.ToArray());//反序列化var jsonValues = new StringBuilder("[");
values.ToList().ForEach(item => jsonValues.Append(item).Append(","));
jsonValues.Append("]");var userList = JsonConvert.DeserializeObject<List<User>>(jsonValues.ToString());

注意以上的程式碼裡,因為每個value都是一個json,為了增加轉換時的效率,我先處理成json arry再進行反序列化。

這個方案,確實是解決了我目前的問題,然而我注意到了Redis文檔裡的一段話:

KEYS 的速度非常快,但在一個大的資料庫中使用它仍然可能造成效能問題,如果你需要從一個資料集中尋找特定的key ,你最好還是用Redis 的集合結構(set)來取代。

以上是Redis該怎麼使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除