Redisの分散ロックはそれほど単純ではなく、オンラインのロックのほとんどにはバグがある

Redisの分散ロックはそれほど単純ではなく、オンラインのロックのほとんどにはバグがある

[[434468]]

Redis 分散ロックの話題はよくあるようです。面接中や仕事中など、どこでも見ることができます。 「コードブラザー」はなぜまだそれについて書く必要があるのでしょうか?

なぜなら、インターネット上の記事の 99.99% は分散ロックを実際に明確に説明しておらず、バグも多数あるからです。

今日は「コード兄さん」が皆さんと一緒に分散ロックのGスポットに深く入り込み、体系的に良いコードを書き、スキルをマスターする本当の男になります。

「クライマックス」を迎える前に、「前戯」として以下の質問について考えてみましょう。いくつ答えられますか?

  • 分散ロックはいつ必要になりますか?
  • コードを追加またはロック解除するための特定の位置はありますか?
  • デッドロックを回避する方法
  • 適切なタイムアウト設定は何ですか?
  • 他のスレッドによってロックが解放されるのを防ぐ方法
  • 再入可能ロックを実装するにはどうすればいいですか?
  • マスタースレーブアーキテクチャはどのようなセキュリティ上の問題をもたらしますか?
  • レッドロックとは

分散ロックはなぜ必要なのでしょうか?

マー兄さん、分散ロックがいつ必要になるかを説明する簡単な例を挙げてもらえますか?

精子が射精される瞬間、何十億もの精子が卵子に向かって突進し、幸運にも卵子と結合できる精子はたった 1 つだけです。

たった 1 つの「精子」だけが「卵子」に好まれるようにするために、創造主は、1 つの精子が卵子に入ると卵子の外殻を変え、経路を閉じて残りの精子をブロックします。

数十億の精子は「同時」交通のようなものです。

卵は共有資源のようなものです。

卵子の殻にある特殊なタンパク質が鍵のような働きをして、精子が 1 個だけ入るのを許可します。

複数のノードで構成されるクラスターには、複数の JVM プロセスが存在します。同じ効果を得るには、調整を行う仲介者が必要であり、JVM 内の 1 つのスレッドのみが共有リソースを操作できるようにする必要があります。

分散ロックは、JVM プロセス内の 1 つのスレッド「精子」のみが同時に保護されたリソース「卵子」にアクセスできるように制御するために使用されます。

「すべての命は何十億ものプレイヤーの中のリーダーだ」、そうか。

分散ロックの概要

分散ロックはどのような特性を満たす必要がありますか?

  • 相互排他: 一度にロックを保持できるのは 1 つのクライアントだけです。
  • デッドロックなし: ロックを取得したクライアントがクラッシュした場合でも、いつでもロックを取得できます。
  • フォールト トレランス: Redis ノードの過半数が稼働している限り、クライアントはロックを取得および解放できます。

コード兄弟、SETNX キー値コマンドを使用して「相互排他」機能を実装できます。

このコマンドは、SET if Not eXists の略語に由来しており、キーが存在しない場合はこのキーに値を設定し、それ以外の場合は何もしないことを意味します。

コマンドは次を返します:

  • 1: 設定は成功しました。
  • 0: キーが正常に設定されませんでした。

次のシナリオ:

一日中コードを入力して疲れているので、リラックスして肩と首をマッサージしたいです。

技術者 168 号は最も人気があり、誰もが彼に注文を付けたがるので、同時実行性が高く、分散ロック制御が必要です。

168 人の技術者と同時に予約を取ることができるのは 1 人の「顧客」だけです。

肖彩吉は168人の技術者の募集に合格しました:

  1. > SETNXロック:168 1
  2.  
  3. (整数) 1 # 168人の技術者を正常に取得

謝覇は後から到着したが、彼の申請は却下された。

  1. > SETNX ロック 2
  2.  
  3. (整数) 0 # 顧客謝八格2の取得に失敗しました

現在、お申し込みに成功したお客様は、168名の技術者による「リソース共有」による肩・首のリラクゼーションサービスをご利用いただけます。

