OpenIM 源码深度解析系列(十一):群聊系统架构与业务设计

群聊系统架构与业务设计

📋 概述

本文档全面解析OpenIM群聊系统的完整架构设计,涵盖存储架构、业务逻辑、权限控制和管理流程等核心模块:

🏗️ 系统架构层次

  • 存储架构:客户端SQLite + 服务端MongoDB + Redis缓存的三层存储体系
  • 业务架构:群组管理、成员管理、权限控制、申请审核等完整业务流程
  • 权限架构:基于角色的分级权限控制体系,支持精细化权限管理
  • 通知架构:实时通知机制,确保群组状态变更的及时同步

通过本文档,您将全面了解OpenIM群聊系统从底层存储到上层业务的完整设计架构。


第一部分:客户端存储层(SQLite)

🗄️ 核心表结构概览

OpenIM SDK 使用四个核心表实现完整的群聊数据存储:

表名 作用 数据特点 查询频率
LocalGroup 群组基础信息 相对稳定,变更较少 高频查询
LocalGroupMember 群成员信息 动态变化,成员进出频繁 超高频查询
LocalGroupRequest 群申请记录 临时数据,定期清理 中频查询
LocalChatLog 群聊消息记录 数据量大,增长快速 超高频查询

📋 1. LocalGroup - 本地群组信息表

表名 : local_groups

完整字段结构
字段名 字段类型 索引 详细描述
GroupID string(64) [主键] PRIMARY KEY 群组唯一标识 • 全局唯一的群组ID • 与服务端保持一致 • 作为主键,关联群成员和消息表
GroupName string(255) 群组名称 • 群聊显示名称 • 支持实时更新 • 影响会话列表显示
Notification string(255) 群公告内容 • 群主/管理员发布的公告 • 支持富文本格式 • 客户端弹窗提醒
Introduction string(255) 群组介绍 • 群组详细描述 • 加群时展示给申请者 • 群信息页面显示
FaceURL string(255) 群头像URL • 群组头像地址 • 支持本地缓存 • 会话列表头像显示
CreateTime int64 创建时间戳 • 群组创建时间 • 毫秒级时间戳 • 用于群组排序
Status int32 群组状态枚举0 = 正常状态 (GroupOk) • 1 = 群禁言状态 (GroupBanChat) • 2 = 群解散状态 (GroupStatusDismissed) • 3 = 群静音状态 (GroupStatusMuted)
CreatorUserID string(64) 创建者用户ID • 群组创建者标识 • 与用户表关联 • 用于权限判断
GroupType int32 群组类型枚举0 = 普通群 (NormalGroup) • 1 = 超级群 (SuperGroup) • 2 = 工作群 (WorkingGroup)
OwnerUserID string(64) 群主用户ID • 当前群主标识 • 支持转让变更 • 最高权限拥有者
MemberCount int32 群成员数量 • 实时成员统计 • 避免实时count查询 • 上限根据群类型确定
Ex string(1024) 扩展字段 • 自定义数据存储 • JSON格式 • 业务扩展使用
AttachedInfo string(1024) 附加信息 • 额外业务数据 • 可选的元数据信息 • 客户端自定义使用
NeedVerification int32 入群验证设置枚举0 = 申请需要验证, 邀请直接进群 (ApplyNeedVerificationInviteDirectly) • 1 = 所有人需要验证,除了群主管理员邀请 (AllNeedVerification) • 2 = 直接进群 (Directly)
LookMemberInfo int32 查看成员信息权限枚举0 = 所有人可查看 (ALL) • 1 = 仅群成员可查看 (MEMBER_ONLY) • 2 = 仅管理员可查看 (ADMIN_ONLY) • 3 = 禁止查看 (FORBIDDEN)
ApplyMemberFriend int32 添加成员为好友权限枚举0 = 允许添加 (ALLOW) • 1 = 需要验证 (NEED_VERIFICATION) • 2 = 禁止添加 (FORBIDDEN) • 3 = 仅管理员可添加 (ADMIN_ONLY)
NotificationUpdateTime int64 群公告更新时间戳 • 公告最后更新时间 • 用于公告变更提醒 • 毫秒级时间戳
NotificationUserID string(64) 群公告更新者ID • 最后修改公告的用户 • 公告来源追踪 • 权限验证使用

👥 2. LocalGroupMember - 本地群成员信息表

表名 : local_group_members

完整字段结构
字段名 字段类型 索引 详细描述
GroupID string(64) [联合主键] PRIMARY KEY 群组标识 • 关联群组表 • 成员归属群组 • 联合主键组成部分
UserID string(64) [联合主键] PRIMARY KEY 成员用户ID • 用户唯一标识 • 联合主键组成部分 • 一个用户在一个群中唯一
Nickname string(255) 群内昵称 • 成员在群内显示名称 • 可与真实昵称不同 • 群主/管理员可修改
FaceURL string(255) 成员头像URL • 用户头像快照 • 群内头像显示 • 支持本地缓存
RoleLevel int32 INDEX 角色等级枚举20 = 普通成员 (GroupOrdinaryUsers) • 60 = 管理员 (GroupAdmin) • 100 = 群主 (GroupOwner) • 权限递增,索引优化查询
JoinTime int64 INDEX 加入时间戳 • 成员入群时间 • 毫秒级时间戳 • 成员列表排序依据
JoinSource int32 加入来源枚举1 = 管理员邀请 (JoinByAdmin) • 2 = 邀请加入 (JoinByInvitation) • 3 = 搜索加入 (JoinBySearch) • 4 = 扫码加入 (JoinByQRCode)
InviterUserID string(64) 邀请者用户ID • 邀请该成员的用户 • 追踪邀请关系 • 入群来源管理
MuteEndTime int64 禁言结束时间戳 • 0表示未被禁言 • 大于当前时间表示禁言中 • 毫秒级时间戳
OperatorUserID string(64) 操作者用户ID • 最后操作该成员的用户 • 用于操作日志记录 • 权限变更追踪
Ex string(1024) 扩展字段 • 成员自定义数据 • JSON格式存储 • 业务扩展使用
AttachedInfo string(1024) 附加信息 • 成员相关元数据 • 可选的业务信息 • 灵活扩展支持

📨 3. LocalGroupRequest - 本地群申请记录表

表名 : local_group_request

