『Amebaなう』リアルタイム検索機能に Apache Solr と MessagePack を採用
ミニブログサービス「Amebaなう」に検索機能を追加 Apache Solrのカスタマイズにより検索パフォーマンスが大幅向上
検索機能は、当社の研究開発組織「インキュベーションラボラトリー」が開発し、Apache Solrをベースに、検索インデックス作成アルゴリズムの効率化や、データを高速かつ効率的に保存できる技術仕様「MessagePack」と各種圧縮アルゴリズムを組み合わせる等の対応を行いました。
あわせて読みたい:LuceneのインデックスにStoreするデータをMessagePackで圧縮してみた - 社内NEET宣言
MessagePack と各種圧縮アルゴリズムを組み合わせることで、インデックスサイズを80%程度に圧縮することが可能になったようです。
MessagePack を使うと、配列やMapなどの構造を、非常にコンパクトに保存することができます。例えば、[1,2,3]という3つの整数からなる配列はたったの4バイト、{"a":null}という連想配列はたったの4バイトで保存することが可能です。もしこれが JSON だと、それぞれ7バイトと10バイトも必要になります。
さらに Deflate などで圧縮すれば、非常に高い圧縮率が得られるという寸法です。先のjust_do_neetさんのブログによれば、作成速度も検索速度も、それほど速度劣化は起こっていないようです。
他に MessagePack を使ってデータサイズを圧縮している事例には、Data::Modelがあります。
KVSに保存するデータのスキーマをあらかじめ定義しておき、キー名を整数に変換するなどの変換を施すことで、空間効率を飛躍的に高めています:
例えば、上記のコードを使った場合に以下のようなデータ構造だった場合に
…
{
file_id => 'dankogai',
media_type => 1,
client_type => 5,
is_broken => undef,
},
Key を任意の値に変換してから直列化をかけます。
Data::Model 標準のシリアライザの MessagePack では、数値をとても効率よく直列化してくれるので、 media_type だとかいう長ったらしい key name を 2 とか言う数値に変換してしまいます。
2 とかという小さい値だと直列化後も1バイトしか容量食わなくて嬉しいんです!実際、上のほうで書いてるデータ例だと以下の用になります。
{
2 => 1,
3 => 5,
},
これを MessagePack でシリアライズすると、元のデータは5バイトという驚異的なサイズとなって kumofs の value に格納されます。
memcachedにデータを保存する場合でも、このように空間効率を高めることで、キャッシュ可能なデータ量を増やすことができます:Data::Model::Driver::Memcachedで超効率データ保存
このように MessagePack は、速いだけでなく「小さい」という利点があります。MessagePack は JSON と型システムが同じ*1なので、JSON を使うところを単に MessagePack を使うようにするだけで、キャッシュのヒット率を向上させられたり、トラフィック量やCPU使用率を減らせるかもしれません。
それでは、MessagePack を使ったプログラミングをお楽しみください^^;