编辑推荐: |
本文来自于csdn,文章大概分为八部分介绍,最后运用场景叙述。 |
|
1、Collection Sharding是否靠谱
Sharding key的一些烦恼;
单一key可能导致分布不均匀;
使用符合Sharding KEY
复合sharding key也不是万能的;
Count计算性不准确;
Balancer不够智能,时间不确定;
禁用Auto-Sharding功能不可靠(尤其是2.X版本);
线上禁用Auto-Sharding
开启库级Sharding;
固定分片;
手动分片、分表;
完全控制并取得较好结果;
2、Free Schema真的Free吗?如何应对
Free Schema意味着重复的Schema;
每个文档都需要有Schema(重复存储的代价);
Free Schema意味着ALL Schema,需要知道所有schema并且进行查询与解析;
尽量表中Schema都是固定的,将会大大简化程序复杂度;
尽可能减少字段名,数据存储压缩(字段名称都一样、压缩比高、zlib type compression、减少存储空间、减少访问压力);
3、字段名如何进行选取
FreeSchema意味着重复存储,存储空间浪费;
字段名尽量短地存储;
1.6billion(243-183=60GB);
减少字段名将会带来可读性的问题,应用层做字段的映射;
4、_id如何进行生成
collection级doc唯一标示,集合内部唯一;
文档主键,默认为12字节,24位的字符串,_id在服务器端生成;
在客户端生成合适的_id,例如IM用户可以使用unit64_t作为id;
在业务层统一生成(_id生成器,twitter snowflake保证生成唯一性);
5、索引如何设计
原理:内存处理速度比硬盘快100倍,加快索引速度;
索引类型:唯一性索引(索引项的唯一),联合索引(支持前缀查询);
返回某些字段,将这些字段都放在索引中;联合查询,支持前缀查询(前面的节点可以利用索引);返回95%的集合文档,小数据量索引建议使用索引;后台索引,background:true,不允许暂停数据库访问,可以在后台构建索引,仍然占用写锁,但是会释放给业务读写操作;MongoDB对外读写性能会下降;
索引副作用,增、删、改的开销;
索引是否合理,explain+hint命令;
6、空间地理索引是否靠谱
空间地理索引兴起;
使用gps进行查询
地理空间索引不太靠谱(可以通过搜索业务搞定)
7、Collection设计原则
RDBMS与MongoDB的对照
数据库、表/集合、行/文档;
三范式与嵌套;
存储用户及地址;
一对一原则(用户信息表,类RDBMS类型);
一对多原则(在线消息表,1:类RDBMS类型;2:MongoDB嵌套方式(单条16MB限制));
多对多原则(User与Team关系,类RDBMS(Team、User、Relation),MongoDB(User存储teamid(不包含时,可以在Team中建立索引),Team存储userid(不包含时,可在uid上创建索引)));
8、数据量较大时如何进行Sharding
Collection Sharding;
手动Sharding;
混合ID查询(商品表,在不同查询条件时将一些id打入另外一些id中);
场景分析:设计QQ即时通信业务
用户信息表(userinfo)中存储了用户id、用户名字、用户昵称、用户签名、用户信息表生成时间戳信息,用户信息表约有1亿条记录。
在线消息表存储用户之间的聊天消息,包括发送人、接收人、消息时间、消息内容等。每天消息量约200w条,消息需要保存6个月。
群组表存储了用户加入群的关系。一个群可以有很多群成员,一个用户也可以加入很多个群。群的规模约100w个,一个群的最多可以加入100个用户,一个用户最大加入100个群。
首先,对整个业务场景进行分析,从即时通信的要求我们可以看出,主要的业务集中于收发消息,从收发消息的类别又可以分为群消息与个人消息;
之后,在确定基本业务之后对数据进行大概估算,用户信息1亿条,大概需要1亿*1k(每条记录1k),约100GB存储空间;用户消息200w*60*30*1k(每条记录1k),约360GB存储空间;群组表,100w*10k(用户及群组相关信息10k),约10GB存储空间;
接下来,对业务进行分析,从逻辑上来看,用户的信息在访问上应该是相互独立的,所以用户信息的存储保证较为随机的存储即可,同时,又不会出现顺序访问的情况,所以用户信息通过简单的hash进行分片即可;另外,用户的群组信息,与用户一样,在分布及存储上是较为独立的,所以可以访问时可以保持相应的独立性即可;在实时消息方面实时消息其实是一个用户回话的过程,在存储方面需要进行一定的计算,同时会有一定的时效性需要按时间进行排序,所以此时的消息最好是采用复合的片键,并且加入时间;
最后,在数据结构设计方面,用户和群组之间是多对多的关系,所以需要在结构方面包含用户的信息,同时用户也需要包含群组的信息,此时在数据结构上将会有一定量的增加,主要是用户表需要包含群组的id,这方面增加数据量大约不超过5G所以可以忽略。此时数据结构的设计为用户包含群组id、群组包含用户id。消息还是按照之前的消息进行存储,使用接收者、发送者构建联合的sharding
key,同时,对消息进行接收者、发送者、时间构建联合索引(因为在消息访问时一般都会是确定接收者与发送者的),此时群组消息的接收者将是群组,如果用户可以通过查询群组信息查看消息;
|