読者です 読者をやめる 読者になる 読者になる

Aerospike Deep Driveに参加してきた

f:id:komeiy:20150329230850p:plain

参加メモです。6/24(水) 19:00〜22:00。

個人的にはpartition mapの話が勉強になりました。Aerospikeは構築するだけであれば非常に簡単でドキュメントにインフラ周りの仕組みがなかなか記載されていないので、裏側を知れたのは非常に嬉しいです。

Aerospikeと他KVSとの違い、適用分野等

  • 導入事例
  • 導入時に検討した他のKVS
  • 導入して気づいたこと

IDSyncサービス

  • 自社IDと他社IDのマッピング
  • 属性データの加工

  • ID Syncサービスとは

  • マッピングテーブルを生成
  • アンケートで特定の解答をした人に広告配信
  • 自社サイトに訪問した人にメール広告を配信

  • システム

  • ELB + Nginx + uWSGI
  • バックエンドにaerospike
  • 平均応答速度は1ms
  • ピーク時で1000req/s程度
  • 主キーが自社ID、他社IDを主キーとしたものを保持

  • 様々な属性情報を、異なるソースから取得

  • 保持している属性情報を人が理解できるように
  • 基盤にaerospike
  • cookie IDを元に様々なデータを保持
  • 要素ごとに個別のsetを保持(useragent, IP, company, ...etc)

他のKVSとの比較

  • DynamoDB

    • 費用面がネック
    • キャパシティを超えたリクエストがロスト(キューイングなし)
    • 10万read/sで130万/月、10万write/sで650万/月
  • Redis(ElasticCache)

    • 容量制限あり(最大240GB)
    • 到達した場合に代替手段がないのでスケールしない
  • Cloud Bigtable

    • GCPにしないとレイテンシが発生する
    • 応答速度がAerospike比で約5〜10倍(らしい)

導入して気づいたこと

  • clientが高機能
  • レコードがどのノードに配置されているか主キーのハッシュ値で把握している
  • コネクション取得時にテーブルを取得する
  • マッピングテーブルはノードの削除・追加時に更新される

  • Clientもパワーが必要

  • 高多重度でリクエストを行う必要あり
  • 1リクエスト1msで3.6億レコードを取り出す

  • メモリの使用量が大きい

  • SSDのみの利用でも意外とメモリを利用する

    • インデックスがメモリ展開される
    • 1レコードにつき64バイト
  • Nmaespaceが分割しにくい

  • SSDを使用する場合、ブロックデバイス単位でしかNamespaceを分けることができない

  • Queryの制約

  • SQLライクな記述でレコードを参照するこも可能だが・・・
  • 指定したサーバで処理が走る(クライアント側ではない)
  • 並列実行ができない
  • バックアップのQuery扱い
  • mysqldumpの様なコマンドがある。平文。データ量と時間に注意

  • その他 雑感

  • インメモリだと特に速い
  • 設定項目がほぼないので構築が楽
  • ドキュメントにない機能がライブラリにある(ソースコードみよう!)

  • まとめ

  • Aerospikeの速度が必要なケースってあまり多くなさそう
  • マッチしそうなケース
    • データ量の見積もりが難しい場合
    • 時間あたりのリクエスト数が膨大な場合
  • リソースの見積もりが難しい

新機能を使ってみて

クライアントライブラリ

  • 新機能の実装優先度

    1. jaba / c / node
    2. go /python ruby /php
  • scalaもcommunity Labsにあるよ

  • 大体の使い方を知るにはサンプルプログラムを読む/実行するのがよい

  • vagrantで入れてAMCでアクセスしてみよう(ここまで30分)
  • GitHubで公開されているclientライブラリにもexamplesが同梱
  • 充実度はJavaが一番

  • 基本の保存と検索

  • client.put / client.get
  • サポートしている型はシンプル
  • list / mapはgetlist/getmapはないget objectでダウンキャスト
  • ver3からlist / set / map / stackをサポート。LDTS
  • LargeListは昇順でソートされている

  • executeはサーバに配置されたluaプログラムを実行するためのメソッド

  • luaスクリプトを自分で書くことができUDFと呼ぶ

  • limitation

    • ソートは昇順
    • write block size設定によって1要素の容量が制限される
    • 1Mbなら200kb / 128kbなら30kb
    • add_all(), udate_all()は1GBまで
    • XDRはLDT対象外
    • aqlで内容を確認できない

その他

  • LDTのデータは1つのサーバノードで保存されクラスタ内に分散しない
  • TTLはRecord単位
  • LDTの堀はluaを使うのでCPUを消費する
  • LDT * luaはサンプル少なくて苦労する

  • OSS

    • あまり使われてない機能・環境を使う場合はEnterprise Editionを推奨
  • Aerosparkあるよ

Node.jsクライアントを半年間、使ってみて

− 運用のし易さで選定 - クラスタ構成、パフォーマンス、サーバ台数削減 - メモリリーク問題 - heapdump / tcp connection? /clinen closeで治るか? -> 治らず - binの文字長 - 感想:サーバサイドの運用が楽、クライアントは・・・

マイグレーション

partition map

  • クラスタ内のデータを4096個に分割したもの
  • partitionはレコードを均等に入れる4096個のバケツ
  • キーのハッシュの先頭12bitを使用
  • パーティションをサーバに均等に分割
  • 各サーバのMACとpartitionIDを使って各ノードの順番を決める。これをパーティションマップ。
  • partition mapは左からreplication factorに従い選択される
  • clientからのアクセスは1ホップ
  • オートシャーディング、オートバランシング

ノード追加

  1. ノード追加
  2. Gossipプロトコルで伝達。全ノードのノードリストができてからMap作成に移る
  3. patition mapが更新される。計算上既存ノードの順序は変わらず新規ノードが入ってくる(マイグレーション処理が少ない)
  4. 新規ノードにデータがあるノードからコピーされる
  5. 新規ノードがslaveであればClientはMasterへ、新規ノードがMasterならclientはコピーが終るまではslaveへ。2台同時追加でmaster/slave両方がコピー中の場合はmapの右へ
  6. slaveで受けているときはコピーを続けつつmasterのjournalへ書き込む
  7. 最後にjournalをflashする

  8. 通常時はmaster/slaveに書き込んでACK, 非同期でSSDFlash。reptication factor 3だと3台書き込めてからレスポンス。

  9. migration走って容量減った? -> partition mapでslave以下に降格したデータが消える。reprication factorは3 !?
  10. 2TBで3台->4台にしたときに18時間

シェアして頂けると嬉しいです。
参考になったという方がいれば是非お願いしますm(_ _ )m
モチベーション維持の観点で非常に励みになります。

このエントリーをはてなブックマークに追加

NOSQLの基礎知識

NOSQLの基礎知識

データベース徹底攻略 (WEB+DB PRESS plus)

データベース徹底攻略 (WEB+DB PRESS plus)

広告を非表示にする