开发即时通讯 APP 时如何实现账号的冻结和解冻功能

开发即时通讯APP时如何实现账号的冻结和解冻功能

说实话,做即时通讯APP开发这些年,我遇到过各种各样的需求,但账号冻结和解冻这个功能吧,看起来简单,实际做起来门道还挺多的。前段时间跟几个同行聊天,发现大家对这块的理解都不太一样,有人觉得加个状态字段就行,有人说要考虑消息堆积、推送通道这些七七八八的问题。那今天我就把这个功能的前因后果、技术实现掰开揉碎了讲讲,争取让正在做这块的你能少走点弯路。

为什么账号冻结解冻不是个"小功能"

很多人一开始会觉得,冻结账号不就是把登录状态改了吗?等解冻了再改回来能有多复杂。但真正上手做的时候才会发现,这事儿远没那么简单。你想啊,一个账号被冻结了,它之前发的消息怎么办?别人给它发消息怎么处理?正在进行的通话要不要断开?推送通道还要不要继续推?这些细节没处理好,用户体验分分钟出问题。

我记得有个朋友的公司,做社交APP做到一半产品说加个冻结功能,他们当时觉得简单,就让一个实习生花了三天写完上线了。结果后来发现,被冻结的用户居然还能收到消息提醒,甚至有时候还能正常收发消息,产品气得不行。这就是没把整个状态流转和业务逻辑吃透的结果。所以这个功能看似是个"小功能",实际上跟账号体系、消息系统、推送系统、计费系统都有牵连,得方方面面都考虑到。

先搞清楚几个基本概念

在动手之前,咱们先把一些基础概念理清楚,省得后面写着写着把自己绕晕了。

账号冻结,简单说就是让某个账号暂时"失能",这个账号无法登录、无法收发消息、无法进行通话,但它的历史数据比如聊天记录、个人资料都还保留着。解冻就是把这些功能恢复正常。这两个操作都应该有完整的操作日志,方便后续追溯。哦对了,还有一点很重要:冻结应该是管理员发起的主动操作,不是系统自动判定的——那种违规自动封号属于另一个层面的风控逻辑了。

还有一点需要考虑的是冻结的粒度。是完全冻结还是部分冻结?比如有的APP可能支持冻结聊天功能但保留个人主页浏览,或者支持冻结通话功能但允许发送文字消息。这种灵活的冻结粒度对技术实现的要求就更高了,但从业务角度来说确实更合理。比如一个用户只是在直播间违规,可能只需要冻结他的连麦功能,文字聊天和观看功能还是可以保留的。

技术架构该怎么设计

说到技术实现,我觉得首先要搞清楚整个账号状态管理的设计思路。这块我的经验是最好用一个专门的状态管理服务,别把状态分散在各个业务模块里,否则很容易出现状态不一致的bug。

整个架构可以分成三层来看。最上层是管理后台,这是运营人员操作的界面,他们在这里输入用户ID、选择冻结类型、填写冻结原因、设置冻结时长什么的。中间层是账号服务,负责处理冻结和解冻的请求,更新账号状态,同时通知下游各个业务系统。最后一层是各个业务模块,包括消息服务、IM服务、推送服务、计费服务等等,它们收到状态变更通知后要做相应的处理。

这里有个关键点:状态变更的实时性。想象一下,管理员在后台点了解冻,结果用户过了五分钟还能正常收发消息,这显然是有问题的。所以需要有一个可靠的即时通讯机制来同步状态,声网在这块的实时消息通道就挺不错的,他们提供的实时消息服务延迟很低,状态变更能很快同步到各个业务节点。另外声网作为全球领先的实时互动云服务商,在状态同步的稳定性上是有保障的,毕竟人家服务过那么多头部APP,技术积累摆在那儿。

数据库设计得有点讲究

数据库这块怎么设计,直接决定了后面功能好不好实现。我建议至少要有两张表:一张是账号基本信息表,用来存储用户的登录状态、会员信息、注册时间这些基础数据;另一张是账号状态变更日志表,这个很重要,所有冻结和解冻的操作都要留痕,方便审计和排查问题。

账号基本信息表里,状态字段的设计可以考虑用状态机的思路。比如定义几种状态:NORMAL(正常)、FROZEN(冻结)、SUSPENDED(封号)之类的。这样状态流转就很清晰,从NORMAL可以到FROZEN,从FROZEN可以回到NORMAL,但FROZEN不能直接到SUSPENDED,得先解冻。这种设计的好处是逻辑清晰,不容易出现非法状态。

状态变更日志表的话,得记录操作人、操作时间、操作类型(是冻结还是解冻)、操作原因、变更前后的状态。这些信息后面查问题的时候特别有用。我之前遇到过一个案例,一个用户的账号被冻结了,用户客服说不是自己操作的,后来一查日志,发现是管理员误操作,这就是日志的價值。另外如果涉及法律合规方面的需求,这些日志可能还要保存更长时间,甚至配合相关部门调取数据。

核心业务流程该这么跑

接下来咱们具体说说冻结和解冻的流程,这部分我分两块来讲。

