ホームページ  >  記事  >  データベース  >  Redisキャッシュの問題を解決する方法

Redisキャッシュの問題を解決する方法

PHPz
PHPz転載
2023-06-03 17:56:411161ブラウズ

レベルDBはここにあります!

#これは、Google がオープンソース化した NOSQL ストレージ エンジン ライブラリであり、最新の分散ストレージの分野では不可欠なツールです。これに基づいて、Facebook は別の NOSQL ストレージ エンジン ライブラリである RocksDB を開発しました。これは、LevelDB の高度な技術アーキテクチャに従いながら、LevelDB の欠点の一部も解決しています。 RocksDB は、LevelDB よりも強力な水素爆弾にたとえることができます。最新のオープンソース データベースの多くは、基盤となるストレージ エンジンとして RocksDB を使用しており、TiDB はその有名な例の 1 つです。

しかし、なぜ RocksDB ではなく LevelDB について話す必要があるのでしょうか?その理由は、LevelDB の技術アーキテクチャがよりシンプルで明確で理解しやすいためです。まずLevelDBをしっかり理解してからRocksDBを見てみると非常に分かりやすいと思いますが、RocksDBはLevelDBをベースに一連の最適化を行ったものに過ぎません。私たちが RocksDB の問題を解決するとき、TiDB の原子力宇宙船はすでにそれほど遠くないところで私たちを迎えてくれています。

Redis キャッシュの何が問題なのでしょうか?

Redis をキャッシュとして使用する場合、通常は完全なコールド データとホット データを記録する永続的なデータベースが残ります。 Redis と永続層データベース間のデータの一貫性は、アプリケーション自体によって制御されます。キャッシュにデータがない場合、アプリケーションは永続化レイヤーからデータをロードしてキャッシュに入れる必要があります。データ更新が発生した場合、キャッシュを無効にする必要があります。

<code class="hljs javascript">function getUser(String userId) User {<br>  User user = redis.get(userId);<br>  if user == null {<br>    user = db.get(userId);<br>    if user != null {<br>      redis.set(userId, user);<br>    }<br>  }<br>  return user;<br>}<br><br>function updateUser(String userId, User user) {<br>  db.update(userId, user);<br>  redis.expire(userId);<br>}<br></code>


この分野での開発経験を持つ友人は、このようなコードの作成が非常に面倒であることを知っているため、キャッシュを含むすべてのビジネス コードには、ロジックのこの部分を追加する必要があります。

厳密に言えば、キャッシュの整合性の問題も慎重に考慮する必要があります。たとえば、updateUser メソッドでは、データベースは更新を正しく実行しますが、ネットワーク ジッターやその他の理由により、キャッシュされた Redis の無効化に失敗します。するとキャッシュ内のデータは 期限切れのデータとなります。読者は、キャッシュの設定と永続ストレージの更新の順序が逆であっても、依然として別の問題が発生する可能性があると考えることができます。

複数のプロセスによる同時実行性の高い状況も、キャッシュの不整合を引き起こす可能性があります。たとえば、プロセスが特定の userId で getUser() メソッドを呼び出した場合、そのメソッドはキャッシュにないため、からロードする必要があります。データベース。結果がロードされたばかりで、キャッシュをセットアップしようとしています。この時点で、メモリ fullgc コードはしばらく一時停止され、この時点で別のプロセスが updateUser メソッドを呼び出してデータベースを更新し、キャッシュを無効にします (実際、キャッシュデータにはキャッシュがありません)。そして、前プロセスは最終的に fullgc を終了し、キャッシュの設定を開始しますが、このとき、期限切れのデータがキャッシュされます。

LevelDB はどのように解決されますか?

LevelDB は、Redis キャッシュと永続化レイヤーを 1 つに結合し、キャッシュと永続化レイヤーを一度に処理できるようにします。 LevelDB を使用すると、コードは次のように簡素化できます

<code class="hljs javascript">function getUser(String userId) User {<br>  return leveldb.get(userId);<br>}<br><br>function updateUser(String userId, User user) {<br>  leveldb.set(userId, user);<br>}<br></code>


キャッシュの整合性の問題を心配する必要はなくなりました。LevelDB のデータ更新は成功または失敗のいずれかであり、中間のシュレディンガー状態はありません。 LevelDB はメモリ キャッシュと永続層のディスク ファイルを内部的に統合しているため、ユーザーはデータの整合性の詳細に注意を払う必要はありません。

LevelDB とは一体何ですか?

これは非リレーショナル ストレージ エンジンであり、Redis の概念とは異なると前に説明しました。 Redis は完全なデータベースですが、LevelDB は単なるエンジンです。データベースを高級スポーツカーにたとえると、ストレージ エンジンはそのエンジン、つまり中核であり心臓部です。このエンジンを使用すると、一連のアクセサリや装飾をパッケージ化してデータベースにすることができます。ただし、アクセサリーや装飾品を軽視しないでください。究極を達成するのは非常に困難であり、LevelDB をシンプルで使いやすいデータベースにパッケージ化するには、非常に多くの精巧なアクセサリーを追加する必要があります。 LevelDB と RocksDB は何年も前から存在していますが、これらをベースにして完全な運用レベルのデータベースを構築できる人はほとんどいません。

LevelDB は、メモリ内のキーと値のデータベースとして見ることができます。これは、コード内でデータを読み書きできる基本的な Get/Set API を提供します。サイズが無制限の高度な HashMap と考えることもでき、ディスクに収まる限り無制限の Key/Value データを詰め込むことができます。

これはインメモリ データベースとしてのみみなされるため、そこに保存されているデータをプロセスやマシン間で共有することはできません。分散分野において、LevelDBはどのように才能を発揮できるのでしょうか?

これを実現するには、ネットワーク API を LevelDB メモリ内データベースの上にラップする必要があります。複数のプロセスが異なるマシン上に存在し、リソースにアクセスしたい場合、それらはすべてネットワーク API インターフェイスを介して均一にアクセスする必要があります。これにより、単純なデータベースが形成されます。 Redis プロトコルを適用してネットワーク層をカプセル化すると、Redis クライアントを使用してデータベースの読み取りと書き込みを行うことができます。

データベースの高可用性を考慮する場合、上記のスタンドアロンデータベースにマスタースレーブレプリケーション機能を追加することで、マスタースレーブ構成の分散NOSQLデータベースに変換できます。マスター/スレーブ データベースの前に転送プロキシの層 (LVS、F5 などのロード バランサー) を追加すると、マスター/スレーブ データベースのリアルタイムの切り替えを実現できます。

必要なデータ容量が大きすぎて、1 台のマシンのハードディスクでは対応できない場合は、データベース データ全体を複数のマシンに分散するデータ シャーディング メカニズムが必要になります。各マシンは一部の読み取りのみを担当します。データの書き込み作業。データ シャーディングには多くのオプションがあります。Codis などの転送プロキシを介してシャーディングすることも、Redis-Cluster などのクライアント転送メカニズムを使用してシャーディングすることもできます。また、TiDB の Raft 分散一貫性アルゴリズムを使用してグループ化および管理することもできます。最もシンプルで理解しやすいのは、Codis のフォワード プロキシ シャーディングです。

データ量が増加し続け、新しいノードが必要になった場合、古いノード上のデータを部分的に新しいノードに移行する必要があります。新しい高度なアクセサリを使用して、データ バランシングと移行を管理します - データ バランシング。 デバイス。

以上がRedisキャッシュの問題を解決する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。