【Redisメモリ最適化】メモリ節約:InstagramのRedis実践


Instagramは、ネット写真アプリの元祖ともいえるアプリであり、現在最も人気のある写真アプリの一つでもあり、Instagramの写真数は3億に達していますが、Instagramでは、各写真の著者が誰なのかを知る必要があります.以下は、InstagramチームがRedisを使用してこの問題を解決し、メモリの最適化を行う方法です.
まず、この画像IDによるユーザUIDのリバースチェックのアプリケーションには、以下の点が必要である.
クエリの速度はで十分です.
データをすべてメモリに入れるには、EC 2のhigh-memoryモデル1台で保存できる(17 GBか34 GB、68 GBはもったいない)が望ましい.
Instagramの既存のアーキテクチャ(InstagramはRedisに対して一定の使用経験があり、例えばこの応用)サーバの再起動後にを予熱する必要がないように、永続化をサポートします.
Instagramの開発者はまずデータベースストレージのスキームを否定し、KISS原則(Keep It Simple and Stupid)を維持した.このアプリケーションはデータベースのupdate機能、トランザクション機能、関連クエリーなどの牛X機能をまったく使用できないため、これらの使用できない機能のためにデータベースを維持する必要はない.
そこで彼らはRedisを選びました.Redisは永続化をサポートするメモリデータベースで、すべてのデータがメモリに格納されています(VMを忘れましょう).最も簡単な実現はRedisのString構造を使ってkey-valueストレージを作ればいいのです.このように:
SET media:1155315 939
GET media:1155315
> 939

このうち1155315はピクチャID、939はユーザIDであり、各ピクチャIDをkeyとし、ユーザuidはvalueとしてkey-valueペアとして格納する.その後、彼らはテストを行い、データを上記の方法で保存し、1000000データは70 MBのメモリを使用し、300000枚の写真は21 GBのメモリを使用します.予算の17 GBに比べて、やはり超過しています.
(NoSQLFan:実はここで最適化点を見ることができます.key値の前の同じメディアを削除して、数字だけを保存することができます.これによりkeyの長さが減少し、key値のメモリへのオーバーヘッドが減少します..実験を経て、メモリの占有量は50 MBに下がり、総メモリの占有量は15 GBで、需要を満たしているが、Instagramの後の改善は必要だ)
そこでInstagramの開発者はRedisの開発者の一人Pieter Noordhuisに最適化案を尋ね,Hash構造を用いたと回答した.具体的には、データをセグメント化し、各セグメントに1つのHash構造を使用して格納します.Hash構造は、単一のHash要素が一定数未満の場合に圧縮格納されるため、メモリを大幅に節約できます.この点は上のString構造には存在しない.この一定数は、プロファイル内のhash-zipmap-max-entriesパラメータによって制御されます.開発者らの実験を経て、hash-zipmap-max-entriesを1000に設定した場合、性能は比較的良く、1000を超えるとHSETコマンドがCPU消費を非常に大きくする.
そこで彼らはシナリオを変更し、データを次の構造に保存しました.
HSET "mediabucket:1155" "1155315" "939"
HGET "mediabucket:1155" "1155315"
> "939"

7ビットのピクチャIDの上位4ビットをHash構造のkey値とすることで,各Hash内部に3ビットのkey,すなわち1000個しか含まれていないことが保証される.
もう一度実験をした結果、1000000 keyごとに16 MBのメモリしか消費されなかった.総メモリ使用量も5 GBに削減され、アプリケーションのニーズを満たしています.
(NoSQLFan:同様に、ここではさらに最適化することができます.まず、Hash構造のkey値を純数字にすることで、key長が12バイト減少し、次にHash構造のsubkey値を3桁にすることで、以下に示すように4バイトのオーバーヘッドが減少しました.実験により、メモリ占有量が10 MBに低下し、総メモリ占有量が3 GBになります)
HSET "1155" "315" "939"
HGET "1155" "315"
> "939"

最適化には限りがない.ストレージ製品を使用するときも、メモリを大切にしてください.