完整字段结构
字段名 字段类型 索引 详细描述
GroupID string(64) [联合主键] PRIMARY KEY 目标群组ID • 申请加入的群组 • 联合主键组成部分
UserID string(64) [联合主键] PRIMARY KEY 申请者用户ID • 发起申请的用户 • 联合主键组成部分
GroupName string(255) 群组名称快照 • 申请时的群名 • 避免群名变更后显示异常 • 申请列表展示使用
Notification string(255) 群公告快照 • 申请时的群公告 • 申请页面展示 • 用户了解群组信息
Introduction string(255) 群介绍快照 • 申请时的群介绍 • 帮助用户了解群组 • 申请决策参考
GroupFaceURL string(255) 群头像快照 • 申请时的群头像 • 申请列表头像展示 • 保持视觉一致性
CreateTime int64 群组创建时间 • 群组创建时间快照 • 群组基本信息
CreatorUserID string(64) 群创建者ID • 群组创建者快照 • 群组历史信息
GroupType int32 群组类型快照 • 申请时的群类型 • 类型变更后的历史记录
OwnerUserID string(64) 群主ID快照 • 申请时的群主 • 群主变更后的历史记录
MemberCount int32 成员数量快照 • 申请时的成员数 • 群规模参考信息
Nickname string(255) 申请者昵称 • 申请者当时昵称 • 审核时显示使用 • 历史昵称记录
UserFaceURL string(255) 申请者头像 • 申请者当时头像 • 审核页面头像展示 • 快照保持一致性
HandleResult int32 处理结果枚举0 = 待处理 (默认状态) • 1 = 同意 (GroupResponseAgree) • -1 = 拒绝 (GroupResponseRefuse)
ReqMsg string(255) 申请消息 • 申请者填写的入群理由 • 帮助管理员决策 • 最大255字符
HandledMsg string(255) 处理消息 • 管理员处理时填写的消息 • 同意/拒绝的具体原因 • 反馈给申请者
ReqTime int64 申请时间戳 • 申请发起时间 • 毫秒级时间戳 • 申请列表排序依据
HandleUserID string(64) 处理者用户ID • 处理申请的管理员/群主 • 权限追踪 • 操作日志记录
HandledTime int64 处理时间戳 • 申请处理时间 • 0表示未处理 • 处理效率统计
Ex string(1024) 扩展字段 • 申请相关自定义数据 • JSON格式存储
AttachedInfo string(1024) 附加信息 • 申请相关元数据 • 业务扩展支持
JoinSource int32 申请来源 • 与成员表JoinSource对应 • 申请渠道统计
InviterUserID string(64) 邀请者ID • 如通过邀请申请 • 邀请关系追踪

第二部分:服务端存储层

🏗️ 架构概览

服务端采用三层存储架构:

  • MongoDB:持久化存储,保证数据安全和事务一致性
  • Redis:高速缓存,提升查询性能,支持大群场景

🗄️ MongoDB 数据库存储层

1. Group - 群组核心表

集合名 : group

完整字段结构
字段名 字段类型 索引 详细描述
_id ObjectId PRIMARY KEY MongoDB主键 • 自动生成的唯一标识
GroupID string UNIQUE INDEX 群组唯一标识 • 业务层面的唯一ID • 与客户端保持一致 • 关键查询索引字段
GroupName string 群组名称 • 群聊显示名称 • 支持修改更新 • 搜索功能使用
Notification string 群公告内容 • 富文本群公告 • 支持链接和格式 • 群管理功能核心
Introduction string 群组介绍 • 群组详细描述 • 搜索和推荐使用 • 入群申请展示
FaceURL string 群头像URL • 群组头像存储链接 • CDN分发优化 • 多端同步显示
CreateTime time.Time INDEX 创建时间 • MongoDB时间类型 • 自动索引优化 • 统计分析使用
Ex string 扩展字段 • 业务自定义数据 • JSON格式存储 • 灵活扩展支持
Status int32 群组状态0 = 正常 (GroupOk) • 1 = 群禁言状态 (GroupBanChat) • 2 = 群解散状态 (GroupStatusDismissed) • 3 = 群静音状态 (GroupStatusMuted)
CreatorUserID string 创建者用户ID • 群组创建者标识 • 历史记录保存 • 权限判断依据
GroupType int32 群组类型0 = 普通群 (NormalGroup) • 1 = 超级群 (SuperGroup) • 2 = 工作群 (WorkingGroup) • 不同类型不同规则
NeedVerification int32 入群验证设置 • 控制入群门槛 • 群管理策略 • 自动化审核规则
LookMemberInfo int32 查看成员权限 • 隐私保护设置 • 成员信息可见性 • 安全策略配置
ApplyMemberFriend int32 加好友权限 • 群内社交控制 • 防骚扰机制 • 隐私保护策略
NotificationUpdateTime time.Time 公告更新时间 • 公告版本控制 • 变更通知依据 • 时间戳精确记录
NotificationUserID string 公告更新者 • 操作者追踪 • 管理审计日志 • 权限验证使用
2. GroupMember - 群成员表

集合名 : group_member

完整字段结构
字段名 字段类型 索引 详细描述
_id ObjectId PRIMARY KEY MongoDB主键
GroupID string INDEX 群组ID • 复合索引:group_id + user_id • 成员归属群组 • 高频查询优化
UserID string INDEX 用户ID • 复合索引组成部分 • 用户群组反向查询 • 权限验证使用
Nickname string 群内昵称 • 群内显示名称 • 可与全局昵称不同 • 群主管理员可修改
FaceURL string 头像URL • 用户头像链接 • 群内头像显示 • 同步全局头像变更
RoleLevel int32 INDEX 角色等级20 = 普通成员 (GroupOrdinaryUsers) • 60 = 管理员 (GroupAdmin) • 100 = 群主 (GroupOwner) • 权限控制核心字段
JoinTime time.Time INDEX 加入时间 • 成员入群时间记录 • 排序和统计使用 • 成员资历判断
JoinSource int32 加入来源 • 入群渠道统计 • 推广效果分析 • 成员质量评估
InviterUserID string 邀请者ID • 邀请关系链 • 社交网络分析 • 成员来源追踪
OperatorUserID string 操作者ID • 最后操作记录 • 管理操作审计 • 权限变更追踪
MuteEndTime time.Time 禁言结束时间 • 禁言功能支持 • 自动解禁机制 • 群管理工具
Ex string 扩展字段 • 成员自定义属性 • 业务数据扩展 • JSON格式存储
3. GroupRequest - 群申请表

集合名 : group_request

完整字段结构
字段名 字段类型 索引 详细描述
_id ObjectId PRIMARY KEY MongoDB主键
UserID string INDEX 申请者用户ID • 复合索引:user_id + group_id • 申请者标识 • 申请历史查询
GroupID string INDEX 目标群组ID • 复合索引组成部分 • 群组申请管理 • 批量处理支持
HandleResult int32 INDEX 处理结果0 = 待处理 (默认状态) • 1 = 同意 (GroupResponseAgree) • -1 = 拒绝 (GroupResponseRefuse) • 申请状态过滤索引
ReqMsg string 申请消息 • 申请者入群理由 • 管理员审核参考 • 申请质量评估
HandledMsg string 处理消息 • 管理员处理说明 • 拒绝/同意原因 • 申请者反馈信息
ReqTime time.Time INDEX 申请时间 • 申请发起时间 • 申请列表排序 • 处理时效统计
HandleUserID string 处理者ID • 处理申请的管理员 • 管理操作追踪 • 权限验证使用
HandledTime time.Time 处理时间 • 申请处理时间 • 处理效率统计 • 时效性分析
JoinSource int32 申请来源 • 申请渠道统计 • 与成员加入来源对应 • 转化率分析
InviterUserID string 邀请者ID • 邀请类申请的邀请者 • 邀请关系维护 • 社交网络构建
Ex string 扩展字段 • 申请相关扩展数据 • 自定义申请属性 • 业务数据支持

🚀 Redis 缓存层

OpenIM Redis缓存采用分层过期策略和智能预加载,特别针对群聊场景优化:

