.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>();

源码

官网

相关推荐
爱的叹息2 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring
松韬3 小时前
Spring + Redisson:从 0 到 1 搭建高可用分布式缓存系统
java·redis·分布式·spring·缓存
天上掉下来个程小白3 小时前
Redis-14.在Java中操作Redis-Spring Data Redis使用方式-操作列表类型的数据
java·redis·spring·springboot·苍穹外卖
·云扬·3 小时前
深度剖析 MySQL 与 Redis 缓存一致性:理论、方案与实战
redis·mysql·缓存
汤姆大聪明4 小时前
Redisson 操作 Redis Stream 消息队列详解及实战案例
redis·spring·缓存·maven
全栈小59 小时前
【C#】.net core 6.0 依赖注入常见问题之一,在构造函数使用的类,都需要注入到容器里,否则会提示如下报错,让DeepSeek找找原因,看看效果
c#·.netcore·依赖注入·deepseek
csjane107918 小时前
Redis原理:rename命令
java·redis
Chandler241 天前
Redis:内存淘汰原则,缓存击穿,缓存穿透,缓存雪崩
数据库·redis·缓存
❀͜͡傀儡师1 天前
多台服务器上docker部署 Redis 集群
运维·服务器·redis
Foyo Designer1 天前
【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的国际化:支持多语言的 RESTful API
java·spring boot·redis·后端·spring·缓存·restful