Android聊天应用消息存储:单文件存储方案可行性及优化咨询
关于方案可扩展性
以你当前设定的业务上限(单用户待投递消息不超过300条,单条消息≤10KB)来看,这套方案足够支撑中等规模的用户量,但如果未来业务有以下变化,会遇到明显的瓶颈:
- 用户量级突破十万级时,小文件会占用海量inode,绝大多数云服务商/主机商的磁盘inode配额都是远低于磁盘容量的,很容易出现还有剩余空间但无法写入新文件的问题
- 如果后续要新增多端同步、离线消息漫游、消息撤回这类功能,文件方案的状态同步成本会非常高,几乎无法适配
- 当并发投递请求变多时,
message_ids.txt的并发写入冲突会加剧,没有加锁的情况下大概率会出现ID丢失、文件内容损坏的问题
另外你现有流程存在一个明显的缺陷:拉取消息读取ID后,没有更新message_ids.txt删除已处理的ID,下次拉取还是会遍历到已经删除了消息文件的ID,会产生大量无效IO,甚至会干扰新消息的处理。
共享主机部署可能遇到的问题
本地测试没有问题不代表共享主机上能正常跑,大概率会遇到以下问题:
- 共享主机普遍对IOPS、单目录文件数、文件锁权限做了限制,很多共享主机使用的分布式文件系统不支持排他锁,
message_ids.txt的并发写入直接会出现数据错乱 - 共享主机的IO资源是多用户共享的,高峰期读写小文件的延迟会大幅上涨,甚至会出现文件操作超时,导致消息投递失败
- 多数共享主机会默认开启定期自动备份,你的临时消息会被存入备份集群,反而会带来额外的数据安全风险
- 部分共享主机的文件系统存在延迟回收机制,删除的文件会在后台暂存一段时间,容易超出你的磁盘配额
更优存储方案推荐
如果你坚持不使用关系型数据库,可以按优先级选择以下方案:
- 优化现有文件方案
给message_ids.txt的读写操作加排他锁,每次处理完消息后立即从文件中删除已处理的ID;如果想进一步降低inode占用,可以把1020条消息打包成一个批次文件,索引中记录每条消息的偏移量,比单条消息存一个文件的IO效率高35倍。 - 使用KV缓存替代文件存储
完全可以用Redis这类内存型KV存储,不需要做复杂的SQL操作:每个用户的待投递消息用list结构存储,投递时直接lpush写入消息,拉取时直接lrange取出所有消息后删除对应key即可,读写性能远高于文件方案,也不存在并发冲突问题,完全匹配你消息短周期存储的需求。 - 单文件打包存储
放弃单条消息存一个文件的设计,直接把单个用户的所有待投递消息和ID都存在同一个JSON格式的文件里,读写都只操作一个文件,锁机制也更好实现,能大幅降低小文件带来的各类问题。
内容的提问来源于stack exchange,提问作者The concise
相关产品推荐
相关产品推荐

