mongodb数据库设计实践

我们公司开发了一款企业博客软件,采用mongodb这种存储海量数据的数据库。简单介绍一下软件的需求,方便后面讨论数据库设计,用户登录后,只能浏览别人发送的微博,只有他加入企业后,才可以代表企业发微博,同时被企业认证过的人或是企业员工可以在系统内转发微博。
数据库设计的时候,只有三个角色,就是人,公司,新闻,因此一开始设计的时候,就只有user,com,news三个表,加上日志表,新闻举报表等附属表。为了加快查询速度,采用redis保存了部分数据副本。
在开发中发现mongodb的多层嵌套不能太深,最好是两层,最多三层,否则增删改查数据不方便。这里的两层指的是一份文档下有一个列表,三层指的是这个列表的元素中,仍然有列表。
写新闻相关模块的时候,发现新闻列表的查询非常耗时间,就是因为每条新闻的查询都需要查询5~6个权限,而这些权限的查询都是要单独请求的,这种新闻和人之间的关系一方面实时性比较高,两次访问的权限可能都不一样。另一方面谁都可以浏览任何新闻啊,我不能每建一条新闻,就把所有人和新闻的关系全部都保存下来吧,一个人不可能把大多数的新闻都看完吧,所以只能是查询了。怎么办呢,采用存储过程,让查询在mongodb里面进行,只返回给我需要的数据就可以了(这个不影响数据库表结构,着急上线,还没有去弄)。原来的数据库设计的时候,对于用户头像什么的基本信息,直接从redis里面取了,不存在这种基本的数据还需要查询的情况,但是用存储过程的话,就只能从mongodb中查询了,但是我的一条数据包含了所有的列表数据,查询一次就意味着数据库要解析所有的数据,仅仅是返回给我一些基本的数据,感觉很费时间了,于是考虑数据库优化。于是将原来的表拆分了,拆成了基本信息表(只存储非列表数据),列表表(只存储列表数据),由于我们的应用是手机端的,界面比较小,极少出现那种同时需要列表数据和基本数据的情况。
优化后,觉得如果遇到大V那种,他的粉丝量是千万级的,我如果想查找其他的列表信息,也要解析千万条他的粉丝列表,或是一个人普通人关注的大V太多的话,他的关注新闻列表的数据也会随着时间增长而增长的非常快,怎么办呢,我采用的分表的办法,将粉丝列表和用户关注新闻列表等会出现大数据的列表拆成了一个单独的表。
但是,后来觉得不妥,因为这样虽然解决了数据增长带来的查询效率低的问题,但是却产生了另外一个问题,就是索引的增加的问题,系统每增加一个用户,都会向5~6个用户表中插入一条记录,但是mongodb的查询效率和对内存的依赖非常严重,如果内存不足以存储索引了,查询效率会降低得非常厉害,插入多个表中会加速把内存耗尽。怎么办呢,我采用动态创建分表的办法,一开始用户注册的时候,只插入基本信息表和存储列表的表,在每次更新列表中的数据的时候,从基本信息表中存储的对应列表中的数目来判断是否需要拆表了,如果需要拆表了,则将对应的列表拆成一个单独的文档保存到对应的集合中,然后将原来的列表数据清空,并且将数据是否拆表的信息保存到redis中。每次查询对应列表数据的时候,需要先访问redis来确认数据保存到了哪里,然后去对应的位置去读取。
考虑到索引太长也消耗内存,我真正跑了一下,int32型索引100万占用 27921040字节 空间, int64型索引100万占用 27921040字节 空间, 16字节字符串索引100万占用 38042928字节 空间,32字节字符串索引占用 56013776空间 。但是保存数据的时候,int型占用的空间可比定长字符串小多了,mongodb的单条记录存在16M的上限,必须得考虑数据大小。int32和int64在保存数据的时候,数据大小没有任何差别,我们最终就用int64型了
原来对于mongodb的理解是有问题的,以为集群就是和mysql一样,将所有数据都复制到其他的备份机器上,只是查询能快一点。学习了hbase后,了解到mongodb集群也是和其一样,将数据分片后保存到不同机器上。这样就不存在单台机器内存的瓶颈,也不存在系统的数据量有上限的问题了,是一种真正的大数据服务器,对比hbase,检索数据要快得多,同时支持的各种查询也丰富得多,本身是一个成熟的c语言开发的产品,不需要各种复杂的安装,也不需要各种复杂的设置,本身支持map-reduce,写js存储过程来实现。设计的时候,只需要考虑索引的命名能让数据分布到不同的机器上,防止出现热机的问题就可以了。
原来考虑采用存储过程加快检索数据的方案也修改了 ,在每个人的个人列表中维护点赞列表,收藏列表,禁止评论列表,站台列表。当用户请求新闻列表的时候,将用户的这些列表一次返回(每个人的数据量不会很大),然后查询redis缓存的新闻(每个新闻缓存30秒,失效就去数据库中查询并保存到redis),组织好回复报文就可以了。这样极大的减少了数据库查询的次数,同时也减少了新闻的查询次数,防止访问量特别大的时候,出现放置新闻的服务器过于繁忙的现象。遵循一个设计原则,按照读的方式写数据,就能最大程度发挥mongodb的优势了。
mongodb的单条记录存在16M的上限,对于数据量比较大的情况,比如用户单人粉丝量达到了千万级,这个是有问题的。真正跑了一下,单条记录存int型,大概在100万条,200万就不行了。对于粉丝表这种可能出现超大规模数据的表,我采用一组记录来保存数据,每一条记录存100万条数据。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值