1. 群组信息相关缓存
缓存Key格式 数据类型 TTL时间 缓存内容 使用场景
GROUP_INFO:{groupID} Hash 24小时 完整群组信息 群组详情快速查询
GROUP_MEMBER_IDS:{groupID} Set 12小时 群成员用户ID集合 群消息推送,权限验证
GROUP_MEMBER_INFO:{groupID}:{userID} Hash 12小时 单个成员详细信息 成员信息快速查询
GROUP_MEMBER_NUM_CACHE:{groupID} String 6小时 群成员数量 成员统计,群容量检查
GROUP_OWNER:{groupID} Hash 24小时 群主信息 权限验证,管理操作
2. 群成员角色相关缓存
缓存Key格式 数据类型 TTL时间 缓存内容 使用场景
GROUP_ADMINS:{groupID} Set 12小时 管理员用户ID集合 管理权限快速验证
GROUP_MEMBERS_ALL:{groupID} List 6小时 全部成员信息列表 成员列表展示
GROUP_ROLE_LEVEL_{roleLevel}:{groupID} Set 12小时 指定角色级别成员ID 按角色查询成员
USER_JOINED_GROUPS:{userID} Set 12小时 用户加入的群组ID集合 用户群组列表
USER_MANAGED_GROUPS:{userID} Set 12小时 用户管理的群组ID集合 管理员权限快速检查
3. 群成员哈希缓存
缓存Key格式 数据类型 TTL时间 缓存内容 使用场景
GROUP_MEMBER_HASH:{groupID} String 24小时 群成员列表哈希值 成员变更检测
GROUP_MEMBER_VERSION:{groupID} Hash 永久 群成员版本信息 增量同步控制
USER_JOIN_GROUP_VERSION:{userID} Hash 永久 用户加群版本信息 用户群组同步
4. 群申请管理缓存
缓存Key格式 数据类型 TTL时间 缓存内容 使用场景
GROUP_REQUEST_COUNT:{groupID} String 30分钟 待处理申请数量 申请数量统计
USER_GROUP_REQUESTS:{userID} List 2小时 用户发起的群申请 申请历史查询
GROUP_PENDING_REQUESTS:{groupID} List 1小时 群组待处理申请 申请管理页面

第三部分:群组管理操作权限矩阵

🔐 群组操作权限控制表

OpenIM群组系统采用严格的分级权限控制机制,根据用户角色不同,拥有不同的操作权限。以下表格详细列出了所有群组管理操作及其对应的角色权限:

操作名称 功能描述 系统管理员 群主 管理员 普通成员 特殊说明
CreateGroup 创建群组 需要通过CheckAccessV3验证权限
InviteUserToGroup 邀请用户加入群组 ⚠️ 普通成员在需验证群组中只能发起申请
KickGroupMember 踢出群组成员 ⚠️ 管理员不能踢出群主和其他管理员
QuitGroup 退出群组 群主不能退出群组,需先转让群主
SetGroupInfo 设置群组信息 修改群名称、头像、公告等信息
SetGroupInfoEx 扩展设置群组信息 扩展版本的群组信息设置
TransferGroupOwner 转让群主 只有群主可以转让群主身份
DismissGroup 解散群组 解散群组是不可逆操作
MuteGroupMember 禁言群组成员 ⚠️ 管理员不能禁言群主和其他管理员
CancelMuteGroupMember 取消禁言群组成员 ⚠️ 权限规则同禁言操作
MuteGroup 全群禁言 禁止所有成员发言
CancelMuteGroup 取消全群禁言 恢复群组正常发言
SetGroupMemberInfo 设置群成员信息 ⚠️ ⚠️ 角色权限有复杂的层级控制
GroupApplicationResponse 处理群组申请 审核加群申请(同意/拒绝)
JoinGroup 申请加入群组 所有用户都可以申请加群
GetGroupMemberList 获取群成员列表 需要是群组成员或系统管理员
GetGroupAllMember 获取群所有成员 无特殊权限限制
GetGroupsInfo 获取群组信息 获取群组基本信息
GetGroupMembersInfo 获取群成员详细信息 需要是群组成员或系统管理员
GetGroupApplicationList 获取群组申请列表 查看待处理的加群申请
GetUserReqApplicationList 获取用户申请列表 查看用户发起的申请(需权限验证)

🏷️ 权限标识说明

标识 含义 说明
完全权限 可以执行该操作,无特殊限制
⚠️ 有条件权限 可以执行,但有特定条件或限制
无权限 不能执行该操作

🔒 详细权限控制规则

1. 系统管理员权限特性
  • 最高权限 :系统管理员通过authverify.IsAppManagerUid()验证,拥有所有群组的完全控制权
  • 跨群组操作:可以操作任何群组,不受群组成员身份限制
  • 权限覆盖:可以绕过大部分业务权限验证
2. 群主权限特性
  • 群组所有者:拥有该群组的完全控制权(除了退出群组)
  • 不可退出:群主不能直接退出群组,必须先转让群主身份
  • 最高管理权:可以踢出任何成员、设置任何成员角色
3. 管理员权限特性
  • 有限管理权:可以进行大部分管理操作,但不能操作群主和其他管理员
  • 禁言限制:不能禁言群主,对其他管理员的操作受限
  • 踢出限制:不能踢出群主和其他管理员
4. 普通成员权限特性
  • 基础权限:主要是查看和自我管理权限
  • 申请权限:可以申请加入群组、退出群组
  • 受限操作:大部分管理操作需要更高权限
5. 特殊权限控制场景
场景 权限规则 代码实现
角色变更 只能降低或保持角色等级,不能提升自己角色 SetGroupMemberInfo中的复杂权限验证
邀请验证 根据群组验证设置决定直接加入还是申请模式 InviteUserToGroup中的验证逻辑
权限继承 高等级角色拥有低等级角色的所有权限 各方法中的角色等级比较
操作审计 所有管理操作记录操作者信息 OperatorUserID字段记录
Webhook扩展 支持业务自定义权限验证逻辑 各操作前后的Webhook回调
6. 权限验证代码模式
go 复制代码
// 模式1:系统管理员检查
if !authverify.IsAppManagerUid(ctx, g.config.Share.IMAdminUserID) {
    // 非系统管理员需要进一步权限验证
}

// 模式2:群组管理员检查  
func (g *groupServer) CheckGroupAdmin(ctx context.Context, groupID string) error {
    if !authverify.IsAppManagerUid(ctx, g.config.Share.IMAdminUserID) {
        groupMember, err := g.db.TakeGroupMember(ctx, groupID, mcontext.GetOpUserID(ctx))
        if err != nil {
            return err
        }
        if !(groupMember.RoleLevel == constant.GroupOwner || groupMember.RoleLevel == constant.GroupAdmin) {
            return errs.ErrNoPermission.WrapMsg("no group owner or admin")
        }
    }
    return nil
}

// 模式3:群组成员检查
func (g *groupServer) checkAdminOrInGroup(ctx context.Context, groupID string) error {
    if authverify.IsAppManagerUid(ctx, g.config.Share.IMAdminUserID) {
        return nil
    }
    // 检查是否为群组成员
}
7. 权限验证函数映射表
验证函数 适用操作 权限要求
CheckGroupAdmin 群组管理操作 系统管理员 或 群主/管理员
checkAdminOrInGroup 群组信息查询 系统管理员 或 群组成员
authverify.CheckAccessV3 用户相关操作 本人操作 或 系统管理员
authverify.IsAppManagerUid 所有操作 系统管理员验证


第四部分:群组管理操作详细流程分析

