展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > Redis怎么实现延迟队列

Redis怎么实现延迟队列

Redis Assistant
Redis Assistant

Redis Assistant 是一款为Redis设计的高效可视化管理与监控工具,提供多种操作模式,高效处理服务器数据。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

¥19
Windows/macOS/Linux 2026-08-22
正版软件 Windows macOS软件 Linux 数据库管理工具
立即下载

Redis实现延迟队列Redis延迟队列Redis是通过有序集合(ZSet)的方式来实现延迟消息队列的,ZSet有一个Score属性可以用来存储延迟执行的时间。但需要无限循环检查任务,会消耗系统资源classRedisDelayQueue(object):"""SimpleQueuewithRedisBackenddq=RedisDelayQueue('delay:commtrans')dq.put(5,{'info':'测试5555','time&

本文目录

      Redis实现延迟队列

      Redis延迟队列

      Redis 是通过有序集合(ZSet)的方式来实现延迟消息队列的,ZSet 有一个 Score 属性可以用来存储延迟执行的时间。

      但需要无限循环检查任务,会消耗系统资源

      class RedisDelayQueue(object):
          """Simple Queue with Redis Backend
          dq = RedisDelayQueue('delay:commtrans')
          dq.put( 5 ,{'info':'测试 5555','time': timestamp_to_datetime_str(t + 5)})
          print(dq.get())
          """
          def __init__(self, name, namespace='queue'):
              """The default connection parameters are: host='localhost', port=6379, db=0"""
              self.__db = get_redis_engine(database_name='spdb')
              self.key = '%s:%s' % (namespace, name)
          def qsize(self):
              """Return the approximate size of the queue."""
              return self.__db.zcard(self.key)
          def empty(self):
              """Return True if the queue is empty, False otherwise."""
              return self.qsize() == 0
          def rem(self, value):
              return self.__db.zrem(self.key, value)
          def get(self):
              # 获取任务,以0和当前时间为区间,返回一条在当前区间的记录
              items = self.__db.zrangebyscore(self.key, 0, int(time.time()), 0, 1)
              if items:
                  item = items[0]
                  if self.rem(item):  # 解决并发问题  如能删就让谁取走
                      return json.loads(item)
              return None
          def put(self, interval, item):
              """:param interval 延时秒数"""
              # 以时间作为score,对任务队列按时间戳从小到大排序
              """Put item into the queue."""
              d = json.dumps(item)
              return self.__db.zadd(self.key, {d: int(time.time()) + int(interval)})

      Redis实现延时队列的优化方案

      延时队列的应用

      近期在开发部门的新项目,其中有个关键功能就是智能推送,即根据用户行为在特定的时间点向用户推送相应的提醒消息,比如以下业务场景:

      • 在用户点击充值项后,半小时内未充值,向用户推送充值未完成提醒。

      • 在用户最近一次阅读行为2小时后,向用户推送继续阅读提醒。

      • 在用户新注册或退出应用N分钟后,向用户推送合适的推荐消息。

      • …

      上述场景的共同特征就是在某事件触发后延迟一定时间后再执行特定任务,若事件触发时间点可知,则上述逻辑也可等价于在指定时间点(事件触发时间点+延迟时间长度)执行特定任务。

      实现这类需求一般采用延时队列,其中创建的延时消息中需要包含任务延迟时间或任务执行时间点等信息,当任务满足时间条件需要执行时,该消息便会被消费,也就是说可以指定队列中的消息在哪个时间点被消费。

      延时队列的实现

      在单机环境中,JDK已经自带了很多能够实现延时队列功能的组件,比如DelayQueue, Timer, ScheduledExecutorService等组件,都可以较为简便地创建延时任务,但上述组件使用一般需要把任务存储在内存中,服务重启存在任务丢失风险,且任务规模体量受内存限制,同时也造成长时间内存占用,并不灵活,通常适用于单进程客服端程序中或对任务要求不高的项目中。

      在分布式环境下,仅使用JDK自带组件并不能可靠高效地实现延时队列,通常需要引入第三方中间件或框架。

      比如常见的经典任务调度框架Quartz或基于此框架的xxl-job等其它框架,这些框架的主要功能是实现定时任务或周期性任务,在Redis、RabbitMQ还未广泛应用时,譬如常见的超时未支付取消订单等功能都是由定时任务实现的,通过定时轮询来判断是否已到达触发执行的时间点。

      但由于定时任务需要一定的周期性,周期扫描的间隔时间不好控制,太短会造成很多无意义的扫描,且增大系统压力,太长又会造成执行时间误差太大,且可能造成单次扫描所处理的堆积记录数量过大。

      此外,利用MQ做延时队列也是一种常见的方式,比如通过RabbitMQ的TTL和死信队列实现消息的延迟投递,考虑到投递出去的MQ消息无法方便地实现删除或修改,即无法实现任务的取消或任务执行时间点的更改,同时也不能方便地对消息进行去重,因此在项目中并未选择使用MQ实现延时队列。

      Redis的数据结构zset,同样可以实现延迟队列的效果,且更加灵活,可以实现MQ无法做到的一些特性,因此项目最终采用Redis实现延时队列,并对其进行优化与封装。

      实现原理是利用zset的score属性,redis会将zset集合中的元素按照score进行从小到大排序,通过zadd命令向zset中添加元素,如下述命令所示,其中value值为延时任务消息,可根据业务定义消息格式,score值为任务执行的时间点,比如13位毫秒时间戳。

      zadd delayqueue 1614608094000 taskinfo

      任务添加后,获取任务的逻辑只需从zset中筛选score值小于当前时间戳的元素,所得结果便是当前时间节点下需要执行的任务,通过zrangebyscore命令来获取,如下述命令所示,其中timestamp为当前时间戳,可用limit限制每次拉取的记录数,防止单次获取记录数过大。

      zrangebyscore delayqueue 0 timestamp limit 0 1000

      在实际实现过程中,从zset中获取到当前需要执行的任务后,需要先确保将任务对应的元素从zset中删除,删除成功后才允许执行任务逻辑,这样是为了在分布式环境下,当存在多个线程获取到同一任务后,利用redis删除操作的原子性,确保只有一个线程能够删除成功并执行任务,防止重复执行。

      实际任务的执行通常会再将其发送至MQ异步处理,将“获取任务”与“执行任务”两者分离解耦,更加灵活,“获取任务”只负责拿到当前时间需要执行的任务,并不真正运行任务业务逻辑,因此只需相对少量的执行线程即可,而实际的任务执行逻辑则由MQ消费者承担,方便调控负载能力。

      整体过程如下图所示。

      Redis怎么实现延迟队列

      采用zset做延时队列的另一个好处是可以实现任务的取消和任务执行时间点的更改,只需要将任务信息从zset中删除,便可取消任务,同时由于zset拥有集合去重的特性,只需再次写入同一个任务信息,但是value值设置为不同的执行时间点,便可更改任务执行时间,实现单个任务执行时间的动态调整。

      了解实现原理后,再进行具体编程实现。创建延时任务较为简便,准备好任务消息和执行时间点,写入zset即可。获取延时任务最简单的方案是通过定时任务,周期性地执行上述逻辑,如下代码所示。

      @XxlScheduled(cron = "0/5 * * * * ?", name = "scan business1 delayqueue")
      public void scanBusiness1() {
      	// 某业务逻辑的zset延迟队列对应的key
      	String zsetKey = "delayqueue:business1";
      	while (true) {
      		// 筛选score值小于当前时间戳的元素,一次最多拉取1000条
      		Set tasks = stringRedisTemplate.opsForZSet().rangeByScore(zsetKey, 0, System.currentTimeMillis(), 0, 1000);
      		if (CollectionUtils.isEmpty(tasks)) {
      			// 当前时间下已没有需要执行的任务,结束本次扫描
      			return;
      		}
      		for (String task : tasks) {
      			// 先删除,再执行,确保多线程环境下执行的唯一性
      			Boolean delete = stringRedisTemplate.delete(task);
      			if (delete) {
      				// 删除成功后,将其再发送到指定MQ异步处理,将“获取任务”与“执行任务”分离解耦
      				rabbitTemplate.convertAndSend("exchange_business1", "routekey_business1", task);
      			}
      		}
      	}
      }

      上述方案使用xxl-job做分布式定时任务,间隔5秒执行一次,代码借助spring提供的api来完成redis和MQ的操作。

      由于是分布式定时任务,每次执行只有一个线程在获取任务,机器利用率低,当数据规模较大时,单靠一个线程无法满足吞吐量要求,因此这种方案只适用于小规模数据量级别。

      此处间隔时间也可适当调整,例如缩短为1秒,调整所需考虑原则在上文已提到:间隔太短会造成很多无意义的扫描,且增大系统压力,太长又会造成执行时间误差太大。

      为了提升整体吞吐量,考虑不使用分布式定时任务,对集群内每台机器(或实例)均设置独立的定时任务,同时采用多个zset队列,以数字后缀区分。

      假设有M个zset队列,创建延时消息时选取消息的某个ID字段,计算hash值再对M取余,根据余数决定发送到对应数字后缀的zset队列中(分散消息,此处ID字段选取需要考虑做到均匀分布,不要造成数据倾斜)。

      队列数量M的选取需要考虑机器数量N,理想情况下有多少台机器就定义多少个队列,保持M与N基本相等即可。

      因为队列太少,会造成机器对队列的竞争访问处理,队列太多又会导致任务得不到及时的处理。

      最佳实践是队列数量可动态配置,如采用分布式配置中心,这样当集群机器数量变化时,可以相应调整队列数量。

      每台机器在触发定时任务时,需要通过适当的负载均衡来决定从哪个队列拉取消息,负载均衡的好坏也会影响整个集群的效率,如果负载分布不均可能会导致多台机器竞争处理同一队列,降低效率。

      一个简单实用的做法是利用redis的自增操作再对队列数量取余即可,只要保持队列数量和机器数量基本相等,这种做法在很大程度上就可以保证不会有多台机器竞争同一队列。

      至于每台机器从对应zset中的任务获取逻辑,仍然和前面代码一致。以上方式简化实现代码如下所示。

      @Scheduled(cron = "0/5 * * * * ?")
      public void scanBusiness1() {
      	// 队列数量M,考虑动态配置,保持和机器数量基本一致
      	int M = 10;
      	// redis自增key,用于负载均衡
      	String incrKey = "incrkey:delayqueue:business1";
      	// 每台机器执行时,从不同的zset中拉取消息,尽量确保不同机器访问不同zset
      	String zsetKey = "delayqueue:business1:" + (stringRedisTemplate.opsForValue().increment(incrKey) % M);
      	while (true) {
      		// 此处逻辑和前面代码一致,省略。。。
      	}
      }

      上述方案和第一种方案的主要的不同点在于zsetKey的获取上,这里是根据负载均衡算法算出来的,确保每台机器访问不同zset并拉取消息,同时定时任务采用spring提供的进程内注解@Scheduled,集群内每台机器都会间隔5秒执行,因此相比之前的方案,能够较为明显地提升整个集群的吞吐量。

      但是这种方案的步骤相对更为复杂,需要动态配置队列数量,同时在创建延时任务时需要选择合适的消息ID字段来决定发送的目标zset队列,此处还要考虑均匀分布,整体实现要考虑的因素较多。

      上面一种方案已经能够较好地满足整体吞吐量要求,但其缺点是步骤相对复杂,因此项目中没有采用这种方案,而是采用下面一种也能满足吞吐量要求,步骤相对简单,又方便通用化的方案。

      该方案不使用定时任务,而是单独启动后台线程,在线程中执行永久循环,每次循环逻辑为:从目标zset中获取score值小于当前时间戳的元素集合中的score最小的那个元素,相当于获取当前时间点需要执行且执行时间点最早的那个任务,如果获取不到,表示当前时间点下暂无需要执行的任务,则线程休眠100ms(可视情况调整),否则,对获取到的元素进行处理,在分布式多线程环境下,仍然需要先删除成功才能进行处理。

      此外,考虑到每个线程获取元素后都需要再次访问redis尝试删除操作,为了避免多线程争抢浪费资源,降低效率,这里采用lua脚本将获取和删除操作原子化。lua脚本逻辑代码如下所示。

      local zsetKey = 'delayqueue'
      local timestamp = 1614608094000
      local items = redis.call('zrangebyscore',zsetKey,0,timestamp,'limit',0,1)
      if #items == 0 then
          return ''
      else
          redis.call('zremrangebyrank',zsetKey,0,0)
          return items[1]
      end

      其中timestamp为当前时间戳,通过在zrangebyscore命令中指定limit为1来获取score最小的元素,若获取不到,即结果集长度为0,则返回空字符串,否则,通过zremrangebyrank命令删除头部元素,即score最小的元素,也就是之前获取到的那个元素,由于redis内部保证lua脚本的原子性,上述获取并删除的操作能够运行无误。具体JAVA实现中还对其进行了多线程操作的封装和通用化的抽象,使不同业务都能够使用该组件实现延时队列。具体实现代码如下所示。

      /**
       * 基于ZSET实现消息延迟处理,score存储执行时间点,到达时间点即会向指定队列发送该消息;
       * 定义一个继承本类的bean即可;
       */
      public abstract class AbstractDelayedMsgScanTrigger implements Runnable, DisposableBean {
      	private static final RedisScript TRY_GET_AND_DEL_SCRIPT;
      	static {
      		// 获取并删除的lua脚本,使用spring提供的api
      		String sb = "local items = redis.call('zrangebyscore',KEYS[1],0,ARGV[1],'limit',0,1)\n" +
      				"if #items == 0 then\n" +
      				"\treturn ''\n" +
      				"else\n" +
      				"\tredis.call('zremrangebyrank',KEYS[1],0,0)\n" +
      				"\treturn items[1]\n" +
      				"end";
      		// 自有工具类,只要能创建出spring包下的 RedisScript 的实现类对象均可
      		TRY_GET_AND_DEL_SCRIPT = RedisScriptHelper.createScript(sb, String.class);
      	}
      	private final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(getThreadNum(), getThreadNum(),
      			0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory(getThreadNamePrefix()));
      	private volatile boolean quit = false;
      	@Autowired
      	private StringRedisTemplate stringRedisTemplate;
      	@Autowired
      	private RabbitTemplate rabbitTemplate;
      	@PostConstruct
      	public void startScan() {
      		// bean构建完成后,启动若干执行线程
      		int threadNum = getThreadNum();
      		for (int i = 0; i < threadNum; i++) {
      			EXECUTOR.execute(this);
      		}
      	}
      	@Override
      	public void run() {
      		while (!quit) {
      			try {
      				// 循环,采用lua获取当前需要执行的任务并将其从redis中删除
      				String msg = stringRedisTemplate.execute(TRY_GET_AND_DEL_SCRIPT,
      						Lists.newArrayList(getDelayedMsgSourceKey()), String.valueOf(System.currentTimeMillis()));
      				if (StringUtils.isNotBlank(msg)) {
      					// 消息不为空,表示获取任务成功,将其再发送到指定MQ异步处理,将“获取任务”与“执行任务”分离解耦
      					rabbitTemplate.convertAndSend(getSendExchange(), getSendRoutingKey(), msg);
      				} else {
      					// 获取不到任务,表示当前时间点下暂无需要执行的任务,则线程休眠1S(可视情况调整)
      					SleepUtils.sleepSeconds(1);
      				}
      			} catch (Exception e) {
      				Logs.MSG.error("delayed msg scan error, sourceKey:{}", getDelayedMsgSourceKey(), e);
      			}
      		}
      	}
      	@Override
      	public void destroy() throws Exception {
      		quit = true;
      	}
      	public void setQuit(boolean quit) {
      		this.quit = quit;
      	}
      	/**
      	 * 获取消息的工作线程数量
      	 */
      	protected abstract int getThreadNum();
      	/**
      	 * 线程名称前缀,方便问题定位
      	 */
      	protected abstract String getThreadNamePrefix();
      	/**
      	 * 存放延迟消息的ZSET队列名
      	 */
      	protected abstract String getDelayedMsgSourceKey();
      	/**
      	 * 消息到达执行时间点时将其通过指定 exchange 发送到实时消费队列中
      	 */
      	protected abstract String getSendExchange();
      	/**
      	 * 消息到达执行时间点时将其通过指定 routingKey 发送到实时消费队列中
      	 */
      	protected abstract String getSendRoutingKey();
      }

      在具体业务应用中,只需定义一个继承上述类的bean即可,需要实现的方法主要是提供一些配置,比如该业务对应的zset延时队列名称,同时工作拉取消息的线程数量,由于采用rabbitMq,因此这里需要提供exchange和routingKey。

      实际使用中只需向该zset队列中添加消息,并将score设为该任务需要执行的时间点(此处为13位毫秒时间戳),则到该时间点后,上述组件便会将该消息从zset中取出并删除,再将其通过指定的路由发送到实时MQ消费队列中,由消费者负责执行任务业务逻辑。目前该组件在项目中正常平稳运行。

      注意:

      本文结合项目中的实际需求介绍了延时队列的应用场景,分析了延时队列的多种实现,重点讲述了利用redis实现延时队列的原理,对其实现方案进行比较与优化,并将最终方案实际运用于项目需求中。

      本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
      作者最新文章
      编程开发
      相关文章 更多
      精品专题 更多
      装机必备

      正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

      Windows

      正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

      PDF教程

      正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

      macOS软件

      正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

      IOS软件

      正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

      AI

      正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

      Mac软件 更多
      Postman macOS版
      Postman macOS版

      Postman是一套面向API全生命周期的开发与测试平台,可在Mac上发送和调试多种协议请求,管理集合、环境及认证信息,并完成脚本测试、模拟服务、监控、文档发布和团队协作。它适合开发、测试及运维人员使用,提供个人免费方案。

      Docker Desktop macOS版
      Docker Desktop macOS版

      Docker Desktop 是 Docker 官方为 Mac 提供的容器开发环境,集成 Docker Engine、命令行工具、Compose、Build、Kubernetes 与图形化管理界面。

      Android Studio macOS版
      Android Studio macOS版

      Android Studio 是 Google 面向安卓应用开发提供的官方集成开发环境,基于 IntelliJ IDEA 构建。它整合智能代码编辑、Gradle 构建、界面预览、设备模拟、性能分析、调试测试及 APK 分析等工具。

      Xcode macOS版
      Xcode macOS版

      Xcode 是苹果面向 Mac 提供的官方集成开发环境,将代码编辑、项目构建、SwiftUI 实时预览、设备模拟、自动化测试、断点调试、性能分析和应用分发整合在同一套工作流中,适合开发与维护 iPhone、iPad、Mac、Apple Wa

      JetBrains WebStorm macOS版
      JetBrains WebStorm macOS版

      JetBrains WebStorm 是面向 JavaScript、TypeScript 和现代 Web 技术的专业集成开发环境,可智能理解项目结构,提供代码补全、重构、错误检查、运行调试、测试及 Git 工具。

      PhpStorm macOS版
      PhpStorm macOS版

      PhpStorm 是 JetBrains 推出的专业 PHP 集成开发环境,可在 Mac 上完成代码编写、智能检查、重构、调试、测试和数据库管理。它支持主流 PHP 框架、Composer、Git、Docker 与远程解释器。

      JetBrains PyCharm macOS版
      JetBrains PyCharm macOS版

      JetBrains PyCharm 是面向 Python 开发者的集成开发环境,提供智能补全、代码检查、重构、调试、测试、版本控制及虚拟环境管理功能。Mac 版兼容 Intel 与 Apple 芯片,核心功能可免费使用。

      JetBrains IntelliJ IDEA macOS版
      JetBrains IntelliJ IDEA macOS版

      IntelliJ IDEA 是 JetBrains 推出的专业集成开发环境,重点服务于 Java、Kotlin 与 JVM 项目开发。软件集成代码补全、静态检查、重构、调试、测试、版本控制及构建工具,并可借助插件扩展语言和框架支持。

      Visual Studio Code macOS版
      Visual Studio Code macOS版

      Visual Studio Code 是微软提供的免费代码编辑器,支持 macOS,并为 Intel 与 Apple 芯片 Mac 提供适配版本。软件集代码编辑、调试、Git 源代码管理、集成终端和扩展市场于一体。

      REAPER macOS版
      REAPER macOS版

      REAPER是Cockos开发的数字音频工作站,提供多轨音频与MIDI录制、剪辑、处理、混音和母带制作工具。Mac版兼容Intel与Apple芯片,支持AU、VST、VST3、CLAP等插件格式,并提供高度可定制的工作流程。

      Adobe Audition macOS版
      Adobe Audition macOS版

      Adobe Audition 是面向播客、影视后期、音乐制作及内容创作者的专业音频工作站,提供波形精修、多轨录制与混音、频谱编辑、降噪修复、响度匹配和效果处理工具,并可与 Adobe Premiere 协同完成视频声音制作。

      Pro Tools macOS版
      Pro Tools macOS版

      Pro Tools 是 Avid 推出的专业数字音频工作站,覆盖多轨录音、无损剪辑、MIDI 编曲、插件处理、自动化混音及声音与画面同步等工作。它拥有 Intro、Artist、Studio 和 Ultimate 等方案。

      WINDOWS 更多
      PixPix 网页版
      PixPix 网页版

      PixPix 是面向品牌、卖家和内容团队的在线 AI 图片视频创作平台,提供图视频 Agent、无限画布、图片生成、视频生成、自然语言编辑及商品套图、产品精修和带货视频等电商工具。

      Postman Windows版
      Postman Windows版

      Postman 是面向 API 全生命周期的开发与协作平台。Windows 桌面版可用于构建和发送 HTTP、GraphQL、gRPC、WebSocket、MQTT 等请求,并提供环境变量、集合、脚本测试、模拟服务、监控、文档及团队工作区等

      Docker Desktop Windows版
      Docker Desktop Windows版

      Docker Desktop 为 Windows 开发者提供集成式容器环境,内置 Docker Engine、命令行工具、Compose、Build 与 Kubernetes 等组件,可在本机完成镜像构建、容器运行、日志查看和资源管理。

      Android Studio Windows版
      Android Studio Windows版

      Android Studio 是 Google 面向 Android 应用开发提供的官方集成开发环境,以 IntelliJ IDEA 为基础,集成智能代码编辑、Gradle 构建、设备模拟、界面预览、调试测试及性能分析工具,

      JetBrains WebStorm Windows版
      JetBrains WebStorm Windows版

      WebStorm 是 JetBrains 面向 JavaScript、TypeScript 和现代 Web 技术打造的集成开发环境。它提供项目级代码分析、智能补全、安全重构、导航搜索,并集成调试、测试、终端、Git 与常用前端工具,

      JetBrains PhpStorm Windows版
      JetBrains PhpStorm Windows版

      PhpStorm 是 JetBrains 面向 PHP 与现代 Web 开发打造的专业集成开发环境,提供代码补全、静态检查、重构、调试、测试、数据库、版本控制及前端语言支持。Windows 用户可直接下载安装程序,

      JetBrains PyCharm Windows版
      JetBrains PyCharm Windows版

      PyCharm 是 JetBrains 推出的 Python 集成开发环境,提供智能代码补全、错误检查、重构、调试、测试、Git、终端及 Jupyter Notebook 支持。统一版安装后可体验 30 天 Pro 功能,

      JetBrains IntelliJ IDEA Windows版
      JetBrains IntelliJ IDEA Windows版

      JetBrains IntelliJ IDEA 是以 Java、Kotlin 和 JVM 项目为核心的专业集成开发环境,提供智能补全、代码检查、安全重构、调试、测试、版本控制及构建工具集成。统一发行版的核心功能可免费用于商业和非商业项目,

      Visual Studio Code Windows版
      Visual Studio Code Windows版

      Visual Studio Code 是微软推出的免费代码编辑器,Windows 版集成智能补全、代码导航、调试、终端和版本控制,并可通过扩展添加语言、格式化及远程开发能力。它启动较快、配置灵活,

      REAPER Windows版
      REAPER Windows版

      REAPER 是 Cockos 推出的数字音频工作站,适用于录音、MIDI 编曲、音频编辑、混音、母带制作及声音设计。软件安装包小巧,支持多轨录制、灵活路由、自动化、第三方插件和脚本扩展,并提供完整功能的 60 天免费评估期。

      Adobe Audition Windows版
      Adobe Audition Windows版

      Adobe Audition 是面向播客、影视后期、广播与音乐制作的专业音频工作站,提供波形编辑、多轨混音、频谱分析、录音、降噪修复和效果处理等功能。Windows 版通过 Adobe Creative Cloud 安装和管理,

      Pro Tools Windows版
      Pro Tools Windows版

      Pro Tools 是 Avid 推出的专业数字音频工作站,提供多轨录音、音频剪辑、MIDI编曲、插件处理、自动化混音及影视声音制作能力。它适合音乐人、录音师、制作人和音频后期团队使用,并提供免费入门版、订阅方案及永久授权选择。

      即将离开本站
      您即将前往第三方网站,请确认是否继续?