楽しみが終わったら、後から来た人が 168 人の技術者のサービスを受けられるように、ロックを時間通りに解除する必要があります。

Xiao Caijiさん、ロックを解除する方法を教えていただけますか?

とても簡単です。DEL を使用してキーを削除するだけです。

  1. > DELロック:168
  2.  
  3. (整数) 1

マー兄さん、「ドラゴン」を見たことがありますか?はい、ドラゴンに仕えられたからです。

シャオ・ツァイジ、物事はそんなに単純じゃないよ。

このソリューションには「デッドロック」を引き起こす問題があり、この問題を引き起こすシナリオは次のとおりです。

マッサージ中に突然オンラインアラームが届いたので、ズボンを上げて会社に駆けつけましたが、ロックを解除するためにDELを間に合うように実行しませんでした(クライアントがビジネスを異常に処理し、ロックを正しく解除できませんでした)。

マッサージ中に心筋梗塞で亡くなり、DEL コマンドを実行できませんでした。

この方法では、ロックは常に使用中となり、他の顧客は技術者のサービスを受ける機会が「決して」なくなります。

デッドロックを回避する方法

コード兄弟、ロックが正常に取得されたときに「タイムアウト」を設定できます

たとえば、マッサージ サービスを 60 分間設定したい場合は、キーをロックするときに 60 分の有効期限を設定できます。

  1. > SETNX lock:168 1 // ロックを取得
  2. (整数) 1
  3. > EXPIRE lock:168 60 // 60秒自動削除
  4. (整数) 1

これにより、時間経過後にロックが自動的に解除され、他のお客様は引き続き 168 人の技術者によるマッサージ サービスを受けることができます。

誰かがこのように書いたらひどいことになるでしょう。

「ロック」と「タイムアウトの設定」は 2 つのコマンドであり、アトミック操作ではありません。

最初の項目のみが実行され、2 番目の項目が実行される機会がない場合、「タイムアウト」設定は失敗し、デッドロックが発生します。

たとえば、次のシナリオでは、2 番目の命令の実行が失敗します。

Redis が異常クラッシュしました。

クライアントが異常クラッシュしました。

ママ兄さん、どうしたらいいですか?ワンストップサービスが求められ、行き詰まりがあってはなりません。

Redis 2.6.12 以降では、キーが存在しない場合に値を設定するセマンティクス、タイムアウト期間を設定するセマンティクス、およびアトミック性を満たすセマンティクスを満たすように SET コマンドのパラメータが拡張されています。

  1. リソース名ランダム値 NX PX 30000を設定する

NX: resource_name が存在しない場合にのみ SET が成功することを示し、これにより 1 つのクライアントのみがロックを取得できることが保証されます。

PX 30000: このロックの自動有効期限が 30 秒であることを示します。

実行時間がロックの有効期限を超えています

ワンストップサービスを安心してご利用いただけますか?

いいえ、他の人のロックを解除する別のシナリオがあります。

  • クライアント 1 はロックを正常に取得し、30 秒のタイムアウトを設定します。
  • クライアント 1 の実行は、何らかの理由 (ネットワークの問題、FullGC の発生など) により非常に遅くなり、30 秒経っても実行が完了しませんでしたが、ロックが期限切れになり、「自動的に解放」されました。
  • クライアント 2 はロックを正常に申請します。
  • クライアント 1 は実行を完了すると、DEL ロック解除命令を実行し、その時点でクライアント 2 のロックが解除されます。

対処すべき重要な問題が 2 つあります。

  • 有効期限を合理的に設定するにはどうすればよいでしょうか?
  • 他のユーザーが保持しているロックが削除されないようにする方法。

ロックタイムアウトを正しく設定する

ロックタイムアウトを計算するにはどうすればいいですか?

今回はランダムに書くことはできません。これは通常、テスト環境での複数のテストと複数ラウンドのストレス テストに基づいており、たとえば、平均実行時間は 200 ミリ秒と計算されます。

すると、ロック タイムアウト期間は平均実行時間の 3 ~ 5 倍に拡大されます。

なぜズームインするのですか?