🔄 操作关系图谱

在深入分析每个操作的详细流程之前,我们先通过关系图谱了解各个操作之间的依赖和关联关系:

graph TD subgraph "核心管理操作" A[CreateGroup] --> B[InviteUserToGroup] A --> C[SetGroupInfo] B --> D[GetGroupMemberList] C --> E[GroupInfoSetNotification] end subgraph "成员管理操作" F[JoinGroup] --> G[GroupApplicationResponse] G --> H[MemberEnterNotification] B --> I[MuteGroupMember] I --> J[CancelMuteGroupMember] K[KickGroupMember] --> L[MemberQuitNotification] M[QuitGroup] --> L end subgraph "权限管理操作" N[TransferGroupOwner] --> O[GroupOwnerTransferredNotification] P[SetGroupMemberInfo] --> Q[GroupMemberInfoSetNotification] R[MuteGroup] --> S[CancelMuteGroup] end subgraph "解散相关操作" T[DismissGroup] --> U[GroupDismissedNotification] M --> V{是否群主} V -->|是| T V -->|否| L end subgraph "查询操作" W[GetGroupsInfo] --> X[GetGroupMembersInfo] D --> X Y[GetGroupApplicationList] --> Z[GetUserReqApplicationList] end

🎯 操作分类与数据流转模式

操作类型 典型操作 数据流转特点 缓存影响范围 通知触发
创建类 CreateGroup, JoinGroup 新增数据,大量缓存更新 全局影响 多用户通知
修改类 SetGroupInfo, MuteGroupMember 更新数据,局部缓存失效 局部影响 群组通知
删除类 KickGroupMember, DismissGroup 删除数据,大量缓存清理 广泛影响 多用户通知
查询类 GetGroupMemberList, GetGroupsInfo 读取操作,缓存优先 无影响 无通知
流程类 GroupApplicationResponse 状态变更,条件处理 条件影响 条件通知

📊 1. CreateGroup - 创建群组详细流程

sequenceDiagram participant Client as 客户端 participant API as Group RPC participant Redis as Redis缓存 participant MongoDB as MongoDB participant Notify as 通知服务 participant User as 用户服务 participant Conv as 会话服务 Client->>API: CreateGroupReq Note over API: 1. 权限验证阶段 API->>API: CheckAccessV3(创建者权限) Note over API: 2. 参数处理阶段 API->>API: GenGroupID(生成/验证GroupID) API->>User: GetUsersInfo(验证初始成员) User-->>API: 返回用户信息 Note over API: 3. 数据库操作阶段 API->>MongoDB: 开启事务 API->>MongoDB: 插入groups集合 Note over MongoDB: 插入字段:
- group_id
- group_name
- notification
- face_url
- status=0
- group_type
- need_verification API->>MongoDB: 批量插入group_members集合 Note over MongoDB: 群主成员记录:
- role_level=100
- join_source=1
- join_time=now() API->>MongoDB: 提交事务 Note over API: 4. 缓存清理阶段 API->>Redis: DEL GROUP_INFO:{groupID} API->>Redis: DEL JOIN_GROUPS:{creatorUserID} API->>Redis: DEL GROUP_MEMBER_IDS:{groupID} API->>Redis: DEL GROUP_MEMBER_NUM_CACHE:{groupID} API->>Redis: DEL GROUP_ROLE_LEVEL_MEMBER_IDS:{groupID} loop 每个初始成员 API->>Redis: DEL JOIN_GROUPS:{memberUserID} API->>Redis: DEL GROUP_MEMBER_INFO:{groupID}:{memberUserID} end Note over API: 5. 版本控制更新 API->>API: setVersion(groups, groupID) API->>API: setSortVersion(group_members, groupID) Note over API: 6. 通知发送阶段 API->>Notify: GroupCreatedNotification Note over Notify: 通知内容类型:
constant.GroupCreatedNotification
会话类型: ReadGroupChatType API->>Conv: SetConversations(创建群组会话) API-->>Client: CreateGroupResp{GroupInfo}

关键Redis Key操作清单:

  • GROUP_INFO:{groupID} - DELETE (新群组,确保缓存一致性)
  • GROUP_MEMBERS_HASH2:{groupID} - DELETE (新群组,确保缓存一致性)
  • GROUP_MEMBER_NUM_CACHE:{groupID} - DELETE
  • GROUP_MEMBER_IDS:{groupID} - DELETE
  • JOIN_GROUPS:{userID} - DELETE (每个初始成员)
  • GROUP_ROLE_LEVEL_MEMBER_IDS:{groupID}:{roleLevel} - DELETE
  • GROUP_MEMBERS_HASH:{groupID} - DELETE
  • GROUP_MEMBER_INFO:{groupID}:{userID} - DELETE

MongoDB操作清单:

  • groups 集合 - INSERT ONE (新群组记录)
  • group_members 集合 - INSERT MANY (初始成员记录)

👥 2. InviteUserToGroup - 邀请用户加群详细流程

sequenceDiagram participant Client as 客户端 participant API as Group RPC participant Redis as Redis缓存 participant MongoDB as MongoDB participant Notify as 通知服务 participant User as 用户服务 participant Webhook as Webhook服务 Client->>API: InviteUserToGroupReq Note over API: 1. 基础参数验证 API->>API: 验证被邀请用户列表非空 API->>API: 检查用户ID不重复 Note over API: 2. 群组状态验证 API->>MongoDB: TakeGroup(获取群组信息) MongoDB-->>API: 群组基础信息 API->>API: 检查群组状态!=GroupStatusDismissed Note over API: 3. 用户存在性验证 API->>User: GetUsersInfoMap(验证被邀请用户) User-->>API: 用户信息映射 API->>API: 确认所有被邀请用户存在 Note over API: 4. 操作者权限验证 alt 系统管理员 API->>API: IsAppManagerUid(检查系统管理员) API->>API: 获取操作者ID else 普通用户 API->>MongoDB: TakeGroupMember(获取操作者群组信息) MongoDB-->>API: 操作者群组成员信息 API->>User: PopulateGroupMember(填充用户信息) end Note over API: 5. Webhook前置回调 API->>Webhook: BeforeInviteUserToGroup Webhook-->>API: 回调结果 Note over API: 6. 群组验证策略判断 alt 群组需要验证(AllNeedVerification=1) alt 非系统管理员 && 非群主/管理员 Note over API: 创建入群申请模式 loop 每个被邀请用户 API->>API: 构建GroupRequest记录 Note over API: join_source=JoinByInvitation
inviter_user_id=操作者ID
req_time=当前时间 end API->>MongoDB: CreateGroupRequest(批量创建申请) loop 每个申请 API->>Notify: JoinGroupApplicationNotification end API-->>Client: 返回成功(申请已创建) else 系统管理员或群主/管理员 Note over API: 继续直接邀请流程 end else 其他验证策略 Note over API: 直接邀请流程 end Note over API: 7. 直接邀请流程 loop 每个被邀请用户 API->>API: 构建GroupMember记录 Note over API: role_level=GroupOrdinaryUsers(20)
join_source=JoinByInvitation(2)
inviter_user_id=操作者ID
join_time=当前时间 end Note over API: 8. Webhook成员加入前回调 API->>Webhook: BeforeMemberJoinGroup Webhook-->>API: 回调结果 Note over API: 9. 批量处理邀请(每批50个) loop 分批处理(每批singleQuantity=50) API->>MongoDB: CreateGroup(批量插入group_members) Note over MongoDB: 事务插入群成员记录
触发缓存清理链式操作 Note over API: 9.1 MongoDB事务操作 MongoDB->>MongoDB: group_members.insertMany() Note over API: 9.2 Redis缓存清理 MongoDB->>Redis: 清理相关缓存 Redis->>Redis: DelGroupMembersHash(groupID) Redis->>Redis: DelGroupsMemberNum(groupID) Redis->>Redis: DelGroupMemberIDs(groupID) loop 每个新成员 Redis->>Redis: DelJoinedGroupID(userID) Redis->>Redis: DelGroupMembersInfo(groupID, userID) end Redis->>Redis: DelGroupAllRoleLevel(groupID) Redis->>Redis: DelMaxJoinGroupVersion(userIDs) Redis->>Redis: DelMaxGroupMemberVersion(groupID) Note over API: 9.3 发送成员加入通知 API->>Notify: GroupApplicationAgreeMemberEnterNotification Note over Notify: 通知类型: MemberEnterNotification
通知对象: 群组所有成员
消息内容: 新成员加入信息 end API-->>Client: InviteUserToGroupResp(成功)