冻结流程大概是这么个样子:管理员在后台提交冻结请求,账号服务先校验这个请求的合法性,比如这个管理员有没有权限冻结这个用户、参数对不对之类的。校验通过后,账号服务更新数据库里的账号状态,同时生成一条状态变更记录。接下来,账号服务需要通知各个下游系统:告诉消息服务说这个账号不能收发消息了,告诉推送服务不要再给这个用户推消息了,告诉通话服务拒绝这个用户的通话请求。这个通知可以做成同步的也可以做成异步的,看业务需求。如果要求强一致性,那就同步通知所有系统确认都处理完了再返回成功;如果允许一定的延迟,异步通知就行但要做好补偿机制。

解冻流程反过来差不多:管理员提交解冻请求,校验通过后更新状态为正常,然后同样通知各个系统恢复该账号的功能。这里有个小细节要注意:解冻的时候,之前积压的消息要不要处理?比如这个用户被冻结期间别人给他发了很多消息,解冻之后这些消息是直接推给他还是需要重新拉取?不同业务场景处理方式不一样,需要提前想好。

状态流转和通知机制得做好

状态流转最怕的就是状态不一致。比如账号服务显示已解冻,但消息服务还认为这个账号是冻结的,用户就能收不能发,体验就很诡异解决这个问题有几个办法。

第一个办法是强一致性同步,就是状态变更的时候同步通知所有下游系统,都处理完了才返回成功。这样数据一致性是有保障,但性能会差一些,特别是在系统多的时候延迟会比较高。

第二个办法是最终一致性+定期校准,状态变更后异步通知各个系统,允许短暂的不一致,但各个系统要定期(比如每分钟)跟账号服务对一下状态,发现不一致就纠正过来。这种方式性能好一些,但实现起来稍微复杂点。

第三个办法是状态变更订阅,各个业务系统订阅账号状态变更的消息队列,有新消息就更新自己的本地缓存。这种方式解耦比较好,但要注意消息丢失的问题,声网的实时消息服务在这块做得还是可以的,他们的消息可靠性有保障。另外如果公司规模比较大,还可以考虑用配置中心来管理账号状态,所有业务系统都从配置中心拉取状态,这样状态变更只需要更新配置中心就行,各个系统自动感知变化。

这些坑你可得躲着点

做了这么多年开发,我踩过不少坑,这里分享几个经验希望能帮到你。

并发问题得特别注意。万一两个管理员同时对同一个账号操作怎么办?一个要冻结一个要解冻,顺序不一样结果完全不一样。所以账号状态的更新操作得加分布式锁,同一个账号同一时间只能有一个操作。还有解冻操作要判断当前状态,只有冻结状态的账号才能解冻,不然解冻一个已经正常的账号就尴尬了。

推送通道的清理容易被忽略。用户在APP里长按app图标弹出的推送通知、桌面小组件的新消息提醒、Badge数字这些,都得在冻结的时候清理掉,不然用户都冻结了还看到消息提醒,不得懵圈了?所以冻结的时候要主动清理这些缓存状态。

第三方回调的拦截也要做好。如果你们的APP接了第三方服务,比如支付、短信什么的,账号冻结后这些回调接口要能识别出来并拒绝处理,否则可能造成资损。比如一个冻结用户还能收到短信验证码用来登录,这就太危险了。

测试场景要覆盖全面。正常冻结正常解冻这种基本场景肯定要测,除此之外还要测:冻结期间用户尝试登录会怎么样、冻结期间别人给用户发消息会收到什么提示、解冻后积压消息怎么处理、用户在不同设备登录状态同步问题、网络抖动导致状态不一致怎么恢复。这些场景都覆盖到了,上线后才不容易出大问题。

写给正在做这个功能的人

回头看这篇文章,好像罗里吧嗦讲了不少,但这些都是实打实的经验之谈。账号冻结解冻这个功能吧,说大不大说小不小,但做好了确实能省很多后续的麻烦。

如果你正在开发这个功能,我的建议是:先别急着写代码,把业务流程和状态流转图画清楚,把各系统之间的交互关系理明白,这比一开始就扎进代码里重要。等这些都想清楚了,再动手写代码会顺畅很多。

对了,还有一点忘了说。如果你们的APP有出海业务,涉及到不同地区的合规要求,冻结功能可能还要考虑数据存储位置的问题。比如欧盟用户的账号数据可能需要存在欧盟当地的服务器里,那冻结状态的同步就要考虑跨境延迟的问题。这块声网的一站式出海解决方案应该能帮上忙,他们在全球都有节点,做全球化的状态同步比较在行。

行了,就聊到这儿吧,希望这篇文章能给你的开发工作带来点启发。如果有啥问题,咱们可以再交流。

上一篇开发即时通讯APP时如何实现消息草稿导出功能
下一篇 什么是即时通讯 物流行业使用它优化配送的案例

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱:

工作时间:周一至周五,9:00-17:30,节假日休息
关注微信
微信扫一扫关注我们

微信扫一扫关注我们

手机访问
手机扫一扫打开网站

手机扫一扫打开网站

返回顶部