ロック操作ロジックにネットワーク IO 操作、JVM FullGC などが含まれている場合、オンライン ネットワークが常にスムーズに動作するとは限らず、ネットワーク ジッタのためにバッファ時間を残す必要があるためです。

1時間など、もっと大きな値に設定したほうが安全ではないでしょうか?

これにこだわらないでください。どれくらい大きいのが「大きい」のでしょうか?

設定時間が長すぎると、ダウンタイムの再起動が発生すると、分散ロック サービスのすべてのノードが 1 時間以内に使用できなくなります。

オペレーターが手動でロックを削除しますか?

運用とメンテナンスに本当に負担がかからない限りは。

完璧な解決策はあるのでしょうか?どのように時間を設定しても、適切ではないようです。

ロックを取得したスレッドにデーモン スレッドを開始させて、期限切れになりそうなロックを「延長」させることができます。

ロック時に有効期限が設定され、クライアントは「デーモン スレッド」を開始して、ロックの有効期限を定期的に検出します。

ロックの有効期限が近づいているがビジネス ロジックが実行されていない場合は、ロックが自動的に更新され、有効期限がリセットされます。

意味は通じますが、書けません。

慌てる必要はありません。これらすべてのタスクをカプセル化するライブラリがすでに存在します。それはレディソンと呼ばれています。

Redisson は、Java で実装された Redis SDK クライアントです。分散ロックを使用する場合、ロックの有効期限切れを回避するために「自動更新」ソリューションを採用します。このデーモン スレッドは一般に「ウォッチドッグ」スレッドと呼ばれます。

スペースが限られているため、「Code Byte」をフォローして、Redisson の使用と原理の次の分析を聞くことができます。

他の人のロックを解除しないでください

他の人のロックを解除する鍵は、DEL コマンドを「無意識に実行」することなので、ロックが自分自身によって追加されたかどうかを確認する方法を見つける必要があります。

ベルを結んだ人はそれを解かなければならない

コード兄弟、ロックするときに、ロックするクライアントを表す値として「一意の識別子」を設定します。

ロックを解除するとき、クライアントは自身の「一意の識別子」とロックの「識別子」を比較して、それらが等しいかどうかを確認します。一致した場合は削除されます。それ以外の場合は、ロックを解除する権利はありません。

疑似コードは次のとおりです。

  1. // 値を一意の識別子と比較する
  2. redis.get( "lock:168" ).equals(uuid) の場合{
  3. redis.del( "ロック:168" ); //比較が成功したら削除する
  4. }

これは GET + DEL 命令の組み合わせであり、アトミック性の問題が関係していると考えたことがありますか。

次の状況を再現します。

  • クライアント 1 で比較の最初のステップが成功した後、2 番目のステップが実行される前にロックが期限切れになります。
  • クライアント 2 はロックを正常に取得し、独自の「uuid」をロックに設定します。
  • このとき、クライアント 1 はロックを解除するために 2 番目の手順を実行しますが、これは明らかに間違っています。

私たちは完璧を追求する人間なので、ここでは Lua スクリプトを使用して実装し、判断と削除のプロセスがアトミック操作になるようにしています。

  1. redis.call( "get" ,KEYS[1]) == ARGV[1]の場合 
  2. redis.call( "del" ,KEYS[1])を返す
  3. それ以外 
  4. 0を返す
  5. 終わり 

最後まで最適化すると、ソリューションはより「厳密」になり、対応するモデルは次のように抽象化されます。

SET lock_resource_name $unique_id NX PX $expire_time を通じて、期限切れが近づいているが実行されていないクライアントのロックを延長するデーモン スレッドが開始されます。

クライアントはビジネス ロジックを実行して共有リソースを操作します。

Lua スクリプトを通じてロックを解除します。まず、ロックが自分で追加されたかどうかを確認し、その後 DEL を実行します。

ロック解除コードの場所は重要です

前回の分析に基づくと、すでに「比較的厳密な」分散ロックが存在します。

