参考:https://blog.csdn.net/iloveyin/article/details/7105181
豊富なデータ構造は、Redisのデザインは非常に興味深いですなります。リレーショナルデータベース、DEVのDBAのニーズやコミュニケーションの深さとは異なり、DBAが参加する必要がありませんようmemcachedのとは異なり、SQL文の各ラインを確認します。DBAのRedis、おなじみのデータ構造も理解し、シナリオを使用する必要があります。
ここで重要な設計について話すと、リレーショナル・データベースとの比較を行うKVのための共通のデータベースのいくつかの例があり、リレーショナル不備を発見しました。
ユーザーのログインシステム
ユーザのログインシステム情報を記録し、私たちはテーブルを離れた後、ビジネスを簡素化します。
リレーショナルデータベースの設計
MySQLの>のログインから選択*; + --------- + ---------------- + ------------- + -------- ------------- + | USER_ID | 名前| login_times | last_login_time | + --------- + ---------------- + ------------- + -------- ------------- + | 1 | ケン・トンプソン| 5 | 2011-01-01夜12時○○分00秒| | 2 | デニスのリッチー| 1 | 2011-02-01夜12時○○分00秒| | 3 | ジョー・アームストロング| 2 | 2011-03-01夜12時○○分00秒| + --------- + ---------------- + ------------- + -------- ------------- +
user_idはプライマリキーテーブル、名前はlogin_timesは、ユーザーがログインするたびに倍のユーザログの数を表しlast_login_timeは、現在の時刻に更新しながら、login_timesは自動的に、増加し、ユーザー名を表します。
Redisのデザイン
次のようにデータベースにKVリレーショナルデータは、私の方法は次のとおりです。
キーテーブル名:主キーの値:列名
値の列の値
コロン区切り文字を行う一般的には、不文律です。例えば、RedisのシステムのためのPHP-adminに、大腸のセグメント化は、ユーザ次に、デフォルト:1つのユーザー:2及び他のキーがグループ化されます。したがって、上記データとの関係は、Kvは、次のデータレコードに変換されます。
設定したログイン:1:login_times 5 セットのログイン:2:login_times 1 セットのログイン:3:login_times 2 セットのログイン:1:2011年1月1日last_login_time セットのログイン:2:last_login_time 2011年2月1日 に設定ログイン:3:last_login_time 2011 -3-1 セットログイン:1:名「ケン・トンプソン」 セットのログイン:2:名「デニス・リッチー」 設定ログイン:3:名「ジョー・アームストロング」
このような既知の主キーは、getの場合は、あなたが得るか、ユーザーのログインおよび最終ログイン時刻と名前を変更することができます設定します。
平均的なユーザーは自分のユーザー名を知って、あなたはまた、デザインは上記異なるとされ、IDに名前からのマッピングを持っている必要があり、そのIDを認識していません。
1つの「:ケン・トンプソンIDログイン」設定 セット「ログイン:デニス・リッチー:ID」2 セット「ログイン:ジョー・アームストロング:ID」3
(Pythonのバージョン)は以下のようにビジネスロジックユーザーがログオンするたびにあり、rは名前がすでにユーザー名を知られ、Redisのオブジェクトです。
需要はIDのみ、更新またはユーザーの最終ログイン時刻を取得し、ログイン時間、およびリレーショナルデータベースKV何違いはありませんが知られている場合。BTREE PKで、ハッシュによって、結果が良好です。
以下の要件を考慮して、最近でログインしてNのユーザーを探します。開発者は、SQLを取得するには非常に簡単です、見て。
1 |
select * from login order by last_login_time desc limit N |
DBA後、テーブルが比較的大きい場合を考慮に入れた後、理解し、そのlast_login_timeにインデックスを構築する必要があります。それは非常に良い、テーブルN倍に戻り、Nレコードの右端のインデックスleafblockからのアクセスの実装を開始する予定。
2日後、需要が来て、あなたは誰ログインの最大数を知る必要があります。関係の同じタイプをどのように扱いますか?そのシンプルDEV
1 |
select * from login order by login_times desc limit N |
DBAは見えるが、また、login_timeにインデックスを構築します。あなたはその後、少し問題を感じてください、フィールドには、各リードの一等地にテーブルを持っています。
リレーショナル・データベースに格納された柔軟性のないデータは、ヒープテーブルは、行に配置された問題の原因、唯一つのデータ格納方法です。統一されたデータ構造は、あなたが支援するために統計を使用しなければならないことを意味するので、多くの問題が浮上しているあなたはすぐにSQL列にアクセスするためのアクセスパスを変更し、順番にアクセスパスを高めるために、インデックスを使用しなければならないことを意味します。
いいえ、インデックスなし、統計的計画、KVデータベースであるノー実施計画、。
これらのニーズを満たす方にはRedisの?データ需要の最新のN個を求めているために、機能のリストの最後の後に、それは非常に適しています。私たちは、それがユーザーに最新のNログで保存されたが、常に存在するように、ログインのリストを維持することは、彼の長さを制御し、コードの一部上のログインコードの後に追加しました。
1 |
#把当前登录人添加到链表里 |
2 |
ret = r.lpush( "login:last_login_times" , uid) |
3 |
#保持链表只有N位 |
4 |
ret = redis.ltrim( "login:last_login_times" , 0 , N - 1 ) |
このような人々は、最新のログインIDを取得する必要があり、次のコードは、することができ
1 |
last_login_list = r.lrange( "login:last_login_times" , 0 , N - 1 ) |
また、ログインするまで求める人々の数は、需要のこの種は、順位をソートするため、ソートセットは非常に適している、我々のユーザーと統一ログインはでソートセットに格納されています。
zaddログイン:login_times 5 1 zaddログイン:login_times 1 2 zaddログイン:login_times 2 3
ユーザーがログオンするのであれば、追加のソートセットなので、コードを維持します
1 |
#对该用户的登录次数自增1 |
2 |
ret = r.zincrby( "login:login_times" , 1 , uid) |
だから、ほとんどのユーザー数はN番目の順位を取るために、ユーザの逆の順序で、その上でログを取得する方法
1 |
ret = r.zrevrange( "login:login_times" , 0 , N - 1 ) |
図から分かるように、DEVは、2行のコードを追加する必要があり、DBAは、どのような指標を検討する必要があります。
タグシステム
従来のリレーショナルデータベースの設計が少し目立たであれば、インターネットアプリケーションで特に普及してタグ付けします。私たちは、この点で本のルックRedisの利点の例を見つけます。
リレーショナルデータベースの設計
このタグのそれぞれを表す2つのテーブル、本の詳細、タグテーブルには、この本には、複数のタグがあります。
MySQLの>本から*を選択します。 + ------ + ------------------------------- + ---------- ------ + | ID | 名前| 著者| + ------ + ------------------------------- + ---------- ------ + | 1 | Rubyプログラミング言語| マーク・ピルグリム| | 1 | レールのルビー| デビッド・フラナガン| | 1 | プログラミングErlangの| ジョー・アームストロング| + ------ + ------------------------------- + ---------- ------ + MySQLの> *タグから選択します。 + --------- + --------- + | タグ名| book_id | + --------- + --------- + | ルビー| 1 | | ルビー| 2 | | ウェブ| 2 | | アーラン| 3 | + --------- + --------- + このような要求するだけでなく、本のルビーウェブで見てがある場合は、場合リレーショナルデータベースは、どのように対処するのだろうか?
1 |
select b. name , b.author from tag t1, tag t2, book b |
2 |
where t1.tagname = 'web' and t2.tagname = 'ruby' and t1.book_id = t2.book_id and b.id = t1.book_id |
その後、関連する書籍に関連付けられているので、それが必要なルビーではなく、それの書籍ウェブ側面であれば、タグテーブルは二回、SQLは、非常に複雑ですか?
実際には、リレーショナルデータの収集およびこれらの操作には適していません。
Redisのデザイン
最初の本は、データは上記と同じで、保存されていることを確認します。
本を設定:1:名「Rubyプログラミング言語」 に設定しブック:2:名前「ルビーのレール上に」 本を設定します。3:名「プログラミングErlangの」 設定の本を:1:著者「マーク・ピルグリム」 に設定しブック:2:著者」デビッド・フラナガン」 に設定しブック:3:著者『ジョー・アームストロング』
タグコレクションが共通の基盤を求めているのが得意なので、我々は、データを格納するコレクションを使用し、テーブル、およびセット
サッドタグ:ルビー1 SADDタグ:ルビー2 SADDタグ:ウェブ2 SADDタグ:アーラン3
まあ、それはルビーに属し、ウェブブックに属し?
inter_list = redis.sinter( "tag.web"、 "タグ:ルビー")
それは、Rubyに属しているが、本はウェブに属していませんか?
inter_list = redis.sdiff( "tag.ruby"、 "タグ:ウェブ")
コレクションに属しているとルビーは、Webブックに属しますか?
inter_list = redis.sunion( "tag.ruby"、 "タグ:ウェブ")
動作しないためのシンプルな。
上記の2つの例は、いくつかのシーンで見ることができることから、リレーショナルデータベースでは、需要を満たすためにシステムを設計することができるかもしれ、適切ではないが、常に、丸暗記感のようなものを不思議な感じ。
具体的には、この例のログインシステム、頻繁にインデックス事業。複雑なシステムでは、DDL(インデックスを作成する)には、実行計画を変更することが可能です。別の実行計画、ビジネスの複雑な古いシステムを使用して他のSQLにつながる、この問題は、SQL奇妙な、で推定することは非常に困難です。このシステムのDBAの要件は、すべてのSQLを認識している、これは非常に困難です。この問題は、各DBA推定値が遭遇した、オラクルでは特に深刻です。このようなシステムのためのMySQL、DDLと不便(オンラインDDL方法が存在することになりますが)。大きなテーブルをヒット、DBAは、私はあまり行っていないものです低い業務の朝のピーク期間中に起きます。そして、非常に良い治療中のRedisにこの需要は、DBAだけの容量を推定することができます。
将来のOLTPシステムは密接に統合し、リレーショナルKVする必要があります