详解即时通讯设计实现(PHP+GatewayWorker+Redis)
需要实现的功能
- 一对一聊天(私聊)
- 一对多聊天(群聊)
- 类似QQ,微信等聊天列表 实时消息 显示
工具选择
-
GatewayWorker 有如下特性(更多请参考官网手册)
- 基于Workerman开发
- 基于Gateway、Worker进程模型
- 支持分布式部署
- 支持高并发
- 支持全局广播或者向任意客户端推送数据
- 支持各种应用层协议
- 多协议支持
- 支持对象或者资源永久保持
- 高性能
- 方便与其它项目集成
- 支持长连接
我们主要使用它的WebSocket通讯协议,并且此框架非常方便的与 ThinkPHP,laravel 等框架结合使用,GatewayWorker可独立部署,php负责相关的业务逻辑
- Redis 键值操作,集合列表等。
即时通讯中,最重要的是响应速度,我们需要展示 “消息列表” 那么这时会有 未读消息,未读数量,最后一条消息内容,时间等等。
websocket与GatewayWorker 原理使用 将不再叙述,不懂的童鞋 请上度娘
效果展示
群聊|私聊效果图
消息列表效果图
数据库设计(群聊,私聊 分开)
私聊设计(简要设计)
参数名 | 说明 |
---|---|
id | 主键 |
sender_id | 发送者id |
receive_id | 接收者id |
chat_identify | 标识 :a与b聊天,b与a聊天。记录 a-b |
message_details | 消息内容 |
last_time_at | 聊天时间间隔 超过一定时间时记录 |
- chat_identify 字段用处,这个字段是为了更方便的查找 a,b 之间的聊天记录。
- last_time_at QQ,微信聊天记录之间,隔一段时间会有 时间 记录,并不显示每一条聊天记录的时间
群聊(简要设计)
- 与私聊很像,只不过接收者id,变成 group_id 群组id。
消息列表设计,希望看到的效果是 “私聊,群聊”等都在一个列表展示,并且数据实时发生变化。这里借助Redis
每个用户的列表都是一个集合 key = message_list:user_id
Redis集合存储 消息类型 1私信,2群聊
message_list:user_id{
json_encode(['消息类型','接收者id|群组id']),
json_encode(['消息类型','接收者id|群组id']),
json_encode(['消息类型','接收者id|群组id']),
}
查找每个人的消息列表,直接取出该列表即可,但每个成员 都要对应 ‘未读消息数量’,‘最后一条消息内容’,‘最后一条小时时间’。由于是可变的,所以需要单独存储
Redis 键值 key = message_content:user_id_消息类型_id
key =>json_encode(['消息数量','最后一条消息内容','时间'])
上面 集合列表里的每一个成员都 对应这里的每个键值。
- 消息更新都要操作Redis,相应的更新内容。
- 速度上 毋庸置疑,redis 相当的迅速。
需要后续优化的地方
-
私聊|群聊 记录表。目前设计是单表单库。显然,随着用户量增加,必然爆棚。影响查询的响应速度。
- (解决方案无非:分库分表,转移备份历史记录)
- GatewayWorker 通讯框架,是单服务器部署,不能支持太高的并发。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。