🔍 邀请验证策略详细解析

OpenIM支持三种群组邀请验证策略,通过NeedVerification字段控制:

验证值 常量名 验证策略 邀请者权限要求 行为描述
0 ApplyNeedVerificationInviteDirectly 申请需验证,邀请直接进 无特殊限制 任何成员邀请都直接加入群组
1 AllNeedVerification 所有人需要验证 群主/管理员可直接邀请 普通成员邀请创建申请,需管理员审核
2 Directly 直接进群 无特殊限制 所有邀请都直接加入群组

💾 数据库操作详细分析

1. MongoDB事务操作

直接邀请模式的MongoDB操作:

javascript 复制代码
// 批量插入群成员记录
db.group_members.insertMany([
    {
        "group_id": "group_12345",
        "user_id": "user_67890",
        "role_level": 20,                    // GroupOrdinaryUsers
        "join_source": 2,                    // JoinByInvitation  
        "inviter_user_id": "inviter_11111",  // 邀请者ID
        "operator_user_id": "inviter_11111", // 操作者ID
        "join_time": ISODate("2024-01-15T10:30:00.000Z"),
        "mute_end_time": ISODate("1970-01-01T00:00:00.000Z")
    }
    // ... 更多成员记录
])

申请模式的MongoDB操作:

javascript 复制代码
// 批量插入群申请记录
db.group_requests.insertMany([
    {
        "group_id": "group_12345",
        "user_id": "user_67890",
        "join_source": 2,                    // JoinByInvitation
        "inviter_user_id": "inviter_11111",  // 邀请者ID
        "req_time": ISODate("2024-01-15T10:30:00.000Z"),
        "handled_time": ISODate("1970-01-01T00:00:00.000Z"),
        "handle_result": 0,                  // 待处理状态
        "req_msg": "",                       // 申请消息(邀请时为空)
        "handled_msg": ""                    // 处理消息(待处理时为空)
    }
    // ... 更多申请记录
])
2. Redis缓存管理策略

OpenIM采用链式缓存清理机制,确保数据一致性:

缓存清理顺序与原因:

go 复制代码
// 缓存清理链式操作
c := g.cache.CloneGroupCache()

// 1. 群组成员相关缓存
c = c.DelGroupMembersHash(groupID)           // 成员列表哈希,用于变更检测
     .DelGroupsMemberNum(groupID)            // 成员数量缓存
     .DelGroupMemberIDs(groupID)             // 成员ID列表缓存
     
// 2. 用户相关缓存(针对每个新成员)  
     .DelJoinedGroupID(userID)               // 用户加入的群组列表
     .DelGroupMembersInfo(groupID, userID)   // 单个成员详细信息
     
// 3. 角色相关缓存
     .DelGroupAllRoleLevel(groupID)          // 所有角色级别的成员缓存
     
// 4. 版本控制缓存
     .DelMaxJoinGroupVersion(userIDs)        // 用户加群版本
     .DelMaxGroupMemberVersion(groupID)      // 群成员版本

// 执行链式删除
return c.ChainExecDel(ctx)

关键Redis Key分析:

缓存Key模式 数据类型 作用 清理原因
GROUP_MEMBERS_HASH:{groupID} String 成员列表哈希值 成员变更需重新计算哈希
GROUP_MEMBER_NUM:{groupID} String 成员数量 新成员加入,数量发生变化
GROUP_MEMBER_IDS:{groupID} List 成员ID列表 新成员ID需要添加到列表
JOIN_GROUPS:{userID} Set 用户参与的群组 用户新加入群组
GROUP_MEMBERS_INFO:{groupID}:{userID} Hash 成员详细信息 新成员信息需要重新加载
GROUP_ROLE_LEVEL_*:{groupID} Set 各角色成员列表 新成员加入普通成员角色

🚪 3. KickGroupMember - 踢出群成员详细流程

sequenceDiagram participant Admin as 管理员/群主 participant API as Group RPC participant Redis as Redis缓存 participant MongoDB as MongoDB participant Notify as 通知服务 participant Conv as 会话服务 Admin->>API: KickGroupMemberReq Note over API: 1. 权限验证阶段 API->>API: CheckGroupAdmin(操作者权限) API->>Redis: HGET GROUP_MEMBER_INFO:{groupID}:{operatorUserID} Redis-->>API: 操作者角色信息 Note over API: 2. 被踢用户权限检查 loop 每个被踢用户 API->>Redis: HGET GROUP_MEMBER_INFO:{groupID}:{kickedUserID} Redis-->>API: 被踢用户角色信息 API->>API: 权限规则验证 Note over API: 规则:管理员不能踢群主
管理员不能踢其他管理员 end Note over API: 3. 数据库删除操作 API->>MongoDB: 开启事务 loop 每个被踢用户 API->>MongoDB: DELETE FROM group_members WHERE group_id=? AND user_id=? end API->>MongoDB: 提交事务 Note over API: 4. 大量缓存清理 loop 每个被踢用户 API->>Redis: DEL GROUP_MEMBER_INFO:{groupID}:{kickedUserID} API->>Redis: DEL JOIN_GROUPS:{kickedUserID} end API->>Redis: DEL GROUP_MEMBER_IDS:{groupID} API->>Redis: DEL GROUP_MEMBER_NUM_CACHE:{groupID} API->>Redis: DEL GROUP_MEMBERS_HASH:{groupID} Note over API: 5. 会话管理 loop 每个被踢用户 API->>Conv: SetConversationMaxSeq(更新会话序号) end Note over API: 6. 版本控制 API->>API: setVersion(group_members, groupID) Note over API: 7. 通知发送 API->>Notify: MemberKickedNotification Note over Notify: 通知对象:
1. 被踢用户:踢出通知
2. 群内其他成员:成员变更通知
通知类型:MemberKickedNotification API-->>Admin: KickGroupMemberResp{Success}

详细缓存操作列表:

