2015/12/28

Production Cluster Architecture in MongoDB: Replica Sets + Sharding

為了建立一個完整的高可用性的 MongoDB 資料庫,我們必須要整合使用 Replica Sets 跟 Sharding。


  1. Shard Server: 2 個以上的 shard server,以 replica sets 建立 shard server,確保每一個節點都有備份,自動容錯及復原的能力
  2. Config Server: 設定 3 個 config server,一定要剛好 3個
  3. Route Server: 1 個以上的 query routers,通常可以在每一個 application server 都配置一個 mongos instance


MongoDB in Trend


在這篇文章中 趨勢科技導入MongoDB 追蹤管理全球10萬個行動裝置,MongoDB 的架構圖其實跟官方提出的架構概念是一致的。



如果是以 Application 的角度來看 MongoDB 的架構,概念上是接近以下這個架構圖。



3 physical servers


因為三個 config server 的基本要求,因此我們最低的硬體要求,是需要三台實體的 server。另外考量到整個 cluster 環境的完整的備援。
MongoDB的Replica Sets+Sharding架構 這篇文章提出了一個架構。



Production Note


MongoDB 官方在 Production Notes 提供了一些在正式環境應該要注意的事項。


  • Storage Engine
    有兩種 MMAPv1 及 WiredTiger,預設是使用 MMAPv1。 mongod 在啟動時,會檢查 dbPath 裡面既有的資料,是不是指定了不同的 storage engine。

  • OS
    Mac OS X, Linux, Windows Server 2012, Windows Server 2008 R2 64bit, Windows 7 (64 bit), Windows Vista, and Solaris 都可以用,但 Production 環境建議要使用 64bits OS。

  • Concurrency
    MMAPv1 提供 collection-level locking,所有的 collections 都有一個唯一的 read-write lock,允許多個 clients 同時在不同的 collections 裡面修改文件。


    WiredTiger 在一個 collection 裡面 readers 與 writers 同時存取文件的機制,clients 可在其他 write operations 進行過程中,還能讀取文件,多個 threads 可以同時修改在某一個 collection中不同的文件。

  • Data Consistency


    1. Journaling: MongoDB 採取了 write ahead logging to an on-disk journal 的機制,可在 mongod crash 時,還能處理尚未儲存到 data files 的資料。最好要保持 journaling 的功能開啟的狀態。

    2. Write Concern: 當 MongoDB 處理 write operation 時,可設定 guarantee 的強度,當以 weak write concern 執行 insert,update,delete 時,這些 operation 會快速完成,但風險是當發生錯誤時,就有可能會發生資料錯誤的狀況。

  • Networking


    1. Use Trusted Networking Environments
      MongoDB 預設沒有啟用 authorization 機制,MongoDB 是以 Role-Based Access Control 的方式,處理 client 端授權的問題。

    2. Disable HTTP Interfaces
      MongoDB 有提供透過 HTTP 查詢 server status 的機制,正式環境要把這個功能關掉。

    3. Manage Connection Pool Sizes
      避免在單一個 mongod 或 mongos,使用太多 connection resources,確保 client 只使用了合理的 connection pool sizes,通常設定為 concurrent db requests 總量的 110%~115% 就可以了。connPoolStats 指令可查詢 open connections 的資訊。

  • HW Considerations


    1. MongoDB 核心是使用 litte-endian 硬體,主要是 x86/x86_64 的 CPU,而 client 可以使用 big 或 little endian 系統

    2. 配置足夠的 RAM 及 CPU
      MMAPv1 不需要太多 CPU cores,增加 RAM 可減少 MongoDB 產生 page faults 的頻率。


      WiredTiger 需要很多 CPU cores 支援,active threads(concurrent operations) 跟 CPU 總數有關係。


      storage.wiredTiger.engineConfig.cacheSizeGB 會限制 cache 的上限。


      可透過 mongostat 指令查看 ar|aw 欄位,得知 active reads/writes 的數量。

    3. 使用 Solid State Disk (SSD)

    4. NUMA (Non-Uniform Access Memory) HW
      NUMA 是一種記憶體的實作方式,CPU 存取 local memory 的速度會比存取 shard memory 還快。MongoDB 在 NUMA 環境中使用,會遇到很多問題,可能會越來越慢。

  • Disk and Storage System


    • Swap


    1. 為系統設定 swap,當記憶體不夠用時,就不會發生OOM(Out of Memoty) killer 把 mongod 刪除的問題
    2. 因為 MMAPv1 是以 map files to memory 的方式,確保 OS 不會將 MongoDB 資料存在 swap space 裡面。


    • Raid


    1. 大多數的 MongoDB deployments 應該使用 Raid-10
    2. Raid-5 與 Raid-6 的效能表現不是很好
    3. 不要用 Raid-0,Raid-0 的 write operation 表現好,但 read operation 就比較差,在 Amazon EBS volumes 上會發生這個問題。


    • Remote File System


    1. MMAPv1 不建議使用 NFS(Network File System),data 與 journal 都可能會有效能問題,建議將 jornal journal 放在 local or iscsi 硬碟會比較快。

    2. 如果真的要使用 NFS,建議在 /etc/fstab 檔案中加上 bg, nolock, noatime 這些設定。


    • Separate Components onto Different Storage Devices


    1. 為了改善效能,可考慮將 data, journal, log 分開放在不同的 stoage devices上。
    2. WiredTiger 可將 indexes 放在不同的 storage device 上。
  • Architecture


    • Replica Sets

    • Shared Clusters

  • Compression
    WiredTiger 可使用 snappy 或 zlib 壓縮 data,snappy 壓縮比例較低,但效能耗費較少,zlib 壓縮比例高,但效能耗費也高。


    WiredTiger 預設使用 snappy,可修改設定值 storage.wiredTiger.collectionConfig.blockCompressor

  • Platform Specific Considerations
    MongoDB 使用 GNU C Library(glibc),建議使用 glibc-2.12-1.2.el6 以上的版本

  • Kernel and File System
    建議使用 kernel 2.6.36 以上的 kernel


    MMAPv1 中,MongoDB 會 preallocate db files,產生比較大的 data files,建議使用 XFS 與 EXT4 file system。


    WiredTiger 強烈建議要使用 XFS,避免效能問題。


    XFS file system 至少使用 linux kernal 2.6.25 以上的版本。
    EXT4 file system 至少使用 linux kernal 2.6.23 以上的版本。


    以下是一些 Linux Distribution建議的 files sytem 及 kernel 版本


