一篇學會 C# Redis list 當作隊列使用
本文轉載自微信公眾號「后端Q」,作者conan 。轉載本文請聯系后端Q公眾號。
Redis的列表經常被用作隊列,用于在不同程序之間有序地交換消息。一個客戶端通過 LPUSH 命令將消息放入隊列中,而另一個客戶端通過 RPOP 或者 BRPOP 命令取出隊列中等待時間最長的消息。
對于c# 方法
- using (var redisClent = RedisManager.GetClient())
- {
- while (true)
- {
- if ((DateTime.Now - date).TotalSeconds > maxSeconds)
- break;
- var infoJson = redisClent.DequeueItemFromList(CacheKeys.UploadLoginTimeQueue);
- if (string.IsNullOrWhiteSpace(infoJson) || string.IsNullOrEmpty(infoJson))
- break;
- var info = JsonConvert.DeserializeObject<LoginTimeUpdate>(infoJson);
- UpdateLoginTime(info);
- }
- }
- client = RedisManager.GetClient();
- if (!client.Get<bool>(key))
- {
- client.Set(key, true, DateTime.Now.Date.AddDays(1).AddSeconds(-1));
- }
- var jsonObj = JsonConvert.SerializeObject(info);
- client.EnqueueItemOnList(CacheKeys.UploadLoginTimeQueue, jsonObj);
命令
- redis 127.0.0.1:6379> LPUSH runoobkey redis
- (integer) 1
- redis 127.0.0.1:6379> LPUSH runoobkey mongodb
- (integer) 2
- redis 127.0.0.1:6379> LPUSH runoobkey mysql
- (integer) 3
- redis 127.0.0.1:6379> LRANGE runoobkey 0 10
- 1) "mysql"
- 2) "mongodb"
- 3) "redis"
問題,上面的隊列方法是『不安全』的,因為在這個過程中,一個客戶端可能在取出一個消息之后崩潰,而未處理完的消息也就因此丟失。
使用 RPOPLPUSH 命令(或者它的阻塞版本 BRPOPLPUSH )可以解決這個問題:因為它不僅返回一個消息,同時還將這個消息添加到另一個備份列表當中,如果一切正常的話,當一個客戶端完成某個消息的處理之后,可以用 LREM 命令將這個消息從備份表刪除。
最后,還可以添加一個客戶端專門用于監視備份表,它自動地將超過一定處理時限的消息重新放入隊列中去(負責處理該消息的客戶端可能已經崩潰),這樣就不會丟失任何消息了。