删除的Redis Key:

  • GROUP_MEMBER_INFO:{groupID}:{kickedUserID} - DELETE (每个被踢用户)
  • JOIN_GROUPS:{kickedUserID} - DELETE (每个被踢用户)
  • GROUP_MEMBER_IDS:{groupID} - DELETE (成员ID列表)
  • GROUP_MEMBER_NUM_CACHE:{groupID} - DELETE (成员数量)
  • GROUP_MEMBERS_HASH:{groupID} - DELETE (成员哈希)

权限验证规则代码逻辑:

go 复制代码
// 权限验证逻辑
if operatorRole == constant.GroupOwner {
    // 群主可以踢任何人
    return true
} else if operatorRole == constant.GroupAdmin {
    // 管理员只能踢普通成员
    return targetRole == constant.GroupOrdinaryUsers
}
return false

⚙️ 4. SetGroupInfo - 设置群组信息详细流程

stateDiagram-v2 [*] --> ValidatePermission : SetGroupInfoReq ValidatePermission --> CheckFields : 权限验证通过 ValidatePermission --> [*] : 权限不足返回错误 CheckFields --> DetectChanges : 字段有效性验证 DetectChanges --> HandleNameChange : 群名称变更 DetectChanges --> HandleAnnouncementChange : 群公告变更 DetectChanges --> HandleNormalChange : 其他信息变更 HandleNameChange --> UpdateMongoDB : 更新群名称 HandleAnnouncementChange --> UpdateMongoDB : 更新公告信息 HandleNormalChange --> UpdateMongoDB : 更新基础信息 UpdateMongoDB --> ClearRedisCache : MongoDB更新成功 ClearRedisCache --> UpdateVersion : 清理群组信息缓存 UpdateVersion --> SendNotification : 版本控制更新 SendNotification --> [*] : 通知发送完成 UpdateMongoDB --> [*] : 数据库更新失败

具体操作细节:

MongoDB更新操作:

javascript 复制代码
// 根据不同字段执行不同的更新操作
db.groups.updateOne(
    { "group_id": "groupID" },
    {
        $set: {
            // 群名称变更
            "group_name": "新群名称",
            
            // 群公告变更(特殊处理)
            "notification": "新公告内容",
            "notification_update_time": new Date(),
            "notification_user_id": "operatorUserID",
            
            // 其他基础信息
            "introduction": "新群介绍",
            "face_url": "http://new-avatar.url",
            "need_verification": 1,
            "look_member_info": 0,
            "apply_member_friend": 1
        }
    }
)

Redis缓存操作:

  • GROUP_INFO:{groupID} - DELETE (群组基础信息缓存失效)

通知分发逻辑:

变更字段 通知类型 通知对象 特殊处理
group_name GroupInfoSetNameNotification 群组所有成员 会话标题更新
notification GroupInfoSetAnnouncementNotification 群组所有成员 公告弹窗提醒
其他字段 GroupInfoSetNotification 群组所有成员 基础信息同步

👑 5. TransferGroupOwner - 转让群主详细流程

sequenceDiagram participant Owner as 当前群主 participant API as Group RPC participant Redis as Redis缓存 participant MongoDB as MongoDB participant Notify as 通知服务 Owner->>API: TransferGroupOwnerReq Note over API: 1. 身份验证阶段 API->>Redis: HGET GROUP_MEMBER_INFO:{groupID}:{currentOwnerID} Redis-->>API: role_level=100 (群主身份确认) API->>Redis: HGET GROUP_MEMBER_INFO:{groupID}:{newOwnerID} Redis-->>API: 新群主成员信息 Note over API: 2. 数据库事务操作 API->>MongoDB: 开启事务 API->>MongoDB: UPDATE group_members SET role_level=20 WHERE group_id=? AND user_id=? Note over MongoDB: 原群主降级为普通成员
role_level: 100 → 20 API->>MongoDB: UPDATE group_members SET role_level=100 WHERE group_id=? AND user_id=? Note over MongoDB: 新群主升级
role_level: 20/60 → 100 API->>MongoDB: 提交事务 Note over API: 3. 大量缓存清理 API->>Redis: DEL GROUP_OWNER:{groupID} API->>Redis: DEL GROUP_MEMBER_INFO:{groupID}:{currentOwnerID} API->>Redis: DEL GROUP_MEMBER_INFO:{groupID}:{newOwnerID} API->>Redis: DEL GROUP_ROLE_LEVEL_MEMBERS:{groupID}:100 API->>Redis: DEL GROUP_ROLE_LEVEL_MEMBERS:{groupID}:20 API->>Redis: DEL GROUP_ROLE_LEVEL_MEMBERS:{groupID}:60 Note over API: 4. 版本控制更新 API->>API: setVersion(group_members, groupID) Note over API: 5. 通知发送 API->>Notify: GroupOwnerTransferredNotification Note over Notify: 通知对象:
1. 原群主:角色变更通知
2. 新群主:群主权限获得
3. 群内成员:群主变更通知 API-->>Owner: TransferGroupOwnerResp{Success}

关键操作分析:

MongoDB事务操作:

javascript 复制代码
// 事务保证原子性操作
session.withTransaction(() => {
    // 降低原群主权限
    db.group_members.updateOne(
        { "group_id": groupID, "user_id": currentOwnerID },
        { 
            $set: { 
                "role_level": 20,
                "operator_user_id": currentOwnerID 
            }
        }
    );
    
    // 提升新群主权限  
    db.group_members.updateOne(
        { "group_id": groupID, "user_id": newOwnerID },
        { 
            $set: { 
                "role_level": 100,
                "operator_user_id": currentOwnerID 
            }
        }
    );
});

角色相关缓存清理:

  • GROUP_OWNER:{groupID} - DELETE (群主信息)
  • GROUP_ROLE_LEVEL_MEMBERS:{groupID}:100 - DELETE (群主角色成员列表)
  • GROUP_ROLE_LEVEL_MEMBERS:{groupID}:20 - DELETE (普通成员角色列表)
  • GROUP_ROLE_LEVEL_MEMBERS:{groupID}:60 - DELETE (管理员角色列表)

🔕 6. MuteGroupMember - 禁言群成员详细流程

flowchart TD A[MuteGroupMemberReq] --> B[权限验证] B --> C{CheckGroupAdmin结果} C -->|权限不足| D[返回权限错误] C -->|权限通过| E[获取被禁言者信息] E --> F[Redis查询] F --> G["HGET GROUP_MEMBER_INFO:{groupID}:{mutedUserID}"] G --> H[验证角色权限] H --> I{被禁言者角色检查} I -->|群主| J[禁止操作返回错误] I -->|管理员且操作者非群主| J I -->|可以禁言| K[计算禁言时间] K --> L["muteEndTime = now() + mutedSeconds"] L --> M[MongoDB更新操作] M --> N["UPDATE group_members SET mute_end_time=? WHERE group_id=? AND user_id=?"] N --> O[Redis缓存更新] O --> P["DEL GROUP_MEMBER_INFO:{groupID}:{mutedUserID}"] P --> Q[版本控制更新] Q --> R[setVersion group_members] R --> S[发送禁言通知] S --> T[GroupMemberMutedNotification] T --> U[返回成功响应]

禁言权限验证矩阵:

操作者角色 被禁言者角色 操作结果 说明
群主 任何角色 ✅ 允许 群主拥有最高权限
管理员 普通成员 ✅ 允许 管理员可以禁言普通成员
管理员 管理员 ❌ 禁止 管理员间平级,不能相互操作
管理员 群主 ❌ 禁止 管理员不能操作群主
普通成员 任何角色 ❌ 禁止 普通成员无禁言权限

