.net core Redis 使用有序集合实现延迟队列

Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。

不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。

有序集合的成员是唯一的,但分数(score)却可以重复。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

延迟队列的设计思想是将队列的延迟时间作为分数,按照这个进行排序

  1. 安装依赖
bash 复制代码
Newtonsoft.Json             13.0.3   
StackExchange.Redis         2.8.0 
  1. 封装Redis
csharp 复制代码
using StackExchange.Redis;
namespace LedayQueue.RedisHelper
{
    public class RedisConnection
    {
        private readonly ConnectionMultiplexer _connection;
        public IDatabase _database;

        public RedisConnection()
        {
            _connection = ConnectionMultiplexer.Connect("localhost:6379");
            _database = _connection.GetDatabase();
        }



        public async Task AddToQueueAsync(string task, TimeSpan delay)
        {
            var executionTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds() + delay.TotalSeconds;
            await _database.SortedSetAddAsync("delayedQueue", task, executionTime);
        }
    }
}
  1. 封装background service
csharp 复制代码
using StackExchange.Redis;

namespace LedayQueue.RedisHelper
{
    public class DelayedQueueProcessor : BackgroundService
    {
        private readonly RedisConnection _connection;
        private const string QueueKey = "delayedQueue";
        public DelayedQueueProcessor(RedisConnection redisConnection)
        {
            _connection = redisConnection;
        }
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
                var tasks = await _connection._database.SortedSetRangeByScoreWithScoresAsync(QueueKey, 0, now);

                foreach (var task in tasks)
                {
                    // 处理任务
                    var taskString = task.Element.ToString();
                    ProcessTask(taskString);

                    // 从队列中移除任务
                    await _connection._database.SortedSetRemoveAsync(QueueKey, task.Element);
                }

                await Task.Delay(TimeSpan.FromSeconds(1), stoppingToken); // 每秒检查一次
            }
        }

        private void ProcessTask(string content)
        {
            Console.WriteLine(content);
        }
    }
}
  1. 注册
csharp 复制代码
builder.Services.AddSingleton<RedisConnection>();
builder.Services.AddHostedService<DelayedQueueProcessor>();

源码

官网

相关推荐
movie__movie17 小时前
秒杀库存扣减可以用redis原子自增么
数据库·redis·缓存
q***428221 小时前
Redis 设置密码(配置文件、docker容器、命令行3种场景)
数据库·redis·docker
运维行者_21 小时前
网站出现 525 错误(SSL 握手失败)修复指南
服务器·网络·数据库·redis·网络协议·bootstrap·ssl
CPU NULL1 天前
Redis相关知识点总结
java·数据库·spring boot·redis·缓存
q***57501 天前
Redis服务安装自启动(Windows版)
数据库·windows·redis
LoneEon1 天前
Ubuntu 上搭建 Redis 3 节点集群(6 实例:3主3从)
数据库·redis·缓存
知其然亦知其所以然1 天前
别再被问住!Redis Cluster 一文彻底讲透(Java 面试必背)
redis·后端·面试
007php0071 天前
Redis面试题解析:Redis的数据过期策略
java·网络·redis·缓存·面试·职场和发展·php
周杰伦fans1 天前
CommunityToolkit.Mvvm(又称MVVM Toolkit) 与 MvvmLight 的核心区别
开发语言·c#·.netcore
姓蔡小朋友1 天前
redis GEO数据结构、实现附近商铺功能
数据结构·数据库·redis