设计遐想---基于Google App Engine的IM

聊天模式无非点对点聊天和群组聊天.下面一一来分析.

1. Peer-to-Peer聊天

消息格式:[from, to, body, timestamp, isread].(根据from来识别是个人还是group消息)

消息读取方式
  标记模式
  置位模式

是否要存储: 
  不需要
  需要



[Group Chatting]:

标记模式
每个用户拥有一个timestamp类型的消息游标.(sequence number不利于sharding).
option: 消息携带一个counter, 每被读取一次引用计数就减一.引用计数到0时.消息会删除.
优点: 节省存储空间.
缺点: 实现稍微复杂.

    Non-Persistent
        只需要有一个Expirer, 定期清理超期信息.
    Persistent
        只需要关闭Expirer.


置位模式
需要复制Group Size个副本.获取最近的消息列表: 根据timestamp差值(timespan)和pageSize来获取最近消息列表.
优点: 实现简单
缺点: 浪费存储空间

    Non-Persistent
        用户读取后即删除.
    Persistent
        读取后设置isread为true


权衡
        信息量小
            需要持久化
                可以直接操作db.
            不需要持久化
                可以直接memcache来实现.
        信息量大
            需要持久化
                考虑write-back机制(timeout + 阀值触发).
            不需要持久化
                mem可能不足,仍然考虑write-back机制(timeout + 阀值触发).只不过读取后会删除.
 

在GAE平台上如何考虑
1. GAE memcache为简单key/value型,而消息存取最好是集合操作,也就是需要一个结构化的memcache(比如mongoDB).
2. GAE datastore为Master/Slave模型, 读快写慢,而IM的特征是读写平均. 但是基于GAE的可扩展性, 对于单笔操作而言开销不会随负载增长.
综上考虑, 消息每次直接经过DB.

置位还是标记?
优先选择置位模型.

Group信息在memcache中进行缓存.在DataStore中以StringListProperty的方式保存用户列表.


收发消息Solution 1:
1. 消息直接存入datastore.
2. 先取peer消息.
3. 取Group消息:
  1). 获取用户的所有group(用户所在组的信息也存在于memcache).[complex, fucking thing]
  2). 以groupid为key,去datastore检索消息.[loop]


收发消息Solution 2:
在置位模型下,消息可以保存一个StringListProperty类型的receivers字段.
1. 用户发送消息,根据group id得到用户列表,即为receivers字段取值.存入datastore.
2. 取消息. 对比用户id和receivers来还有时间戳来取消息.

收发消息solution的权衡:
如果群组数量很多,方案1的效率就很差.
如果单个群组的成员很多, 方案2的效率就很差, receivers列表的存储开销就比较明显了.
posted on 2009-09-01 16:57  彭帅  阅读(714)  评论(0编辑  收藏  举报