MongoDB更新字段:

javascript 复制代码
{
    "mute_end_time": new Date(Date.now() + mutedSeconds * 1000),
    "operator_user_id": operatorUserID
}

Redis缓存影响:

  • GROUP_MEMBER_INFO:{groupID}:{mutedUserID} - DELETE (成员信息缓存)

📋 7. GetGroupMemberList - 获取群成员列表详细流程

sequenceDiagram participant Client as 客户端 participant API as Group RPC participant LocalCache as 本地缓存 participant Redis as Redis缓存 participant MongoDB as MongoDB Client->>API: GetGroupMemberListReq{groupID, pagination} Note over API: 1. 权限验证 API->>API: checkAdminOrInGroup(验证成员身份) Note over API: 2. 本地缓存查询 API->>LocalCache: 查询成员列表缓存 LocalCache-->>API: 缓存未命中 Note over API: 3. Redis缓存查询 API->>Redis: LRANGE GROUP_MEMBER_IDS:{groupID} offset limit alt Redis缓存命中 Redis-->>API: 返回成员ID列表 Note over API: 4. 批量查询成员详情 loop 每个成员ID API->>Redis: HGETALL GROUP_MEMBER_INFO:{groupID}:{userID} end Redis-->>API: 成员详细信息 Note over API: 5. 缓存回写 API->>LocalCache: 更新本地缓存 else Redis缓存未命中 Note over API: 6. 数据库查询 API->>MongoDB: db.group_members.find({group_id}).sort({role_level: -1, join_time: 1}).skip().limit() MongoDB-->>API: 完整成员信息 Note over API: 7. 缓存预热 API->>Redis: LPUSH GROUP_MEMBER_IDS:{groupID} memberIDs... loop 每个成员 API->>Redis: HSET GROUP_MEMBER_INFO:{groupID}:{userID} memberInfo end API->>LocalCache: 更新本地缓存 end Note over API: 8. 数据转换 API->>API: groupMemberDB2PB(格式转换) API-->>Client: GetGroupMemberListResp{members, pagination}

缓存策略分析:

三级缓存架构:

  1. 本地缓存:进程内缓存,最快访问速度
  2. Redis缓存:分布式缓存,支持集群共享
  3. MongoDB:持久化存储,数据源头

Redis Key使用:

  • GROUP_MEMBER_IDS:{groupID} - List类型,存储成员ID列表
  • GROUP_MEMBER_INFO:{groupID}:{userID} - Hash类型,存储成员详细信息

分页查询优化:

javascript 复制代码
// MongoDB聚合查询,支持高效分页
db.group_members.aggregate([
    { $match: { "group_id": groupID } },
    { $sort: { 
        "role_level": -1,  // 按角色等级倒序(群主>管理员>普通成员)
        "join_time": 1     // 同等级按加入时间正序
    }},
    { $skip: offset },
    { $limit: pageSize }
]);

📝 8. GroupApplicationResponse - 处理群组申请详细流程

stateDiagram-v2 [*] --> ReceiveRequest : GroupApplicationResponseReq ReceiveRequest --> ValidateHandler : 接收处理请求 ValidateHandler --> GetApplication : 验证处理者权限 GetApplication --> CheckStatus : 获取申请详情 CheckStatus --> ProcessApproval : handle_result=1(同意) CheckStatus --> ProcessRejection : handle_result=-1(拒绝) CheckStatus --> [*] : 申请已处理返回错误 ProcessApproval --> CheckMemberExists : 同意申请 CheckMemberExists --> CreateMember : 用户未在群组 CheckMemberExists --> UpdateApplicationOnly : 用户已在群组 CreateMember --> MongoTransaction : 创建成员记录 MongoTransaction --> UpdateApplication : 更新申请状态 UpdateApplication --> ClearCache : 清理相关缓存 ClearCache --> SendApprovalNotify : 发送同意通知 SendApprovalNotify --> [*] : 完成处理 UpdateApplicationOnly --> SendApprovalNotify : 仅更新申请状态 ProcessRejection --> UpdateRejection : 拒绝申请 UpdateRejection --> SendRejectionNotify : 发送拒绝通知 SendRejectionNotify --> [*] : 完成处理 ValidateHandler --> [*] : 权限验证失败

详细数据操作:

同意申请的事务操作:

javascript 复制代码
// MongoDB事务确保数据一致性
session.withTransaction(() => {
    // 1. 更新申请状态
    db.group_requests.updateOne(
        { 
            "group_id": groupID, 
            "user_id": applicantUserID,
            "handle_result": 0  // 仅处理待处理的申请
        },
        {
            $set: {
                "handle_result": 1,  // 1=同意
                "handled_msg": "欢迎加入群组",
                "handle_user_id": handlerUserID,
                "handled_time": new Date()
            }
        }
    );
    
    // 2. 创建群成员记录(如果用户不在群中)
    db.group_members.insertOne({
        "group_id": groupID,
        "user_id": applicantUserID,
        "role_level": 20,           // 普通成员
        "join_source": 3,           // 通过申请加入
        "join_time": new Date(),
        "operator_user_id": handlerUserID,
        "mute_end_time": new Date(0)
    });
});

拒绝申请操作:

javascript 复制代码
// 仅更新申请状态,不创建成员记录
db.group_requests.updateOne(
    { "group_id": groupID, "user_id": applicantUserID },
    {
        $set: {
            "handle_result": -1,  // -1=拒绝
            "handled_msg": "申请被拒绝",
            "handle_user_id": handlerUserID,
            "handled_time": new Date()
        }
    }
);

缓存清理操作:

  • GROUP_MEMBER_IDS:{groupID} - DELETE (成员列表)
  • GROUP_MEMBER_NUM_CACHE:{groupID} - DELETE (成员数量)
  • JOIN_GROUPS:{applicantUserID} - DELETE (申请者加群列表)
  • GROUP_PENDING_REQUESTS:{groupID} - DELETE (待处理申请列表)

通知发送逻辑:

处理结果 通知类型 通知对象 通知内容
同意 GroupApplicationAcceptedNotification 申请者 "您的入群申请已通过"
同意 MemberEnterNotification 群组成员 "XXX加入了群组"
拒绝 GroupApplicationRejectedNotification 申请者 "您的入群申请被拒绝"

🏠 9. QuitGroup - 退出群组详细流程