そこで、「Xie Ba Ge」はプロジェクトに分散ロックを適用するために次のコードを作成しました。疑似コードのロジックは次のとおりです。

  1. パブリックvoid doSomething() {
  2. 試す {
  3. redisLock() を呼び出します。 // ロック
  4. // プロセスビジネス
  5. redisLock のロックを解除します。 // ロックを解除する
  6. } キャッチ (例外 e) {
  7. e.printStackTrace();
  8. }
  9. }

ビジネス ロジックの実行中に例外がスローされると、プログラムはロックを解除する次のステップに進むことができなくなります。

したがって、ロックを解除するコードは finally{} ブロックに配置する必要があります。

ロック位置も問題あり。 redisLock.lock() ロック例外が発生した場合、finally{} コード ブロック命令が実行されてロックが解除されますが、この時点ではロックは正常に適用されません。

したがって、redisLock.lock(); try の外側に配置する必要があります。

まとめると、正しいコードの場所は次のとおりです。

  1. パブリックvoid doSomething() {
  2. // ロック
  3. redisLock() を呼び出します。
  4. 試す {
  5. // プロセスビジネス
  6. ...
  7. } キャッチ (例外 e) {
  8. e.printStackTrace();
  9. ついに
  10. // ロックを解除する
  11. redisLock のロックを解除します。
  12. }
  13. }

再入可能ロックの実装

再入可能ロックを実装するにはどうすればいいですか?再入後のタイムアウトを設定するにはどうすればいいですか?

スレッドがコードの一部を実行し、ロックを正常に取得して実行を続行すると、ロックされたコードに再び遭遇します。再入可能性により、スレッドは実行を継続できますが、再入可能性がない場合は、実行を継続する前にロックが解放されるのを待機し、再度ロックを正常に取得する必要があります。

再入可能性をコードで説明してください:

  1. パブリック同期void a() {
  2. b();
  3. }
  4. パブリック同期void b(){
  5. // 合格
  6. }

スレッド X がメソッド a でロックを取得した後、メソッド b の実行を継続すると仮定します。この時点で再入が不可能な場合、スレッドはロックが解放されるまで待機し、再度ロックを競合する必要があります。

ロックは明らかにスレッド X によって所有されていますが、ロックを取得する前に、スレッド X 自身がロックを解放するのを待つ必要があります。これはとても奇妙に見えます。自分を解放するよ〜

Redis ハッシュ再入可能ロック

Redisson ライブラリは、Redis Hash を使用して再入可能ロックを実装します。今後は、Redisson の使い方や原理について具体的に記事を書く予定です。

スレッドがロックを取得した後、将来ロック メソッドに遭遇すると、ロックの数を直接 1 増やしてからメソッド ロジックを実行します。

ロックメソッドを終了した後、ロック回数が 1 減少します。ロック回数が 0 になると、ロックは完全に解除されます。

再入可能ロックの最大の特徴は、ロックが追加された回数を計算するカウント機能であることがわかります。

したがって、分散環境で再入可能ロックを実装する必要がある場合は、ロックの数もカウントする必要があります。

ロックロジック

これを実装するには、Redis ハッシュ構造を使用できます。キーはロックされた共有リソースを表し、ハッシュ構造のフィールドキーの値にはロックの数が格納されます。

KEYS1 = "lock"、ARGV "1000, uuid" と仮定して、Lua スクリプトを通じてアトミック性を実装します。

  1. ---- 1は真を表す 
  2. ---- 0は偽を意味します 
  3.  
  4. (redis.call( 'exists' , KEYS[1]) == 0)の場合 
  5. redis.call( 'hincrby' , キー[1], ARGV[2], 1);
  6. redis.call( 'pexpire' , KEYS[1], ARGV[1]);
  7. 1 を返します
  8. 終わり;
  9. (redis.call( 'hexists' , KEYS[1], ARGV[2]) == 1)場合 
  10. redis.call( 'hincrby' , キー[1], ARGV[2], 1);
  11. redis.call( 'pexpire' , KEYS[1], ARGV[1]);
  12. 1 を返します
  13. 終わり;
  14. 0を返します

ロック コードは、まず Redis の exists コマンドを使用して、現在のロックが存在するかどうかを判断します。

