データベースキャッシュの最終的な整合性に関する4つのオプション
背景
キャッシュはソフトウェア開発において非常に有用な概念であり、データベースのキャッシュはプロジェクトにおいて必然的なシナリオである。キャッシュの一貫性の保証については、インタビューでも繰り返し質問されるので、ここでは、さまざまな要件に適した一貫性ソリューションを選択するための概要を説明します。
キャッシュとは何ですか?
ストレージの速度に差がある。キャッシュとは、低速のストレージの結果を、高速のストレージに一時的に保存する技術のことです。
図のようにピラミッドのさらに上のストレージは、下のストレージのキャッシュとして使用することができます。
データベースのキャッシュシナリオに焦点を当てた今回の議論では、ケーススタディとしてmysqlのキャッシュとしてredisを使用します。
キャッシュが必要な理由
mysqlなどのストレージは通常ACIDのフル機能をサポートしており、信頼性や永続性などの関係で一般的に性能は高くありません。同時実行性の高いクエリはmysqlに負担をかけ、データベースシステムを不安定にさせる可能性があります。また、レイテンシも発生しがちです。
ローカリティの原則によれば、リクエストの80%はホットデータの20%に該当し、キャッシュの層を追加することは、リードモアライトレスのシナリオにおいてシステムのスループットと堅牢性を向上させるのに非常に有用です。
問題点
保存されたデータは時間の経過とともに変化し、キャッシュ内のデータに一貫性がなくなることがある。時間とともに許容される不整合の正確な量は、ビジネスごとに分析する必要がありますが、通常ビジネスでは、最終的に一貫性があることが必要です。
mysqlのキャッシュとしてのredis
通常の開発モデルでは、mysqlをストレージとして使用し、redisをmysqlの高速化と保護のためのキャッシュとして使用します。しかし、mysqlのデータが更新された後、redisはどのように同期を維持するのでしょうか。
強い一貫性のある同期はコストがかかりすぎるし、強い一貫性を求めるなら、キャッシュを使う必要はなく、mysqlを使えばいいのです。普通に考えれば、最終的な一貫性が大事なんだけどね。
解決策
解決策1
鍵の有効期限により、mysqlが更新されてもredisは更新されない。
この方法は実装が簡単ですが、不整合が非常に長くなる可能性があります。読み取り要求が非常に頻繁で、有効期限が長い場合、長期のダーティデータが大量に作成される可能性があります。
長所
開発コストが低く、導入が容易であること。
管理コストが低く、問題が発生する確率が低くなる。
デメリット
有効期限に完全に依存する、短すぎて頻繁にキャッシュが無効になりやすい、長すぎて更新遅延が長くなりやすい(一貫性がない)。
オプション2
オプション1を拡張し、キーの有効期限を引き下げ、mysqlの更新時にredisも同時に更新する。
長所
オプション1と比較して、更新のレイテンシーが少ない。
デメリット
は、mysql の更新が成功し、redis の更新が失敗した場合、オプション 1 にデグレードされます。
高連続性シナリオでは、ビジネスサーバーはmysqlとredisに同時に接続する必要があります。この場合、接続リソースが2倍消費され、接続数が多すぎると問題が発生する傾向があります。
シナリオ3
メッセージキューを追加して、redisの更新操作をkafkaに渡し、メッセージキューで信頼性を保証し、redisを非同期に更新する消費サービスを構築して、オプション2の同期書き込みredisを最適化します。
長所
メッセージキューは1つのハンドルで送信でき、多くのメッセージキュークライアントもローカルキャッシュをサポートしており、オプション2の接続数が多すぎるという問題を効果的に解決しています。
メッセージキューを使用した論理的デカップリング。
メッセージキューは本質的に信頼性が高く、手動コミットなどにより少なくとも一度はredisに消費させることが可能です。
デメリット
まだタイミングの問題は解決していません。複数のビジネスサーバーが同じデータ行に対する2つの別々のリクエストを処理する場合、例えばa = 1; a = 5のように、最初のものがmysqlで先に実行され、kafkaへの順序は2番目のものだとすると、データの一貫性が失われることになるのです。
メッセージキューの導入に加え、メッセージを消費するためのサービスを追加しなければならないため、コストがかかり、二重消費の危険性もあります。
シナリオ4
binlogを購読してredisを更新する。構築したコンシューマーサービスをmysqlのスレーブとして、binlogを購読し、更新を解析し、redisに更新します。
長所
mysqlへの負担が少なく、レイテンシーが低い。
ビジネスとの完全なデカップリング。
タイムリーさの問題を解決する。
デメリット
同期サービスを別途構築し、ビンログ同期機構を導入する方がコストがかかる。
概要
ソリューションの選択
まず、製品に求められるレイテンシーを確認します。要件が極端に高く、データが変化する可能性がある場合は、キャッシュを使用しないでください。
通常、選択肢1で十分です。私は4、5チームをコンサルティングしたことがありますが、基本的にオプション1を使います。キャッシュソリューションは、通常、リードモアライトレスシナリオに使用でき、一方でビジネスはレイテンシーをある程度包括しているからです。オプション1には開発コストがかからず、実際により実用的です。
更新時の即時性を高めたいのであれば、リトライ保証などをする必要はありませんが、オプション2にしましょう。
オプション3、オプション4は、プッシュモードとプルモードで1つずつ、よりレイテンシーを要求されるビジネス向けで、オプション4の方が信頼性が高いです。どちらもメッセージを処理するためのロジックを行う労力を惜しまないので、一歩進んでオプション4を利用するのがよいでしょう。
結論
一般的には、選択肢1でよいでしょう。面接のシナリオであれば、面接官が簡単なものから複雑なものまで段階的に質問してくるので、それを少しずつ推理して楽しんでいく。
データベースキャッシュの一貫性に関する4つの選択肢の記事は以上です。データベースキャッシュの一貫性に関する詳細は、スクリプトハウスの過去記事を検索するか、以下の関連記事を引き続き閲覧してください。
関連
-
テーブル変数によるSQL実行効率低下の記録
-
DataGrip データエクスポート/インポート実装例
-
Linuxシステム用Navicatアクティベーションチュートリアル
-
MySQLとRedisがデータの一貫性を確保する方法について説明します。
-
ナビカット15のインストールチュートリアルを超詳しく解説(一番信頼できるのはこれ)
-
QtによるOpenGaussデータベースへの接続の詳細チュートリアル
-
SQLインジェクションの実装と防止事例を解説
-
どのようなデータベースのサブベースのサブテーブルは、どのような状況でサブベースのサブテーブルを使用する必要があります。
-
SQLインジェクションの例とその解決方法
-
Navicat Premium 12でOracleに接続する際にoracle library is not loadedと表示される問題の解決
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
SQL修正構文文の概要
-
Navicat 15アクティベーションチュートリアル
-
ツリー構造データベースのテーブルのスキーマ設計のための2つのオプション
-
Navicat for SQLite インストールチュートリアル(インストールキット付き
-
SQL実行エンジンを自作する方法
-
SQLyogダウンロード、インストール超詳細チュートリアル(プロテスト永久保存版)
-
データベース管理ツール「Navicat」と「DBeaver」を一挙に読む
-
タイプインジェクションとコミットインジェクションのSQLインジェクションチュートリアル
-
データベースのSQLインジェクションの原理と簡単な紹介
-
ユニークSQLの原理と応用を解説