工作用Go: 异步任务怎么写6 | Asynq: 专业异步任务框架

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 工作用Go: 异步任务怎么写6 | Asynq: 专业异步任务框架

go01.jpeg

本文为 工作用Go: 异步任务怎么写 系列的第6


如果只是 异步一下, 上面讲解的内容也基本够用了; 如果有重度异步任务使用, 就得考虑专业的异步任务队列框架了, Go 中可以选择 Async


Asynq Features


整体架构图

image.pngimage.png

实际使用

使用的 demo 就不贴了, asynq 的文档很详细, 说一下具体实践中遇到的 2个 case:


  • 使用 web UI: 处于安全考虑, 设置了 ReadOnly
h :=asynqmon.New(asynqmon.Options{
RootPath:     "/monitoring", // RootPath specifies the root for asynqmon appRedisConnOpt: tasks.GetRedis(),
ReadOnly:     true, // admin web can't operation})
r :=mux.NewRouter()
r.PathPrefix(h.RootPath()).Handler(h)
srv :=&http.Server{
Handler: r,
Addr:    ":8080",
}


PS: 使用 web UI 由于涉及到使用新的端口, 而应用部署已经上 k8s 了, 如何顺利访问就需要一系列运维操作, 留个坑, 以后有机会再填


  • 测试环境OK, 线上报错: recoverer: could not move task to archive: INTERNAL_ERROR: redis eval error: ERR 'asynq:{}:t:' and 'asynq:{}:active' not in the same slot


对比发现, 是测试和线上使用的不同类型的 redis 实例导致的, 搜索云服务的帮助文档:

Redis实例类型差异

对比项

单机/主备

Proxy集群

Cluster集群

兼容Redis版本

兼容社区Redis 3.0、4.0、5.0。

Redis 6.0兼容社区KeyDB(当前只支持主备实例)。

可在购买实例时选择版本号。

兼容社区3.0、4.0和5.0版本。

兼容开源社区4.0/5.0版本。

可在购买集群实例时选择版本号。

特性支持

  • 支持event notify。
  • 支持pipeline。
  • 支持pipeline、mset、mget。
  • 支持scan、keys、slowlog。
  • 支持发布订阅。
  • 支持event notify。
  • 支持brpop、blpop、brpoplpush。
  • 支持发布订阅。

特性限制

单机不支持持久化。

  • lua脚本受限使用,所有的key必须在同一个slot,否则会报错,建议使用hashtag技术。
  • 多个key的命令中,所有key必须属于同一个slot,否则会报错,建议使用hashtag技术。
  • 不支持event notify用法。
  • lua脚本受限使用,所有的key必须在同一个slot,建议使用hashtag技术。
  • 需要客户端SDK支持redis cluster协议,需要能够处理"-MOVED"响应。
  • 使用pipeline、mset/mget模式时,所有key必须属于同一个slot,否则报错,建议使用hashtag技术。
  • 使用event notify时,需要建立与每个redis-server的连接,分别处理每个连接上的事件。
  • 执行scan、keys等遍历类或者全局类命令时,需要对每个redis-server分别执行该命令。

客户端协议

使用传统Redis客户端即可。

使用传统Redis客户端即可,不需要支持Redis Cluster协议。

需要客户端支持Redis Cluster协议。

命令限制

单机和主备实例不支持的Redis命令,请参考表 Redis4.0单机和主备禁用命令表 Redis 5.0单机和主备禁用命令

Proxy集群实例不支持的Redis命令,请参考表 Redis3.0 Proxy集群实例禁用命令表8表8

Cluster集群不支持的Redis命令,请参考表 Redis4.0 Cluster集群禁用命令表 Redis5.0 Cluster集群禁用命令

副本数

单机实例为单副本,只有一个节点。

主备实例为双副本,目前Redis 3.0、Redis 6.0主备不支持自定义副本数,默认为一主一从的架构。在创建Redis 4.0、5.0主备实例时,支持自定义副本数,形成一主多从的架构。

每个集群分片都为双副本,但不支持为分片新增副本,每个分片是一主一从的架构。

每个集群分片默认为双副本,支持自定义副本数,可以是一主多从的架构。在创建实例时,也可以定义为单副本,单副本表示实例只有主节点,无法保障数据高可靠。


集群架构实例的命令限制: 如需在集群架构实例中执行下述受限制的命令,请使用hash tag确保命令所要操作的key都分布在1个hash slot中


但是查看 asqnq 源码: 以 enqueue 操作为例, lua 操作中的部分 key 无法通过外部添加 hash tag

// github.com/hibiken/asynq/internal/rdb/rdb.go// enqueueCmd enqueues a given task message.//// Input:// KEYS[1] -> asynq:{<qname>}:t:<task_id>// KEYS[2] -> asynq:{<qname>}:pending// --// ARGV[1] -> task message data// ARGV[2] -> task ID// ARGV[3] -> current unix time in nsec//// Output:// Returns 1 if successfully enqueued// Returns 0 if task ID already existsvarenqueueCmd=redis.NewScript(`if redis.call("EXISTS", KEYS[1]) == 1 thenreturn 0endredis.call("HSET", KEYS[1],"msg", ARGV[1],"state", "pending","pending_since", ARGV[3])redis.call("LPUSH", KEYS[2], ARGV[2])return 1`)


最终, 通过使用线上另一台主从版redis解决问题


写在最后


到这里, 工作用Go: 异步任务怎么写 就暂时告一段落了, 这个过程中:


  • 一些计算机基础概念的理解: 同步与异步, 异步与任务编排, 协程与异步, 协程与生命周期
  • 一些 Go 语言的基础知识以及基础不牢地动山摇的坑: 野生Goroutine, panic&recover
  • 可观测的实践之一: trace
  • 专业的异步任务框架 Asynq 以及踩坑记


一起拥抱变化, 直面问题和挑战, 不断精进, 我们下个话题再见👋🏻.

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
5月前
|
Go
go的并发初体验、加锁、异步
go的并发初体验、加锁、异步
|
2月前
|
JSON Go API
使用Go语言和Gin框架构建RESTful API:GET与POST请求示例
使用Go语言和Gin框架构建RESTful API:GET与POST请求示例
|
29天前
|
安全 编译器 Go
Go runtime 调度器精讲(十):异步抢占
Go runtime 调度器精讲(十):异步抢占
|
3月前
|
Cloud Native JavaScript API
一文读懂云原生 go-zero 微服务框架
一文读懂云原生 go-zero 微服务框架
|
2月前
|
消息中间件 NoSQL Go
PHP转Go系列 | ThinkPHP与Gin框架之Redis延时消息队列技术实践
【9月更文挑战第7天】在从 PHP 的 ThinkPHP 框架迁移到 Go 的 Gin 框架时,涉及 Redis 延时消息队列的技术实践主要包括:理解延时消息队列概念,其能在特定时间处理消息,适用于定时任务等场景;在 ThinkPHP 中使用 Redis 实现延时队列;在 Gin 中结合 Go 的 Redis 客户端库实现类似功能;Go 具有更高性能和简洁性,适合处理大量消息。迁移过程中需考虑业务需求及系统稳定性。
|
3月前
|
Go API 数据库
[go 面试] 分布式事务框架选择与实践
[go 面试] 分布式事务框架选择与实践
|
3月前
|
Go 数据库 UED
[go 面试] 同步与异步:程序执行方式的不同之处
[go 面试] 同步与异步:程序执行方式的不同之处
|
3月前
|
SQL JavaScript Go
Go Web 服务框架实现详解
Go Web 服务框架实现详解
|
3月前
|
存储 Prometheus 中间件
2020最佳人气项目之Go Web框架
2020最佳人气项目之Go Web框架
|
3月前
|
存储 Go 调度
go-zero 如何应对海量定时/延迟任务?
go-zero 如何应对海量定时/延迟任务?