ロックが存在しない場合は、hincrby を直接使用してキー uuid を持つロック ハッシュ テーブルを作成し、ハッシュ テーブル内のキー uuid を 0 に初期化してから、再度 1 を追加し、最後に有効期限を設定します。

現在のロックが存在する場合は、hexists を使用して、キー uuid が現在のロックに対応するハッシュ テーブルに存在するかどうかを判断します。存在する場合は、hincrby を使用して再度 1 を追加し、最後に有効期限を再度設定します。

最後に、上記の 2 つのロジックが一致しない場合は、直接戻ります。

ロジックをアンロック

  1. -- ハッシュセットの再入可能キーの値が0に等しいかどうかを判定します 
  2. -- 0の場合は、再入可能キーが存在しないことを意味します 
  3. (redis.call( 'hexists' , KEYS[1], ARGV[1]) == 0)場合 
  4. nilを返します
  5. 終わり;
  6. -- 現在の再入可能回数を計算する 
  7. ローカルカウンター = redis.call( 'hincrby' , KEYS[1], ARGV[1], -1);
  8. -- 0以下の場合はロック解除可能 
  9. (カウンタ>0)ならば 
  10. 0を返します
  11. それ以外 
  12. redis.call( 'del' , キー[1]);
  13. 1 を返します
  14. 終わり;
  15. nilを返します

まず、hexists を使用して、Redis ハッシュ テーブルに特定のフィールドが含まれているかどうかを判断します。

ロックに対応するハッシュ テーブルが存在しない場合、またはキー uuid がハッシュ テーブルに存在しない場合は、直接 nil が返されます。

存在する場合、現在のロックはそれによって保持されていることを意味します。まず、hincrby を使用して再入回数を 1 減らし、計算後に再入回数を決定します。 0 以下の場合は、del を使用してロックを削除します。

ロック解除コードの実行方法はロックの場合と似ていますが、ロック解除の実行結果の戻り値の型が Long である点が異なります。ここでロックと同様にブール値が使用されていない理由は、ロック解除の Lua スクリプトでは、3 つの戻り値が次の意味を持つためです。

  • 1はロック解除が成功し、ロックが解除されたことを意味します
  • 0は再入回数が1減少することを意味する
  • nullは他のスレッドがロック解除を試み失敗したことを意味します

マスタースレーブアーキテクチャによって引き起こされる問題

コード兄弟、分散ロックはここでは「完璧」ですよね?分散ロックにこれほど多くのトリックがあるとは思いませんでした。

まだ長い道のりが残っています。これまで分析したシナリオはすべて、「単一の」Redis インスタンスをロックすることで発生する可能性のある問題に関するものであり、Redis のデプロイメント アーキテクチャの詳細は関係していませんでした。

高可用性を確保するために、通常は「Cluster Cluster」または「Sentinel Cluster」モードを使用します。

どちらのモードも「マスタースレーブアーキテクチャデータ同期レプリケーション」に基づいてデータ同期を実装しており、Redis のマスタースレーブレプリケーションはデフォルトで非同期です。

次のシナリオで何が起こるか想像してみましょう。

クライアント 1 がマスター ノードに分散ロックを書き込んだばかりの場合、この命令はまだスレーブ ノードに同期されていません。

このとき、マスター ノードがクラッシュし、スレーブの 1 つが新しいマスターとして選出されます。この時点では、新しいマスターにはクライアント 1 によって書き込まれたロックがないため、ロックは失われます。

この時点で、クライアント 2 スレッドがロックの取得に成功します。

確率は極めて低いですが、このリスクの存在を認識しなければなりません。

Redisの作者はRedlockと呼ばれるソリューションを提案した。

