序文
元の公開アカウント:bigsai
Webの場合、ユーザー数と訪問数の増加は、プロジェクトのテクノロジーとアーキテクチャの変化と進歩をある程度促進します。次の条件のいくつかがあるかもしれません:
- ページの同時実行性と訪問数は多くありません。MySQL
足以支撑
独自の論理的なビジネス開発です。実際、キャッシュは必要ありません。静的ページは最大でキャッシュできます。 - ページの同時実行性が大幅に向上し、データベースにいくらかプレッシャーがかかり、一部のデータの更新頻度
反复被查询
やクエリ速度が低下してい较慢
ます。次に、キャッシングテクノロジーを使用して最適化することを検討できます。ヒット率の高いオブジェクトはRedisのキー値形式で保存されるため、データがヒットした場合でも、非効率的なデータベースを通過する必要はありません。効率的なredisからデータを見つけます。 - もちろん、他の問題が発生する可能性もあります。静的ページキャッシング、CDNアクセラレーション、さらには負荷分散によって、システムの同時実行性を高めることもできます。ここでは紹介はありません。
キャッシングのアイデアはいたるところにあります
アルゴリズムの問題からキャッシングの意味を理解し始めます。
質問1:
- 数値n(n <20)を入力し、質問し
n!
ます。
分析1:
- アルゴリズムのみを考慮し、範囲外の数値の問題は考慮しないでください。
もちろん、私たちは知っていn!=n * (n-1) * (n-2) * ... * 1= n * (n-1)!
ます;
それなら再帰関数で問題を解決することができます。
static long jiecheng(int n)
{
if(n==1||n==0)return 1;
else {
return n*jiecheng(n-1);
}
}
このように、各入力要求はn
何度も実行する必要があります。
質問2:
- データのtグループ(おそらく数百または数千)を入力します
xi!
。各グループに1つのxi(xi <20)、検索;
分析2:
递归
、input tグループのデータを使用する場合、入力がxiになるたびに、毎回実行される回数は次のようになり
ます。入力Xiまたはtが大きすぎるたびに、多くの負担が発生します。時間の複雑さはO(n2)です- だからあなたはあなたの考えを変えることができますか?はい、はい
打表
。集計は、ACMアルゴリズムでよく使用され、入力と出力の複数のセット、グラフ理論の検索結果、およびパスの保存の問題を解決するためによく使用されます。だから、これの要因を見つけてください。配列を申請し、必要な数を前から後ろまでの数に応じて配列に格納し、後で取得するときに配列値を直接出力するだけです。アイデアは明確です。
import java.util.Scanner;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int t=sc.nextInt();
long jiecheng[]=new long[21];
jiecheng[0]=1;
for(int i=1;i<21;i++)
{
jiecheng[i]=jiecheng[i-1]*i;
}
for(int i=0;i<t;i++) {
int x=sc.nextInt();
System.out.println(jiecheng[x]);
}
}
}
- 時間の複雑さはO(n)のみです。ここでの考え方は
缓存
、考え方と似ています。まず、データをjiecheng [21]配列に格納します。計算を実行します。後でアクセスを続ける場合は、静的配列値を要求するのと同じです。毎回O(1回の操作)です。
キャッシングのアプリケーションシナリオ
キャッシングは、サービス容量を増やすための同時実行性の高いシナリオに適しています。主に、from —>などの低速メディアから高速メディアへの保存经常被访问的数据
またはクエリ。ほとんどのリレーショナルデータベースはであり、その効率とリソースは限られていますが、redisはメモリベースであり、その読み取りと書き込みの速度は大きく異なります。同時実行性の高いリレーショナルデータベースのパフォーマンスがボトルネックに達した場合、頻繁にアクセスするデータをRedisに戦略的に配置して、システムのスループットと同時実行性を向上させることができます。成本较高
硬盘
内存
基于硬盘读写
一般的なWebサイトとシナリオの場合、リレーショナルデータベースは主に次の2つの場所で低速になる可能性があります。
- 読み取りと書き込みのIOパフォーマンスが低い
- データの一部は、より多くの量で計算される場合があります
したがって、キャッシングを使用すると、ディスクIO時間の数と、リレーショナルデータベースでの計算の数を減らすことができます。速い読み取り速度は、2つの側面にも反映されています。
- メモリに基づいて、より高速な読み取りと書き込み
- ハッシュアルゴリズムを使用して、計算せずに結果を直接見つけます
したがって、まともな、いくらかサイトのサイズの場合、それはキャッシュされnecessary
、Redisは間違いなく最良の選択の1つです。
注意を払う必要があります
キャッシュの不適切な使用は多くの問題を引き起こす可能性があります。したがって、いくつかの詳細を慎重に検討して設計する必要があります。もちろん、最もまれなデータの一貫性は、以下で個別に分析されます。
キャッシュを使用するかどうか
プロジェクトは、キャッシュのためにキャッシュを使用することはできません。キャッシュは、必ずしもすべてのシナリオに適しているわけではありません。データの一貫性が非常に高い場合、データが頻繁に変更され、クエリが少ない場合、または同時実行性がまったくない場合、クエリは必ずしも必要ではありません。キャッシングはリソースを浪費し、プロジェクトを肥大化させて維持するのを困難にする可能性があり、redisキャッシングを使用すると、考慮する必要のあるデータ整合性の問題が発生する可能性があります。
合理的なキャッシュ設計
キャッシュを設計するとき、マルチテーブルクエリが発生する可能性が非常に高くなります。マルチテーブルクエリキャッシュのキーと値のペアが発生した場合は、合理的に検討する必要があります。それらを分割または結合する必要がありますか?もちろん、組み合わせの種類は多いが頻繁に表示されない場合は、直接キャッシュすることができます。具体的な設計はプロジェクトのビジネスニーズに基づいている必要があり、絶対的な基準はありません。
有効期限戦略の選択
- キャッシュには比較的高温で一般的に使用されるデータが含まれており、Redisリソースも制限されています。有効期限が切れた後にキャッシュを削除するには、適切な戦略を選択する必要があります。
操作系统
コンピューターキャッシュの実装には、ファーストインファーストアウトアルゴリズム(FIFO)、最近使用されていないアルゴリズム(LRU)、最良の除去アルゴリズム(OPT)、最小ページアクセスアルゴリズム(LFR)、およびその他のディスクスケジューリングアルゴリズムがあることを学び、知っています。Redisキャッシュを設計するときにも学ぶことができます。時間に基づくFIFOが最適な実装です。そして、Redisは全局key
有効期限戦略をサポートしています。 - また、システムの状況に応じて有効期限を適切に設定する必要があります。ハードウェアの方が優れている場合は少し長くすることもできますが、有効期限が長すぎたり短すぎたりすると、キャッシュヒット率が高くならない場合があります。多くの人気のないデータがRedisに保存され、リリースされません。
データの一貫性の問題★
実際、上記のデータ整合性の問題。一貫性の要件が非常に高い場合、キャッシュはお勧めしません。キャッシュされたデータを少し整理してみましょう。
データの整合性の問題は、Redisキャッシュで頻繁に発生します。キャッシュの場合、いくつかの状況を以下に示します。
読んだ
read
:Redisから読み取ります。Redisにない場合は、MySQLからRedisキャッシュを更新します。
次のフローチャートは一般的なシーンを示していますが、論争はありません。
書き込み1:最初にデータベースを更新してから、キャッシュを更新します(通常の低同時実行性)
データベース情報を更新してから、Redisキャッシュを更新します。これは一般的な方法です。キャッシュはデータベースに基づいており、データベースから取得されます。
ただし、いくつかの問題が発生する可能性があります。たとえば、更新キャッシュに障害が発生した場合(ダウンタイムやその他の条件)、データベースとRedisデータの整合性が失われます。DBに新しいデータを作成し、古いデータをキャッシュします。
書き込み2:最初にキャッシュを削除してから、データベースに書き込みます(低同時実行性の最適化)
解決した問題
この状況は、書き込み1でRedisへの書き込みを妨げる問題を効果的に回避できます。更新するキャッシュを削除します。理想は、Redisへの次のアクセスをMySQLに対して空にして、キャッシュに最新の値を取得することです。ただし、この状況は同時実行性の低いシナリオに限定されており、同時実行性の高いシナリオには適用されません。
問題
でも2を書いてください看似写入Redis异常的问题
。これはより良い解決策のようですが、同時実行性の高いソリューションにはまだ問題があります。我々は議論に1を書き込み、更新ライブラリーが成功した場合、キャッシュの更新の失敗は、ダーティデータを引き起こすこと。私たちの理想は、下一个线程
アクセスがキャッシュの更新に適しているように、キャッシュを削除することです。問題は、この次のスレッドが早すぎて偶然に来た場合はどうなるでしょうか。
マルチスレッドのため、誰が最初に行くのか、誰が速いのか、誰が遅いのかがわかりません。上の図に示すように、RedisキャッシュデータとMySQLの間に不整合があります。もちろん、あなたは鍵をかけることができます上锁
。ただし、ロックは非常に重いため、同時実行性に大きな影響を与えるため、ロックせずに使用しないでください。上記の状況では、高い同時実行性の下で、キャッシュは古いデータになり、DBは新しいデータになります。また、キャッシュの有効期限が切れていない場合、この問題は常に存在します。
書き込み3:二重削除戦略を遅らせる
これは遅延二重削除戦略であり、書き込み2でMySQLを更新するプロセスで読み取りスレッドのエントリによって引き起こされるRedisキャッシュとMySQLデータ間の不整合を軽減できます。方法は、キャッシュを削除する->キャッシュを更新する->遅延(数百ミリ秒)(非同期)して、キャッシュを再度削除することです。キャッシュの更新中に書き込み2の問題が発生した場合でも。データの不整合を引き起こしますが、遅延(具体的には、ビジネスによっては、通常は数百ミリ秒)を再度削除すると、不整合をすばやく解決できます。
ただし、書き込み専用ソリューションには、実際には2番目の削除エラー、高い同時実行性でのMySQLアクセスへのプレッシャーなどの抜け穴があります。もちろん、MQなどのメッセージキューを使用して非同期で解決することもできます。実際、実際の解決策を絶対確実に考慮することは困難であるため、設計のいくつかの欠陥のために多くのビッグウィッグがスプレーされる可能性があります。Caicaiの作者として、ここであなたの醜さを見せたくありません。誰もがあなたの貢献を歓迎します。
書き込み4:キャッシュを直接操作し、定期的にSQLに書き込みます(高い同時実行性に適しています)
一堆并发(写)
以前のスキームがメッセージキュー非同期通信を使用していても、何かがスローされた場合、ユーザーに快適なエクスペリエンスを提供することは困難です。また、SQLの大規模な操作も、システムにかなりの圧力をかけます。したがって、別の解決策は、キャッシュを直接操作し、キャッシュをSQLに定期的に書き込むことです。非リレーショナルデータベースであるRedisはメモリ操作に基づいているため、KVは従来のリレーショナルデータベースよりもはるかに高速です。
上記は、同時実行性の高い状況でのビジネス設計に適しています。現時点では、Redisデータが主力であり、MySQLデータは補助的です。定期的に挿入してください(データバックアップライブラリのように)。もちろん、この種の高い同時実行性は、ビジネスペア读
、写
注文などによって要件が異なることが多く、高い同時実行性とマルチスレッドによって引き起こされる不確実性と不整合を使用消息队列
して锁
完了する必要がある場合があります。安定性、ビジネスの信頼性を向上させます。
つまり、データの整合性の設計には高并发
、ますます適切な数据一致性要求高
ソリューションが必要考虑和顾及
になります越复杂、越多
。上記は、Redisデータの一貫性の問題に対する著者の学習と自己発散(ナンセンス)学習でもあります。不合理な説明がある場合、または私を訂正してください!
最後に、気分が良ければ、3つのリンクをクリックしてください。元の公開アカウント「bigsai」に注目してください。ここでは、知識や乾物を学ぶだけでなく、多くの高度な情報を準備できます。「bigsai」パスワードに返信するだけです。受け取る!