1. 程式人生 > >例項說明MongoDB儲存的行情資料如何選擇合適的Shard Key

例項說明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根,那麼根據這個資料量我們把一分鐘線把到一臺伺服器上,其他分鐘線放在其他伺服器上。
按照之前的分析,資料均分和負載均分的問題基本解決了,接下來就要看擴充套件了。我們從資料規模來看,我只需要再按照股票程式碼做劃分即可。