实例说明MongoDB存储的行情数据如何选择合适的Shard Key

概述

当利用MongoDB的shard cluster技术做数据库扩展时,一个至关重要的点是要选择一个合适的shard key(片键),它是用来决定将数据在分片服务器上分配的策略。一个适用的shard key应该满足以下几个条件:

  1. 数据均分
    所谓数据均分,就是要保证需要扩展的那部分数据能够尽可能平均分配到数据分片上,以达到空间上的扩展目的。
  2. 负载均分
    负载均分是把应用访问的分片数据的负载平均分配到数据分片集群上,应用对数据的访问要划分读写分析。
  3. 方便扩展
    一般情况下,数据库的扩展都不是一次完成的的,以后可能还需要对数据进一步分片,因此这次的设计方案,要尽可能为后续的扩展留下余地,而不是每一次都要推倒重来。

MongoDB的片键分类

MongoDB支持两种类型的shard key:

  1. Hashed,数据库根据指定的字段值,算出一个哈希值,然后根据这个哈希值把数据写入相应的服务器中。它的好处是数据会分布的比较均匀,但是它只能把一个字段指定为shard key,另外对于范围的操作,它更多是一个广播的操作,没有精确地路由。
  2. Ranged。按照指定字段的值的范围进行划分,支持复合shard key。这个就要求对字段值的范围有比较深入的了解,对未来也有一个相对清晰的把握。相对哈希,这种方式就可以有比较精确的路由。但是它也可能会带来数据分布不均匀,负载不能完全均衡。

举例

下面以实例说明一下,如何选择合适的shard key。假设我们要分布的是分钟级别的K显示,数据样例如下:

{
code:'600000',
time: '2016-05-04 14:34:00',
period: 1, //分钟线级别, 表示1分钟级别K线
date: '2016-05-04'
},
{
code:'600000',
time: '2016-05-04 14:35:00',
period: 5, //分钟线级别,表示5分钟级别K线
date: '2016-05-04'
},

为了操作方便,把各个分钟级别的数据都存放在了一起,如果拆表,会对业务造成很大伤害,改动较多。因此考虑对该表做sharding。

那么我们该如何选择shard key呢?

在回答这个问题之前,我们首先要看下最常用的操作有哪些。

首先是写入操作,基本上一次性,之后很少会进行变更。
其次就是查询操作,我们看下面两个典型的操作:

# 查询某只股票在某个日期的某个分钟级别的数据
db.min_k_data.find({code:'000001', period:5, date:'2016-09-01'})
# 查询某只股票在某个时间前或者后某个分钟级别的特定数量的数据
db.min_k_data.find({code:'000001', period:1, 'time':{'$lte': '2016-07-01 09:45:00'}}).sort({'time':-1}).limit(20)

通过上面两个查询不难看出两个关键字段是code和period,同时要提高查询效率,我们需要使用精确路由,因此我们选用Ranged类型的shard key。
那么范围应该如何划分呢?对于code,我们可以按照前两位或者前三位划分,它的问题是数据分布不均衡,因为每种类型的股票个数不一样;对于period,我们可以根据数量来划分,简单计算一下就知道一只股票一天的1分钟线是240根(不包含集合竞价)、60分钟线4根、5分钟线24根,那么根据这个数据量我们把一分钟线把到一台服务器上,其他分钟线放在其他服务器上。
按照之前的分析,数据均分和负载均分的问题基本解决了,接下来就要看扩展了。我们从数据规模来看,我只需要再按照股票代码做划分即可。

猜你喜欢

转载自blog.csdn.net/mydeman/article/details/80275390
key
今日推荐