Linux Distribution Filesystem Kernel Version
CentOS 5.5 ext4, xfs 2.6.18-194.el5
CentOS 5.6 ext4, xfs 2.6.18-3.0.el5
CentOS 5.8 ext4, xfs 2.6.18-308.8.2.el5
CentOS 6.1 ext4, xfs 2.6.32-131.0.15.el6.x86_64
RHEL 5.6 ext4 2.6.18-3.0
RHEL 6.0 xfs 2.6.32-71
Ubuntu 10.04.4 LTS ext4, xfs 2.6.32-38-server
Amazon Linux AMI release 2012.03 ext4 3.2.12-3.2.4.amzn1.x86_64

  • fsync() on Directories
    MongoDB 需要 file system 支援 fsync on directories 的功能,HGFS 與 Virtual Box 並不支援這個功能。

  • Recommended Configuration


    1. 在儲存 data files 的硬碟,要關掉 atime
    2. 設定 file descriptor limit (-n) 以及 user process limit(ulimit) 超過 20000
    3. disable Transparent Huge Pages,MongoDB 在 4096 bytes virtual memory pages 的效能較好


      echo never > /sys/kernel/mm/redhat_transparent_hugepage/defrag
      echo never > /sys/kernel/mm/redhat_transparent_hugepage/enabled
      echo never > /sys/kernel/mm/transparent_hugepage/enabled
      echo never > /sys/kernel/mm/transparent_hugepage/defrag
    4. disable NUMA in BIOS

    5. 設定 SELinux


    在 MMAPv1
    1. 檢查針對 block device 的 readahead 設定。一般設定為 32(16kb) 就可以了


    注意:所有 MongoDB 系統都要用 NTP 同步時間。

  • Linux System
    mongod 及 mongos 在他們自己的 socket 裡面限制 TCP keep alive setting 最大值為 300 seconds。


    查詢設定


    sysctl net.ipv4.tcp_keepalive_time
    cat /proc/sys/net/ipv4/tcp_keepalive_time

    修改設定


    sudo sysctl -w net.ipv4.tcp_keepalive_time=<value>
    echo <value> | sudo tee /proc/sys/net/ipv4/tcp_keepalive_time

    永久修改設定


    vi /etc/sysctl.conf
    net.ipv4.tcp_keepalive_time = <value>

noPadding


mysql遷移到mongodb shared架構的過程中踩到的一個坑
MongoDB 2.x 在儲存資料時,會自動預留一些空間,所以原本在 mysql 259GB 的資料,移到 MongoDB 變成了 1197.416 GB。這個問題在 MongDB 3.x 採用了 WiredTiger 以後,已經有改善了。


就算是使用預設的 MMAPv1 Storage Engine 在 3.0 以後已經可以在建立 collection 時,就加上 noPadding 選項設定,避免 MongoDB 用掉太多預留空間。