/// <summary> /// 发送消息到队列,使用List实现,有重复 /// (过期时间为整个Key内的所有消息过期,从第一个消息的Key开始) /// </summary> /// <param name="queueKeyPrefix">队列Key前缀</param> /// <param name="msg">发送的消息</param> /// <param name="keyExpiryTimeType">Key过期时间类型,默认为小时</param> /// <param name="expiryTimes">key过期时间类型的倍数,如过期时间是按小时,则表示多少小时后过期</param> /// <returns>返回是否发送成功</returns> private async Task <bool> SendQueueWithKeyExpiryAsync(string queueKeyPrefix, string msg, KeyExpiryTimeType keyExpiryTimeType = KeyExpiryTimeType.Hours, int expiryTimes = 2, CancellationToken token = default) { if (string.IsNullOrEmpty(msg)) { throw new ArgumentNullException($"please set param {nameof(msg)}!"); } if (expiryTimes <= 1) { throw new ArgumentNullException($"param {nameof(expiryTimes)} must be greater than 1 !"); } TimeSpan expiry = GetKeyExpiryTime(keyExpiryTimeType, expiryTimes); //lock (lockObj) using (await ListWriteSyncSemaphore.LockAsync(token)) { RedisKey queueKey = GetQueueKey(keyExpiryTimeType, RedisDataType.List, queueKeyPrefix); var keyExists = await redis.GetDatabase().KeyExistsAsync(queueKey); RedisValue queueItems = msg; //var aaa = redis.GetDatabase().List(queueKey, queueItems, When.NotExists); var when = When.Always;//List 不能用NotExists var pushResult = await redis.GetDatabase().ListLeftPushAsync(queueKey, queueItems, when); if (!keyExists && pushResult > 0) { await redis.GetDatabase().KeyExpireAsync(queueKey, expiry); } return(pushResult > 0); } }
/// <summary> /// 发送消息到排序队列,使用ZSET,同一Key内无重复 /// 排序按照时间戳升序 /// (过期时间为整个Key内的所有消息过期,从第一个消息的Key开始) /// </summary> /// <param name="queueKeyPrefix">队列Key前缀</param> /// <param name="msg">发送的消息</param> /// <param name="expiryHours">过期小时</param> /// <returns>返回是否发送成功</returns> private async Task <bool> SendSortQueueWithKeyExpiryAsync( string queueKeyPrefix, string msg, KeyExpiryTimeType keyExpiryTimeType = KeyExpiryTimeType.Hours, int expiryTimes = 2, CancellationToken token = default) { if (string.IsNullOrEmpty(msg)) { throw new ArgumentNullException($"please set param {nameof(msg)}!"); } if (expiryTimes <= 1) { throw new ArgumentNullException($"param {nameof(expiryTimes)} must be greater than 1 !"); } TimeSpan expiry = GetKeyExpiryTime(keyExpiryTimeType, expiryTimes); //lock (lockObj) using (await ZSetWriteSyncSemaphore.LockAsync(token)) { RedisKey queueKey = GetQueueKey(keyExpiryTimeType, RedisDataType.ZSet, queueKeyPrefix); RedisValue queueItems = msg; var score = DateTime.Now.Ticks; var when = When.NotExists; var keyExists = await redis.GetDatabase().KeyExistsAsync(queueKey); var addResult = await redis.GetDatabase().SortedSetAddAsync(queueKey, queueItems, score, when); if (!keyExists && addResult) { await redis.GetDatabase().KeyExpireAsync(queueKey, expiry); } return(addResult); } }
/// <summary> /// 发送消息到排序队列,使用ZSET,同一Key内无重复 /// 排序按照时间戳升序 /// (过期时间为整个Key内的所有消息过期,从第一个消息的Key开始) /// </summary> /// <param name="queueKeyPrefix">队列Key前缀</param> /// <param name="msg">发送的消息</param> /// <param name="keyExpiryTimeType">Key过期时间类型,默认为小时</param> /// <param name="expiryTimes">key过期时间类型的倍数,如过期时间是按小时,则表示多少小时后过期</param> /// <returns>返回是否发送成功</returns> private bool SendSortQueueWithKeyExpiry(string queueKeyPrefix, string msg, KeyExpiryTimeType keyExpiryTimeType = KeyExpiryTimeType.Hours, int expiryTimes = 2) { if (string.IsNullOrEmpty(msg)) { throw new ArgumentNullException($"please set param {nameof(msg)}!"); } if (expiryTimes <= 1) { throw new ArgumentNullException($"param {nameof(expiryTimes)} must be greater than 1 !"); } TimeSpan expiry = GetKeyExpiryTime(keyExpiryTimeType, expiryTimes); lock (ZSetWriteObj) { RedisKey queueKey = GetQueueKey(keyExpiryTimeType, RedisDataType.ZSet, queueKeyPrefix); var keyExists = redis.GetDatabase().KeyExists(queueKey); RedisValue queueItems = msg; var score = DateTime.Now.Ticks; var when = When.NotExists; var addResult = redis.GetDatabase().SortedSetAdd(queueKey, queueItems, score, when); if (!keyExists && addResult) { redis.GetDatabase().KeyExpire(queueKey, expiry); } return(addResult); } }
private string GetQueueKeyPattern(KeyExpiryTimeType keyExpiryTimeType, RedisDataType redisDataType, string queueKeyPrefix) { var queueKeyPattern = queueKeyPrefix + (redisDataType == RedisDataType.List ? listQueueKeyPrefix : zsetQueueKeyPrefix); var timesNodeStr = "Hours"; var timesFormatKeySuffix = ""; if (keyExpiryTimeType == KeyExpiryTimeType.Hours) { timesNodeStr = "Hours"; timesFormatKeySuffix = hoursFormatKeySuffix.Replace("yyyy", "*"). Replace("MM", "*"). Replace("dd", "*"). Replace("HH", "*") ; } else if (keyExpiryTimeType == KeyExpiryTimeType.Minutes) { timesNodeStr = "Minutes"; timesFormatKeySuffix = minutesFormatKeySuffix.Replace("yyyy", "*"). Replace("MM", "*"). Replace("dd", "*"). Replace("HH", "*").Replace("mm", "*"); } queueKeyPattern += timesNodeStr + ":" + timesFormatKeySuffix; return(queueKeyPattern); }
/// <summary> /// 接收队列消息 /// (过期时间为整个Key内的所有消息过期,从第一个消息的Key开始) /// </summary> /// <param name="queueKeyPrefix">队列Key前缀</param> /// <param name="count">获取消息数量</param> /// <returns>返回消息列表</returns> private List <string> GetMessageByKeyExpiry(string queueKeyPrefix, int count = 1, KeyExpiryTimeType keyExpiryTimeType = KeyExpiryTimeType.Hours ) { if (count <= 0) { throw new ArgumentNullException($"param {nameof(count)} must be greater than 0 !"); } var msgList = new List <string>(); var queueKeyPattern = GetQueueKeyPattern(keyExpiryTimeType, RedisDataType.List, queueKeyPrefix); var keyList = GetkeysByPrefix(queueKeyPattern); foreach (var item in keyList) { RedisKey queueKey = item; var keyExists = redis.GetDatabase().KeyExists(queueKey); if (!keyExists) { continue; } while (msgList.Count < count && redis.GetDatabase().ListLength(queueKey) > 0) { var msgV = redis.GetDatabase().ListRightPop(queueKey); msgList.Add(msgV); if (msgList.Count == count) { return(msgList); } } } return(msgList); }
/// <summary> /// 发送消息到队列,使用List实现,有重复 /// (过期时间为整个Key内的所有消息过期,从第一个消息的Key开始) /// </summary> /// <param name="queueKeyPrefix">队列Key前缀</param> /// <param name="msg">发送的消息</param> /// <param name="keyExpiryTimeType">Key过期时间类型,默认为小时</param> /// <param name="expiryTimes">key过期时间类型的倍数,如过期时间是按小时,则表示多少小时后过期</param> /// <returns>返回是否发送成功</returns> private bool SendQueueWithKeyExpiry(string queueKeyPrefix, string msg, KeyExpiryTimeType keyExpiryTimeType = KeyExpiryTimeType.Hours, int expiryTimes = 2) { if (string.IsNullOrEmpty(msg)) { throw new ArgumentNullException($"please set param {nameof(msg)}!"); } if (expiryTimes <= 1) { throw new ArgumentNullException($"param {nameof(expiryTimes)} must be greater than 1 !"); } TimeSpan expiry = GetKeyExpiryTime(keyExpiryTimeType, expiryTimes); lock (ListWriteObj) { RedisKey queueKey = GetQueueKey(keyExpiryTimeType, RedisDataType.List, queueKeyPrefix); var keyExists = redis.GetDatabase().KeyExists(queueKey); RedisValue queueItems = msg; //var aaa = redis.GetDatabase().List(queueKey, queueItems, When.NotExists); var when = When.Always;//List 不能用NotExists var pushResult = redis.GetDatabase().ListLeftPush(queueKey, queueItems, when); if (!keyExists && pushResult > 0) { redis.GetDatabase().KeyExpire(queueKey, expiry); } return(pushResult > 0); } }
private TimeSpan GetKeyExpiryTime(KeyExpiryTimeType keyExpiryTimeType, int expiryTimes) { TimeSpan expiry = TimeSpan.FromHours(expiryTimes); if (keyExpiryTimeType == KeyExpiryTimeType.Hours) { expiry = TimeSpan.FromHours(expiryTimes); } else if (keyExpiryTimeType == KeyExpiryTimeType.Minutes) { expiry = TimeSpan.FromMinutes(expiryTimes); } return(expiry); }
/// <summary> /// 接收队列消息 /// (过期时间为整个Key内的所有消息过期,从第一个消息的Key开始) /// </summary> /// <param name="queueKeyPrefix">队列Key前缀</param> /// <param name="count">获取消息数量</param> /// <returns>返回消息列表</returns> private async Task <List <string> > GetMessageByKeyExpiryAsync(string queueKeyPrefix, int count = 1, KeyExpiryTimeType keyExpiryTimeType = KeyExpiryTimeType.Hours) { if (count <= 0) { throw new ArgumentNullException($"param {nameof(count)} must be greater than 0 !"); } var msgList = new List <string>(); var queueKeyPattern = GetQueueKeyPattern(keyExpiryTimeType, RedisDataType.List, queueKeyPrefix); #if NETCOREAPP3_0 || NETCOREAPP3_1 var keyList = await GetkeysByPrefixAsync(queueKeyPattern); #else var keyList = GetkeysByPrefix(queueKeyPattern); #endif foreach (var item in keyList) { RedisKey queueKey = item; var keyExists = await redis.GetDatabase().KeyExistsAsync(queueKey); if (!keyExists) { continue; } while (msgList.Count < count && (await redis.GetDatabase().ListLengthAsync(queueKey)) > 0) { var msgV = await redis.GetDatabase().ListRightPopAsync(queueKey); /* * var startIndex = 0; * var endIndex = count - 1; * var msgVList =await redis.GetDatabase().ListRangeAsync(queueKey,startIndex,endIndex); */ msgList.Add(msgV); if (msgList.Count == count) { return(msgList); } } } return(msgList); }
private RedisKey GetQueueKey(KeyExpiryTimeType keyExpiryTimeType, RedisDataType redisDataType, string queueKeyPrefix) { var currentTime = DateTime.Now.ToString(hoursFormatKeySuffix); var timesNodeStr = "Hours"; if (keyExpiryTimeType == KeyExpiryTimeType.Hours) { currentTime = DateTime.Now.ToString(hoursFormatKeySuffix); timesNodeStr = "Hours"; } else if (keyExpiryTimeType == KeyExpiryTimeType.Minutes) { currentTime = DateTime.Now.ToString(minutesFormatKeySuffix); timesNodeStr = "Minutes"; } RedisKey queueKey = queueKeyPrefix + (redisDataType == RedisDataType.List? listQueueKeyPrefix:zsetQueueKeyPrefix) + timesNodeStr + ":" + currentTime; return(queueKey); }
/// <summary> /// 接收排序队列消息 /// (过期时间为整个Key内的所有消息过期,从第一个消息的Key开始) /// </summary> /// <param name="queueKeyPrefix">队列Key前缀</param> /// <param name="count">获取消息数量</param> /// <param name="keyExpiryTimeType">Key过期时间类型,默认为小时</param> /// <returns>返回消息列表</returns> private async Task <List <string> > GetSortMessageByKeyExpiryAsync( string queueKeyPrefix, int count = 1, KeyExpiryTimeType keyExpiryTimeType = KeyExpiryTimeType.Hours, CancellationToken token = default) { bool getBySingle = false; var msgList = new List <string>(); if (count <= 0) { throw new ArgumentNullException($"param {nameof(count)} must be greater than 0 !"); } var queueKeyPattern = GetQueueKeyPattern(keyExpiryTimeType, RedisDataType.ZSet, queueKeyPrefix); #if NETCOREAPP3_0 || NETCOREAPP3_1 var keyList = await GetkeysByPrefixAsync(queueKeyPattern); #else var keyList = GetkeysByPrefix(queueKeyPattern); #endif foreach (var item in keyList) { RedisKey queueKey = item; var keyExists = redis.GetDatabase().KeyExists(queueKey); if (!keyExists) { continue; } while (msgList.Count < count && (await redis.GetDatabase().SortedSetLengthAsync(queueKey)) > 0) { //ZPOPMIN命令需要Redis 5及以上版本SortedSetPop方法 //redis.GetDatabase().SortedSetScan(queueKey,, Order.Ascending); if (getBySingle) { if (RedisServerVersion < new Version("5.0.0")) { var startIndex = 0; var endIndex = 0; var vList = await redis.GetDatabase().SortedSetRangeByRankAsync(queueKey, startIndex, endIndex, Order.Ascending); if (vList == null || vList.Count() == 0) { break; } var msgV = vList.FirstOrDefault(); msgList.Add(msgV); await redis.GetDatabase().SortedSetRemoveAsync(queueKey, msgV); } else { var sortedSetEntry = await redis.GetDatabase().SortedSetPopAsync(queueKey, Order.Ascending); if (!sortedSetEntry.HasValue) { break; } var msgV = sortedSetEntry.Value.Element; msgList.Add(msgV); } if (msgList.Count == count) { return(msgList); } } else { var getCount = count - msgList.Count; if (getCount == 0) { return(msgList); } if (RedisServerVersion < new Version("5.0.0")) { using (await ZSetReadSyncSemaphore.LockAsync(token)) { var startIndex = 0; var endIndex = getCount - 1; var vList = await redis.GetDatabase().SortedSetRangeByRankAsync(queueKey, startIndex, endIndex, Order.Ascending); if (vList == null || vList.Count() == 0) { break; } await redis.GetDatabase().SortedSetRemoveAsync(queueKey, vList); foreach (var msgV in vList) { msgList.Add(msgV); //await redis.GetDatabase().SortedSetRemoveAsync(queueKey, msgV); } } } else { var sortedSetEntryList = await redis.GetDatabase().SortedSetPopAsync(queueKey, getCount, Order.Ascending); if (sortedSetEntryList == null || sortedSetEntryList.Length == 0) { break; } foreach (var sortedSetEntry in sortedSetEntryList) { var msgV = sortedSetEntry.Element; msgList.Add(msgV); } } if (msgList.Count == count) { return(msgList); } } } } return(msgList); }
/// <summary> /// 接收排序队列消息 /// (过期时间为整个Key内的所有消息过期,从第一个消息的Key开始) /// </summary> /// <param name="queueKeyPrefix">队列Key前缀</param> /// <param name="count">获取消息数量</param> /// <param name="keyExpiryTimeType">Key过期时间类型,默认为小时</param> /// <returns>返回消息列表</returns> private List <string> GetSortMessageByKeyExpiry( string queueKeyPrefix, int count = 1, KeyExpiryTimeType keyExpiryTimeType = KeyExpiryTimeType.Hours ) { bool getBySingle = false; var msgList = new List <string>(); if (count <= 0) { throw new ArgumentNullException($"param {nameof(count)} must be greater than 0 !"); } var queueKeyPattern = GetQueueKeyPattern(keyExpiryTimeType, RedisDataType.ZSet, queueKeyPrefix); var keyList = GetkeysByPrefix(queueKeyPattern); foreach (var item in keyList) { RedisKey queueKey = item; var keyExists = redis.GetDatabase().KeyExists(queueKey); if (!keyExists) { continue; } while (msgList.Count < count && redis.GetDatabase().SortedSetLength(queueKey) > 0) { //ZPOPMIN命令需要Redis 5及以上版本SortedSetPop方法 //redis.GetDatabase().SortedSetScan(queueKey,, Order.Ascending); if (getBySingle) { if (RedisServerVersion < new Version("5.0.0")) { var startIndex = 0; var endIndex = 0; var vList = redis.GetDatabase().SortedSetRangeByRank(queueKey, startIndex, endIndex, Order.Ascending); if (vList == null || vList.Count() == 0) { break; } var msgV = vList.FirstOrDefault(); msgList.Add(msgV); redis.GetDatabase().SortedSetRemove(queueKey, msgV); } else { var sortedSetEntry = redis.GetDatabase().SortedSetPop(queueKey, Order.Ascending); if (!sortedSetEntry.HasValue) { break; } var msgV = sortedSetEntry.Value.Element; msgList.Add(msgV); } if (msgList.Count == count) { return(msgList); } } else { var getCount = count - msgList.Count; if (getCount == 0) { return(msgList); } if (RedisServerVersion < new Version("5.0.0")) { lock (ZSetReadObj) { var startIndex = 0; var endIndex = getCount - 1; var vList = redis.GetDatabase().SortedSetRangeByRank(queueKey, startIndex, endIndex, Order.Ascending); if (vList == null || vList.Count() == 0) { break; } redis.GetDatabase().SortedSetRemove(queueKey, vList); foreach (var msgV in vList) { msgList.Add(msgV); //redis.GetDatabase().SortedSetRemove(queueKey, msgV); } } } else { var sortedSetEntryList = redis.GetDatabase().SortedSetPop(queueKey, getCount, Order.Ascending); if (sortedSetEntryList == null || sortedSetEntryList.Length == 0) { break; } foreach (var sortedSetEntry in sortedSetEntryList) { var msgV = sortedSetEntry.Element; msgList.Add(msgV); } } if (msgList.Count == count) { return(msgList); } } } } return(msgList); }