如何在 .NET 程式中使用 Redis 做為 Cache Server - Part 3 (使用 Lists 型別)

先前文章 如何在 .NET 程式中使用 Redis 做為 Cache Server - Part 2 (使用 Hashes 型別) 使用了 Hashed 型別來 cache 資料,但總覺得不太清楚各型別間的差異加上 Redis 型別不多,打算每個來用用看,再好好比較一番

基礎建設

  1. 處理 redis 連線 factory

    • 使用 StackExchange.Redis 套件,記得 nuget 安裝

      public static class RedisConnectionFactory
      {
          private static readonly Lazy<ConnectionMultiplexer> Connection;
          static RedisConnectionFactory()
          {
              var connectionString = "localhost:6379";
              var options = ConfigurationOptions.Parse(connectionString);
              Connection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(options));
          }
          public static ConnectionMultiplexer GetConnection => Connection.Value;
          public static IDatabase RedisDB => GetConnection.GetDatabase();
      }
      
  2. 測試用自訂 class

    public class Person
    {
        public string ID{ get; set; }
            
        public string Name { get; set; }
        
        public string Tel { get; set; }
    }
    
  3. 存取 redis 用的 object

    IDatabase _db = RedisConnectionFactory.RedisDB;
    
  4. 製造假資料

    Dictionary<string, List<Person>> peopleDic = new Dictionary<string, List<Person>>();
    for (int i = 0; i < 3; i++)
    {
        var _id = Guid.NewGuid().ToString();
        List<Person> people = new List<UserQuery.Person>();
        for (int j = 0; j < 3; j++)
        {
            people.Add((new Person { ID = $"{i}_{j}_ID", Name = $"{i}_{j}_yowko", Tel = $"{i}_{j}_0123456789" }));
        }
        peopleDic.Add(_id, people);
    }
    
  5. 使用 batch 來批次處理指令

    var batch = _db.CreateBatch();
    

使用 Lists 型別

相關指令介紹

指令參數對應 StackExchange.Redis 指令說明
BLPOPkey [key …] timeout-刪除並取得該 list 中的第一元素,或 blocking 直到有一個可用
BRPOPkey [key …] timeout-刪除並取得該 list 中的最後一個元素,或 blocking 直到有一個可用
BRPOPLPUSHsource destination timeout-取出一個list 的值,將它推到另一個 list,並傳回它;或 blocking 直到有一個可用
LINDEXkey indexListGetByIndex|ListGetByIndexAsync使用 index 取得一個元素
LINSERTkey BEFORE|AFTER pivot valueListInsertAfter|ListInsertAfterAsync
|ListInsertBefore|ListInsertBeforeAsync
在 list 中的另一個元素之前或之後插入一個元素
LLENkeyListLength|ListLengthAsync取得 List的長度
LPOPkeyListLeftPop|ListLeftPopAsync從 list 的左邊取出一個元素
LPUSHkey value [value …]ListLeftPush|ListLeftPushAsync從 list 的左邊插入一個或多個元素
LPUSHXkey valueListLeftPush|ListLeftPushAsync當 list 存在時,從 list 左邊插入一個元素
LRANGEkey start stopListRange|ListRangeAsync從 list 中獲取指定返回的元素
LREMkey count valueListRemove|ListRemoveAsync從 list 中刪除元素
LSETkey index valueListSetByIndex|ListSetByIndexAsync設置 list 裡面一個元素的值
LTRIMkey start stopListTrim|ListTrimAsync刪除到指定範圍內的清單
RPOPkeyListRightPop|ListRightPopAsync從 list 的右邊取出一個元
RPOPLPUSHsource destinationListRightPopLeftPush|ListRightPopLeftPushAsync刪除 list 中的最後一個元素,將其加到另一個 list
RPUSHkey value [value …]ListRightPush|ListRightPushAsync從 list 的右邊插入一個元素
RPUSHXkey valueListRightPush|ListRightPushAsync從 list 的右邊插入一個元素,僅 list 存在時有效

實際使用

  • 範例程式碼

    var batch = _db.CreateBatch();
    foreach (var item in peopleDic)
    {
        foreach (var element in item.Value)
        {
            _db.ListRightPushAsync(item.Key, JsonConvert.SerializeObject(element));
        }
    }
    batch.Execute();
    
  • 儲存狀況

    1result

完整程式碼

void Main()
{
	IDatabase _db = RedisConnectionFactory.RedisDB;
	Dictionary<string, List<Person>> peopleDic = new Dictionary<string, List<Person>>();
	for (int i = 0; i < 3; i++)
	{
		var _id = Guid.NewGuid().ToString();
		List<Person> people = new List<UserQuery.Person>();
		for (int j = 0; j < 3; j++)
		{
			people.Add((new Person { ID = $"{i}_{j}_ID", Name = $"{i}_{j}_yowko", Tel = $"{i}_{j}_0123456789" }));
		}
		peopleDic.Add(_id, people);
	}
	var batch = _db.CreateBatch();
	foreach (var item in peopleDic)
	{
		foreach (var element in item.Value)
		{
			_db.ListRightPushAsync(item.Key, JsonConvert.SerializeObject(element));
		}
	}
	batch.Execute();
}

public class Person 
{
	public string ID { get; set; }

	public string Name { get; set; }

	public string Tel { get; set; }
}

public static class RedisConnectionFactory
{
	private static readonly Lazy<ConnectionMultiplexer> Connection;
	static RedisConnectionFactory()
	{
		var connectionString = "localhost:6379";
		var options = ConfigurationOptions.Parse(connectionString);
		Connection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(options));
	}
	public static ConnectionMultiplexer GetConnection => Connection.Value;
	public static IDatabase RedisDB => GetConnection.GetDatabase();
}

參考資料

  1. Redis - LIST
  2. GitHub - StackExchange.Redis