sequenceDiagram participant Client as 客户端 participant API as Group RPC participant Redis as Redis缓存 participant MongoDB as MongoDB participant Notify as 通知服务 participant Conv as 会话服务 Client->>API: QuitGroupReq Note over API: 1. 验证用户身份 API->>MongoDB: TakeGroupMember(获取成员信息) MongoDB-->>API: 成员角色信息 Note over API: 2. 成员身份检查 alt 非群成员 API-->>Client: 返回非成员错误 else 是群成员 Note over API: 3. 角色判断 alt 群主退群(role_level=100) API->>MongoDB: FindGroupMemberNum(查询成员数量) MongoDB-->>API: 群成员总数 alt 仅群主1人 Note over API: 自动解散群组 API->>API: 调用DismissGroup API-->>Client: 群组解散完成 else 还有其他成员 API-->>Client: 返回错误:需先转让群主 end else 普通成员退群 Note over API: 4. 执行退群流程 API->>MongoDB: 开启事务 API->>MongoDB: DELETE FROM group_members Note over MongoDB: 删除成员记录 Note over API: 5. Redis缓存清理 API->>Redis: DEL GROUP_MEMBER_INFO:{groupID}:{userID} API->>Redis: DEL JOIN_GROUPS:{userID} API->>Redis: DEL GROUP_MEMBER_IDS:{groupID} API->>Redis: DEL GROUP_MEMBER_NUM_CACHE:{groupID} Note over API: 6. 会话管理 API->>Conv: SetConversationMaxSeq(更新会话序号) Note over API: 7. 版本控制更新 API->>API: setVersion(group_members) Note over API: 8. 发送退群通知 API->>Notify: MemberQuitNotification Note over Notify: 通知群内其他成员:
XXX退出了群组 API-->>Client: 退群成功 end end

群主退群特殊逻辑:

go 复制代码
// 群主退群权限检查
func (g *groupServer) QuitGroup(ctx context.Context, req *pbgroup.QuitGroupReq) (*pbgroup.QuitGroupResp, error) {
    // 1. 获取操作者在群中的信息
    member, err := g.db.TakeGroupMember(ctx, req.GroupID, req.UserID)
    if err != nil {
        return nil, err
    }
    
    // 2. 群主退群特殊处理
    if member.RoleLevel == constant.GroupOwner {
        // 查询群成员总数
        memberCount, err := g.db.FindGroupMemberNum(ctx, req.GroupID)
        if err != nil {
            return nil, err
        }
        
        if memberCount == 1 {
            // 仅群主一人,解散群组
            return g.DismissGroup(ctx, &pbgroup.DismissGroupReq{
                GroupID: req.GroupID,
                UserID:  req.UserID,
            })
        } else {
            // 还有其他成员,需要先转让群主
            return nil, errs.ErrArgs.WrapMsg("群主需要先转让群主权限才能退群")
        }
    }
    
    // 3. 普通成员直接退出
    return g.quitGroupDirectly(ctx, req)
}

数据一致性保证:

  • MongoDB删除操作:确保成员记录彻底删除
  • Redis缓存清理:避免脏数据,保证缓存一致性
  • 会话序号更新:确保消息同步的准确性
  • 版本控制更新:支持增量同步机制

💀 10. DismissGroup - 解散群组详细流程

sequenceDiagram participant Owner as 群主 participant API as Group RPC participant Redis as Redis缓存 participant MongoDB as MongoDB participant Notify as 通知服务 participant Conv as 会话服务 Owner->>API: DismissGroupReq Note over API: 1. 权限验证 API->>API: CheckGroupAdmin(仅群主或系统管理员) Note over API: 2. 获取群组信息 API->>MongoDB: 查询groups集合 MongoDB-->>API: 群组基础信息 API->>MongoDB: 查询group_members集合 MongoDB-->>API: 所有群成员列表 Note over API: 3. 数据库批量删除 API->>MongoDB: 开启事务 API->>MongoDB: DELETE FROM group_members WHERE group_id=? Note over MongoDB: 删除所有群成员记录 API->>MongoDB: DELETE FROM groups WHERE group_id=? Note over MongoDB: 删除群组记录 API->>MongoDB: DELETE FROM group_requests WHERE group_id=? Note over MongoDB: 删除所有相关申请记录 API->>MongoDB: 提交事务 Note over API: 4. 大量缓存清理 API->>Redis: DEL GROUP_INFO:{groupID} API->>Redis: DEL GROUP_MEMBER_IDS:{groupID} API->>Redis: DEL GROUP_MEMBER_NUM_CACHE:{groupID} API->>Redis: DEL GROUP_OWNER:{groupID} API->>Redis: DEL GROUP_MEMBERS_HASH:{groupID} loop 每个群成员 API->>Redis: DEL GROUP_MEMBER_INFO:{groupID}:{userID} API->>Redis: DEL JOIN_GROUPS:{userID} end Note over API: 5. 会话清理 loop 每个群成员 API->>Conv: SetConversationMaxSeq(清理群组会话) end Note over API: 6. 版本控制 API->>API: setVersion(groups, groupID) API->>API: setVersion(group_members, groupID) Note over API: 7. 解散通知 API->>Notify: GroupDismissedNotification Note over Notify: 通知对象:所有群成员
通知内容:群组已解散
触发客户端会话删除 API-->>Owner: DismissGroupResp{Success}

解散群组的数据清理范围:

MongoDB删除操作:

javascript 复制代码
// 事务保证数据一致性
session.withTransaction(() => {
    // 1. 删除所有群成员
    db.group_members.deleteMany({ "group_id": groupID });
    
    // 2. 删除群组记录
    db.groups.deleteOne({ "group_id": groupID });
    
    // 3. 删除相关申请记录
    db.group_requests.deleteMany({ "group_id": groupID });
});

Redis缓存清理列表:

  • GROUP_INFO:{groupID} - DELETE
  • GROUP_MEMBER_IDS:{groupID} - DELETE
  • GROUP_MEMBER_NUM_CACHE:{groupID} - DELETE
  • GROUP_OWNER:{groupID} - DELETE
  • GROUP_MEMBERS_HASH:{groupID} - DELETE
  • GROUP_MEMBER_INFO:{groupID}:{userID} - DELETE (每个成员)
  • JOIN_GROUPS:{userID} - DELETE (每个成员)
  • GROUP_PENDING_REQUESTS:{groupID} - DELETE
  • GROUP_REQUEST_COUNT:{groupID} - DELETE

通知影响分析:

  • GroupDismissedNotification:通知所有群成员群组已解散
  • 会话清理:触发客户端删除群组会话
  • 数据同步:版本控制确保所有设备同步解散状态

以上详细解析了OpenIM群聊管理的核心功能模块和完整的权限控制体系。每个功能都包含完整的权限验证、数据存储、缓存管理和通知机制,确保群组管理的安全性、一致性和用户体验。完善的权限矩阵为系统提供了精细化的访问控制,满足不同场景下的安全需求。

相关推荐
用户914536330839130 分钟前
ThreadLocal详解:线程私有变量的正确使用姿势
后端
用户40993225021239 分钟前
如何在FastAPI中实现权限隔离并让用户乖乖听话?
后端·ai编程·trae
阿星AI工作室1 小时前
n8n教程:5分钟部署+自动生AI日报并写入飞书多维表格
前端·人工智能·后端
郝同学的测开笔记1 小时前
深入理解 kubectl port-forward:快速调试 Kubernetes 服务的利器
后端·kubernetes
Ray661 小时前
store vs docValues vs index
后端
像污秽一样1 小时前
软件开发新技术复习
java·spring boot·后端·rabbitmq·cloud
Y_3_72 小时前
Netty实战:从核心组件到多协议实现(超详细注释,udp,tcp,websocket,http完整demo)
linux·运维·后端·ubuntu·netty
小雄Ya2 小时前
Auth01|常见三种登录认证机制
后端·go
颛顼2 小时前
【源码分析】:从零拆解bs_worker的3层核心架构
后端·搜索引擎
yihuiComeOn2 小时前
【大数据高并发核心场景实战】 - 数据持久化之冷热分离
java·后端