分散ロックの標準を統一するために、Redis の作者は Redlock を作成しました。これは、分散ロックを実装するための公式の Redis ガイドと見なされています (https://redis.io/topics/distlock)。しかし、このレッドロックは海外の分散専門家からも批判されている。

なぜなら、完璧ではなく、「穴」があるからです。

レッドロックとは

これは赤い鍵ですか?

インスタントラーメンを食べ過ぎると、Redlock はマスタースレーブアーキテクチャにおけるロック損失を解決するために提案されたアルゴリズムです。

Redlock のソリューションは、次の 2 つの前提に基づいています。

  • スレーブやセンチネルインスタンスを展開する必要はなく、マスターのみを展開すればよい
  • ただし、複数のマスター データベースを展開する必要があり、同時にクラッシュしないようにするには少なくとも 5 つのインスタンスを展開することが公式の推奨です。

つまり、Redlock を使用する場合は、少なくとも 5 つの Redis インスタンスをデプロイする必要があり、それらはすべてマスター データベースである必要があります。それらの間には関連性はなく、すべて独立したインスタンスです。

クライアントがロックを取得するには、次の 5 つの手順があります。

  • クライアントは現在の時刻 T1 (ミリ秒レベル) を取得します。
  • 同じキーと値の順序を使用して、N 個の Redis インスタンスからロックを取得しようとします。
    • 各リクエストにはタイムアウト (ミリ秒単位) が設定されています。このタイムアウトはロックの有効期間よりもはるかに短くする必要があります。これにより、次のインスタンスにリクエストをすばやく送信できるようになります。
    • たとえば、ロックの自動解除時間が 10 秒の場合、リクエストのタイムアウトを 5 ~ 50 ミリ秒以内に設定することができ、クライアントが長時間ブロックされることを防ぐことができます。
  • クライアントは現在の時刻 T2 を取得し、ステップ 1 から T1 を減算して、ロックの取得にかかる時間を計算します (T3 = T2 - T1)。ロックは、クライアントがほとんどのインスタンス (N/2 + 1) でロックの取得に成功し、ロックの取得に使用された合計時間 T3 がロックの有効時間よりも短い場合にのみ成功したと見なされます。そうでない場合、ロックは失敗します。
  • ステップ 3 でロックが正常に取得されると、リソースを共有するためのビジネス ロジック操作が実行されます。キーの実際の有効時間は、有効時間からロックを取得するために使用された時間を引いた値 (手順 3 で計算された結果) に等しくなります。
  • 何らかの理由でロックの取得に失敗した場合 (少なくとも N/2+1 個の Redis インスタンスでロックが取得されていないか、ロックの取得時間が有効時間を超えている場合)、クライアントはすべての Redis インスタンスのロックを解除する必要があります (一部の Redis インスタンスが正常にロックされていない場合でも)。

複数のインスタンスをデプロイしてロックするのはなぜですか?

本質は高可用性とフォールト トレランスです。一部のインスタンスがダウンした場合でも、ほとんどのインスタンスは正常にロックされ、分散ロック サービス全体が引き続き利用できます。

3 番目のステップで累積ロック時間を計算する必要があるのはなぜですか?

複数のノードがロックされるため、時間がかかる場合があり、ネットワークでパケット損失やタイムアウトなどが発生する可能性があります。

ほとんどのノードがロックを正常に取得できたとしても、ロックの取得にかかる合計時間がロックの有効期間を超えると、ロックは無意味になります。

一部のノードがロックに失敗した場合でも、ロックを解除するためにすべてのノードを操作する必要があるのはなぜですか?

これは、クライアントが Redis インスタンスを正常にロックしたが、応答の読み取りに失敗し、ロックが失敗したとクライアントが判断する可能性があるためです。

ロックを安全にクリアするには、ロックを解除する要求を各ノードに送信する必要があります。

Redlock はそんなに完璧なのか? Redis マスタースレーブアーキテクチャノードの異常なダウンタイムによって引き起こされるロック損失の問題を解決しますか?

物事はそんなに単純ではありません。 Redis の作者がこのソリューションを提案した後、業界の著名な分散システムの専門家から疑問が投げかけられました。

二人はまるで神々が戦うかのように、一つの問題に対して多くの結論を出すのに十分な証拠をもって、何度も議論を交わしました...

スペースの制約により、次回は、Redssion の分散ロックのカプセル化と Redlock の実装に関する両者の議論の分析についてお話しします。

次に何が起こるかは、次のエピソードをお待ちください...

要約する

終わったら、画面を閉じて、自分が何をしているのか、なぜそれをしているのか、どんな問題を解決しようとしているのかを考えながら、もう一度各ステップを頭の中で確認することをお勧めします。

一緒に、Redis 分散ロックのさまざまなトリックを最初から最後まで確認しました。実際、これらの点の多くは、分散ロックに何を使用しても存在する問題です。大切なのは思考のプロセスです。

システム設計に関しては、誰もが異なる出発点を持っています。完璧な建築、普遍的な建築というものは存在しませんが、完璧さと普遍性の間で良いバランスをとった建築は良い建築です。

Redlock に関する議論は主に以下の点に焦点を当てています。

  • Redlock は効率が悪すぎて重すぎます。効率を向上させる必要があるシナリオでは、分散ロックが使用され、時折のロック失敗が許可されます。この場合、シンプルで効率的な単一の Redis ノード ロック ソリューションで十分です。
  • 正確性に対する要件が高いシナリオでは、時間に依存し、十分に強力なアルゴリズムではありません。 Redlock は正確性を維持しませんでした。

<<:  企業がハイブリッド クラウドを採用するメリットは何でしょうか?

>>:  ドイツテレコムが GitOps を使用してエッジ インフラストラクチャを管理する方法

推薦する

NodeServ - $3.99/512m メモリ/150g ハードディスク/1T トラフィック/G ポート/フロリダ

フロリダのホスティングサービスは安いらしいと言われていますが?クリスシックなどの商品もとても安く販売...

マイクロソフトとオラクルの提携:蜜月は甘いが、破局には注意

世の中の物事は、長い統一期間を経て、やがて分離し、長い分離期間を経て、やがて統一される。巨大企業の間...

Baidu 製品の外部リンクの損益分析

多くのウェブマスターは、Baidu の製品の重みが非常に高いことを知っています。Baidu を使用し...

Qihoo 360、独立系検索アプリ「360 Search」を正式リリース

網易科技ニュース、6月3日、360社は本日、独立したモバイル検索アプリ「360 Search」を正式...

Spring Cloud はマイクロサービス アーキテクチャを構築します: 分散サービス追跡 (サンプリング収集)

分散システムでのリクエスト追跡は、Trace ID と Span ID を通じて実現され、記録された...

WordPress タグを正しく使用していますか?

WordPress を使用して Web サイトを構築している友人は、タグに非常に精通しています。ラベ...

なぜ Kafka を諦めて Pulsar を選んだのでしょうか?

最近、私は Pulsar と Kafka の比較を調べています。ちょっと検索してみると、これら 2 ...

AIと機械学習がSaaS業界にどのような変化をもたらすか

GlobalDots の CTO である Yair Green 氏が、人工知能と機械学習がサービスと...

最適化の不正行為はすべて不倫のようなもの

最適化の不正行為はすべて不倫のようなもの今日では、インターネットについて少しでも知っている人なら誰で...

ウェブサイトのPR価値を効果的に高める3つの方法

PR値、つまりPageRankは、Webページのレベル技術です。これは Google の創設者である...

5Gとエッジクラウドが出会うとき、それが5Gが世界を変える根本的な理由です

2019年6月6日、非常に縁起の良い日に、工業情報化部は4つの主要通信事業者に5G商用ライセンスを発...

クラウドコンピューティングの収益は2028年までに6,290億ドルに達する

従来のシステムからクラウドベースのソリューションに部分的または完全に移行しようとする企業がますます増...

パーフェクトダイアリーは618イベントで失敗しました

数カ月にわたるマイナス成長の後、美容・化粧品業界の企業は618を今年上半期の最後の命綱とみなしている...

成功するEDMメールコピーを作成するための「5つのステップ」

月収10万元の起業の夢を実現するミニプログラム起業支援プラン読者数とクリック率を多く獲得できる魅力的...

恵州 SEO ブログ ウェブサイト SEO 最適化計画

以下は、Huizhou SEO Blog のために Ye Jianhui が書いたウェブサイト SE...