MQ 用来解耦挺好的。我们有个业务,计算用户在线时长,然后触发完成 “每日在线 15 分钟” 的每日任务。登录,登出都发消息,接到消息的程序减一下时间得到在线时间触发任务完成。
我们的系统有个毛病,可能出现闪登闪退,也就是同一个毫秒登录马上登出,这就尴尬了,消费者可能先收到登出再收到登录。这个候程序员小伙子们可来劲了:“我知道我知道,可以用 MQ 的保证消息顺序能力”,然而被我制止了。我已经受的够够的了,一有什么达不到,立马诉诸各类技术框架的功能。
不急,先想想,登录的业务本质是什么?就是验证身份,成功之后开启一段会话,登出自然就是终结这段会话咯,在线时长就是这段会话的时长。好,那么当先收到登出消息时,无非就是发现这个会话没有开始时间么,但是他确实是一个存在的会话啊,没有开始时间就没有好了,先放着,一会儿登录消息来了那么会话开始时间也就补齐了,可以调用会话的 “计算会话时长” 方法计算在线时间了。
所以这关 MQ 的保证消息顺序什么事?我们是不是做技术做魔怔了?把太多的业务解决方案诉诸技术,系统越来越复杂,在错误的道路上越走越远。。。
![]() | 1 AItsuki 2023-10-31 16:42:00 +08:00 via iPhone ![]() 你是对的 |
![]() | 2 sunwei0325 2023-10-31 17:03:48 +08:00 复杂业务还是需要 MQ 保证顺序的, 不然 aws 的 SQS 也不会设计一个 FIFO 队列了 |
3 Plutooo 2023-10-31 17:06:46 +08:00 ![]() MQ MQ ,Message Queue ,我觉得需要 Queue 有顺序没有什么问题 |
4 54qyc 2023-10-31 17:08:26 +08:00 ![]() OP 也魔怔了,看见别人用顺序消息就开始脑补开始喷了?别人思路必须跟你一样?你要是不接受有序消息,你不能反问别人还有没有其他的解决方案?上来就是恶意假设?不过这里顺序消息也根本处理不了秒登秒登出场景。生产的时候并不能保证先生产登录 后生产登出,如果是有多个应用服务器的话。 |
5 coderzhangsan 2023-10-31 17:09:26 +08:00 看问题的角度不一样,程序员从技术角度要保证业务的可靠性和严谨性,没什么问题,需求交互场景细节这个可以沟通,按照需求调整,没必要鸡蛋里挑骨头。 |
6 B1acKy1in 2023-10-31 17:10:59 +08:00 个人理解是简单的业务,消费者那里缓存下,然后验证下时间戳就够了;复杂系统还是搞点组件(甚至搞个服务)来处理下吧,毕竟复杂业务的架构跨度太大了,很难说哪里有啥问题。 |
7 zihuyishi 2023-10-31 17:13:53 +08:00 ![]() 这个计算在线时长的逻辑不太合适吧,如果我今天不登出意思就完成不了这个任务了? 如果以后要做防沉迷是不是我只要一直在线也可以一直玩下去了 |
![]() | 8 k9982874 2023-10-31 17:16:59 +08:00 via Android ![]() 取出最后登录时间,登出时间一减就成,确实不需要 mq 。 但是 op 的态度是真的让人讨厌。 |
![]() | 9 opentrade 2023-10-31 17:17:10 +08:00 程序闪退了,就不计算我的在线时长? |
![]() | 10 shalk 2023-10-31 17:20:05 +08:00 如果登入消息丢了呢,这个时长就不记录了么 |
11 yibinhp 2023-10-31 17:22:44 +08:00 @sunwei0325 请教一下,多消费者的情况下怎么保证 mq 有序消费啊 |
12 Jooeeee 2023-10-31 17:23:53 +08:00 如果登录登出是同一个 mq ,且 mq 有这个能力,为什么不用呢。 另外,这个需求看着不需要很精确,没有登录消息,就当是 5 分钟好了 |
![]() | 13 lsk569937453 2023-10-31 17:27:02 +08:00 我是看了标题进来的,只能说你的应用场景可以不用 MQ 。 但是针对你的标题,我想说 MQ 确实需要一个保证顺序的功能。 比如现在主流的分布式事务的解决方案就是分布式消息,而分布式消息里面很重要的一点就是 MQ 的消息必须是顺序的。 |
![]() | 14 Goooooos 2023-10-31 17:31:25 +08:00 ![]() |
![]() | 15 sunwei0325 2023-10-31 17:35:48 +08:00 ![]() MQ 保证顺序, 主要是因为分布式服务以及服务器网络通信等因素, 造成的 AB 消息入队, 结果是 BA 消息出队这种情况. 但是如果像闪退闪登这种, 2 个事件一起发, 很可能由于网络, 客户端先发的登出消息, 后于登录消息到达 MQ, 这种情况下, 即使 MQ 保证顺序, 消费者看到的依然是乱序. 上面说的这种情况可以借鉴 Flink 的 watermark+window, 由业务进行补偿处理, 虽然 IngestionTime 是乱序的, 但是 EventTime 是有序的. |
![]() | 16 wolfie 2023-10-31 17:50:46 +08:00 via Android mq 消息存储没有时间戳吗。 多实例多线程 消费一个队列 如何应对。 |
17 Pantheoon 2023-10-31 19:15:24 +08:00 队列的本质就是先进先出 |
![]() | 18 kingfalse 2023-10-31 19:17:45 +08:00 via Android 功能实现了吗?实现了就没毛病!毕竟每个人都有自己的骚操作。 |
19 GopherDaily 2023-10-31 19:26:40 +08:00 你菜 |
20 makersy 2023-10-31 19:27:44 +08:00 这标题就有问题。MQ 也是 queue ,保证顺序为什么不是 queue 该做的事情? |
![]() | 21 milkpuff 2023-10-31 20:59:32 +08:00 楼主说的对。我赞同。 我觉得楼主的重点在于”把太多的业务解决方案诉诸技术“,这一点指得准确 |
22 leonshaw 2023-10-31 21:09:37 +08:00 via Android 这是重排,不是保序 |
![]() | 23 GuangXiN 2023-10-31 21:41:46 +08:00 MQ 不是 Message Queue 的缩写么? Queue 不保证 FIFO 还叫 Queue 么? |
24 cp19890714 2023-10-31 21:47:08 +08:00 挖掘业务本质, 是个很难但是非常重要的能力. 这个能力难以通过固有的教程去训练. 对于人来说, 技术能力可以通过已有的教程文档快速掌握, 自然就会依赖技术. |
25 PVXLL 2023-10-31 21:48:16 +08:00 via iPhone 都是菜鸡 |
26 ShuWei 2023-10-31 22:51:10 +08:00 通过两条消息的时间差去计算在线时长,这真的是个好的方案么?会不会,这个方案从一开始就是有问题的 |
![]() | 27 adoal 2023-10-31 22:58:25 +08:00 ![]() “我们的系统有个毛病”……你看,你自己都知道是业务系统的毛病,不去解决毛病也就罢了,毕竟屎山不能乱动,以防溅一脸屎汤。人家要在外围用技术手段来把你这业务系统这端的毛病给人家外围附加功能带来的困扰 workaround 掉,你还怪人家做技术做魔怔了。“系统越来越复杂,在错误的道路上越走越远”是“把太多的业务解决方案诉诸技术”导致的吗?你们这群技术不重要业务该被舔的嘤嘤怪,心里真的没有点碧树吗? |
![]() | 28 IvanLi127 2023-10-31 23:01:12 +08:00 via Android MQ 有复杂的也有简单的,你知道人家说的是什么 MQ 吗? |
29 neoblackcap 2023-11-01 01:02:06 +08:00 ![]() 就这样的统计功能都要放在业务系统里面做,那什么系统跑不死啊。登录,登出的事件写日志(进 MQ 再落地也一个道理),直接通过回放日志,简单统计一下当天是否有超过 15 分钟的在线就得了。而且还不会对业务系统产生影响,因为这需求可以做成实时的,也可以做成离线。 OLAP 的活就不要压业务系统了。 |
![]() | 30 Amex 2023-11-01 05:13:15 +08:00 > 我们的系统有个毛病,可能出现闪登闪退 不先把系统的问题修一修么 |
![]() | 31 xuanbg 2023-11-01 06:33:57 +08:00 1 、我不懂闪退为啥还能有登出动作? 2 、计算在线时长不是应该用 redis 吗?用 MQ 做啥? |
32 haochih 2023-11-01 08:37:31 +08:00 你是对的 |
33 jguo 2023-11-01 08:54:17 +08:00 ![]() “我喜欢和聪明人交往,因为不用考虑他们的尊严”。讨论技术问题别上来就开启防御姿态。 |
![]() | 34 dongdong12345 2023-11-01 08:55:27 +08:00 第一反应是修复这个登入登出的毛病 |
![]() | 36 zsdroid 2023-11-01 09:27:30 +08:00 系统有毛病不管,先来发帖喷一喷别人。op 牛逼。 |
![]() | 37 msaionyc 2023-11-01 09:31:20 +08:00 “先放着”是什么意思,这条消息怎么处理? 如果这个消息处理的地方为这个行为做个补丁,其实也等于提高了系统复杂度,后人接手时也会摸不着头脑,为什么这么做 |
38 ecareyu 2023-11-01 09:37:11 +08:00 其实 up 主,你说的压根就是两件事,但也可以说是一件事,就是,产品思维和技术思维,技术一般很难跳出技术思维这个圈,但是很多以产品思维来想,有些事,确实没必要完全通过复杂的技术实现,因为用户根本不会 care 。你要没必要喷那个小伙,毕竟,他只是个技术,你让他往产品想,那属实有点隔行如隔山了。 |
![]() | 39 zhazi 2023-11-01 09:42:23 +08:00 笑死,op 来找认同,结果被按着头喷。 水平不高的人当 ld 是这样的 |
40 Leviathann 2023-11-01 09:43:38 +08:00 mq 保证的不是入队的顺序吗,入队就是乱的保证什么? |
41 FrankAdler 2023-11-01 09:45:02 +08:00 via Android 水平不高的人有话语权是这样的 block 了 |
![]() | 42 Habyss 2023-11-01 09:48:14 +08:00 可是 mq 单队列单消费者, 本身不就是有序的吗. |
![]() | 43 Habyss 2023-11-01 09:51:16 +08:00 |
44 Masoud2023 2023-11-01 09:58:55 +08:00 你们不应该先解决一下闪灯闪退的问题吗 |
45 GeruzoniAnsasu 2023-11-01 10:01:18 +08:00 > 登录的业务本质是什么?就是验证身份,成功之后开启一段会话 明明你「理解」了本质,怎么还能想出这种结论。 假设你们的系统真的能先收到登出再收到登录,登出的时候,会话在哪? > 么当先收到登出消息时,无非就是发现这个会话没有开始时间么,但是他确实是一个存在的会话啊,没有开始时间就没有好了 哈? REALLY? 你是凭什么认为这个登出消息能是一个合法消息的? |
![]() | 46 qiyilai 2023-11-01 10:42:45 +08:00 为什么非要登出才能统计在线时长?好奇怪 |
47 wOuv7i4e7XxsSOR1 2023-11-01 10:48:57 +08:00 不能保证顺序的 mq 还能叫 mq 吗? |
![]() | 48 venglide 2023-11-01 10:52:04 +08:00 典型的流处理问题,文不对题。 |
![]() | 50 kelvin_fly 2023-11-01 11:27:09 +08:00 我理解是两个事情。一是发送到 MQ 的 message 本身就顺序有问题,由于网络波动或者其他啥原因。 另一个是 MQ 保证顺序。 最好在 message 中携带业务的时间戳。 这个计算时长应该业务方自己解决先手顺序,因为只靠 MQ 的顺序也解决不了 |
![]() | 51 Aresxue 2023-11-01 11:30:49 +08:00 无非就是顺序消息存在的必要性,答案是有必要。只是说不能一股脑地把问题都丢给中间件以为就万事大吉了,10TPS 有 10TPS 的处理方式,1kTPS 有 1kTPS 的,10wTPS 也有 10wTPS 的,就事论事选择最适合业务的。 |
![]() | 52 MIUIOS 2023-11-01 12:06:18 +08:00 你们的业务好奇怪啊, 计算在线时长,而且是每日任务, 那取当日首次登陆时间,和当前存在时间计算一下不就知不知道满足 15 分钟了吗, 为什么还要去登出登入什么奇奇怪怪的逻辑,登出才出发任务? 那我一直登着不退出不就不触发这个任务了,难不成你们业务是必须实实在在的计算某一次在线时长满足 15 分钟的? |
![]() | 54 Mikawa 2023-11-01 12:16:33 +08:00 要不先修一下闪登的问题,然后在线的时候能不能发个心跳包 来自某个必须要登出才能统计在线的游戏的玩家 |
![]() | 55 MIUIOS 2023-11-01 12:17:05 +08:00 @nbndco 游戏可能就会频繁涉及登出登入,但以登出作为计算任务的触发点, 我是没想到,这要是发个在线时长奖励活动, 我岂不是还要把游戏重开一下才能领。。 |
![]() | 56 nuII 2023-11-01 12:22:44 +08:00 笑死,主要问题来源不是因为闪登闪退吗?这问题不修,搞其他的有用? |
57 WashFreshFresh 2023-11-01 13:14:16 +08:00 怎么先放着,服务维护重启怎么办,存 redis 还是存库?存的话什么时候取出来,登出的时候取出来? 业务就是这样一步步搞复杂的。 |
![]() | 58 Akiya 2023-11-01 13:40:29 +08:00 同一个 partition 本来就是保证顺序的。但是 MQ 有序并不能解决你这里秒登秒退的问题。总之 OP 确实有点魔怔 |
59 imokkkk 2023-11-01 13:57:48 +08:00 我理解 如果项目已经引入了 MQ ,用到这里来解决问题也不是不行,如果单纯为了解决这个问题引入 MQ ,那确实没必要额外在运维一个组件。 |
60 herofire 2023-11-01 14:17:03 +08:00 你是对的!我必需为此点个赞 |
61 palfortime 2023-11-01 14:26:19 +08:00 via Android 只有我好奇同一毫秒的登入登出是怎么达成的吗? |
62 FaustY 2023-11-01 14:28:34 +08:00 这辈子登出的次数用一只手都能数得过来,如果符合 lz 的场景的话,新增个接口,前端判断时间够了直接调用会不会好点。 |
63 zhuoyue100 2023-11-01 14:31:06 +08:00 怎么能用登陆和登出来统计在线时长? 现在谁还点登出 |
64 iseki 2023-11-01 14:38:07 +08:00 业务不诉诸技术诉诸什么?无非是不同的取舍而已,别说的这么清新脱俗。虽然我不赞同他的解决方案,但是你这种思想问题更大,他的方案不够严密只是水平问题,你这是路线问题。 不妨先想想所谓的「业务解决方案」真的只是业务吗。 |
![]() | 65 qwwe01 2023-11-01 14:57:49 +08:00 入队是无序的话,就算 MQ 保证了也解决不了。除非从发消息到 MQ 到消费都是同一条链路才能保证吧。 设计的话,为啥不记录下来自己计算一遍就好了 |
66 NoKey 2023-11-01 16:32:16 +08:00 讨论一个问题啊,闪退的情况下,有回调发出登出消息么? |
67 wh0syourda66y 2023-11-01 16:45:51 +08:00 《我们业务有个问题》 《这样不就行了,想那么复杂干什么》 《以后出了问题再说》 《哦,这个问题是因为我们上次为了修复那个问题引进的》 《你问我为什么不解决根本问题,你懂不懂业务》 《我离职了,上个公司代码就是个屎山,技术差的要命》 |
![]() | 68 BQsummer 2023-11-01 17:41:11 +08:00 模型和 flink 的 watermark 挺相似的, 时间时间和消息时间是两回事. |
![]() | 69 sunsan05 2023-11-01 17:59:08 +08:00 MQ 需要不需要保证顺序,是架构设计的时候决定的。架构设计的时候怎么决定的,就是考虑异常情况下的处理方案。 如果你需要顺序的数据并且做计算, 那么: 如果 MQ 不需要保证顺序,那就需要 Flink 这种流式计算(或自研)做窗口数据流校验。 如果你觉得实时数据也没必要,那就改为批处理,同样也是窗口期校验。 --- 到这你就会发现,是你要什么,然后才选择什么的,不能既要有要还要。如果想既要有也要还要,那就需要有牺牲。 |
![]() | 70 LieNoWell 2023-11-01 18:11:35 +08:00 按照目前他们的设计,我在 14 分 59 秒退出,如此反复,哪怕玩一天,也无法达成“在线 15 分钟”任务。 |
71 mysunshinedreams 2023-11-01 18:57:06 +08:00 MQ 也没法保证毫秒级的顺序吧,我记忆中 Kafka 从 producer 到 broker 还有一段时间呢,而且你这个登入和登出衔接这么近,打到两台节点上,到 broker 的顺序也不一定,这种东西真正的解决办法不应该是记录时间戳+延迟消息搞定吗 |
![]() | 72 rioshikelong121 2023-11-01 19:51:36 +08:00 很奇怪的实现方式。我完全可以不登出啊。 |
![]() | 73 sunsan05 2023-11-02 09:01:46 +08:00 |
![]() | 74 atVoid 2023-11-02 11:02:33 +08:00 不要先确定一个"我想喷 xx"目的, 然后在现实中当小警察时刻搜寻, 抓到一个看起来有点像的点就开喷. PS: 要不还是先解决秒登秒出的 bug, 以及你们这方案不登出就没法完成任务的问题? 然后真的理解了很多的业务场景和方案, 才开始聊聊顺序消息. |
75 bthulu 2023-11-02 12:40:28 +08:00 没有登陆的登出, 直接丢弃就好了, 不差这个几百毫秒的在线时间的. |
![]() | 76 LoliconInside 2023-11-02 12:44:07 +08:00 思路有问题,你要统计的是“在线时长”,不是“登入-登出时间的差值” 如果我这辈子都不主动登出,是不是这辈子都无法完成这个在线任务? 个人思路:在登入后按分钟发送心跳包,服务端统计心跳包个数,满足个数后标记该用户“任务已完成” 这样你消息是否 FIFO 也无关紧要了,我只是想看你到底有没有满足“在线 15 分钟”这个条件而已 |
![]() | 77 purensong 2023-11-02 15:28:24 +08:00 看标题进没让我失望,浪费了一分钟 |
78 mysunshinedreams 2023-11-02 17:10:32 +08:00 @sunsan05 #73 即使设定到很低,分布式架构上的假定还是会存在问题 |
79 DefoliationM 2023-11-02 18:36:38 +08:00 via Android 没学过数据结构?不知道什么叫队列?先进先出不知道? |
80 258 2023-12-21 09:43:29 +08:00 登出? |