マルチスレッドミドルウェアは、暴行やRedisのをぶら下げ!

KeyDBを紹介する今日、KeyDBプロジェクトは、Redisのブランチからフォーク出ています。我々はすべて知っているようにRedisのKVメモリ記憶システムは、シングルスレッドであり、そして場合KeyDB 100%互換性のRedisのRedisのAPIは、マルチスレッドに変換されます。
また、あなたは最後の時間は、公式バージョンは今年の終わりにリリースされるマルチスレッドのRedis、我々が表示されますということです教えてください。

スレッドモデル

KeyDBはメインスレッドとワーカースレッドの中に、元のメインスレッド分割をRedisのだろう。各ワーカースレッドは、データや分析プロトコルを読んで、要求を受け入れて、ポートを監視する責任IOスレッドです。図示のように:

WEBP

画像

KeyDBは、複数のスレッドが同じポートでリッスンするようにバインドすることができ、SO_REUSEPORT特性を使用しました。タイ・コアCPUを行うために、各ワーカースレッドは、CPUを指定も使用SO_INCOMING_CPU特性データを受信されたデータを読み出します。解決プロトコル後に各スレッドは、メモリグローバルロックからデータにアクセスする複数のスレッドを制御するために、メモリ内の運用データを移動します。メインスレッドは、実際にワーカースレッド、仕事内容など、ワーカースレッドですが、また、メインスレッドの前に完了することができるコンテンツのみの作業が含まれています。ワーカースレッド配列の添字にメインスレッド0です。実装serverCron、を含むでメインスレッドの主な作品:

  • 統計的治療

  • クライアント・リンクマネージャ

  • DBデータ、サイズを変更し、reshard

  • 処理AOF

  • スタンバイ同期レプリケーション

  • クラスタモードの下での作業

リンク・マネージャー

すべてのリンクの管理がでRedisのスレッドで行われます。KeyDBの設計では、各ワーカースレッドは、リンクのセット、メンテナンス中にこのスレッドでリンクのリストに挿入されたすべてのリンクを担当しています。リンクに仕事を生成し、それは同じスレッドで破壊されなければなりません。各リンクは、フィールドを追加します

int型IEL; / *私たちは* /リンクを示すために使用されて登録されているイベントループインデックスはにどのスレッドを引き継ぐために属します。3つの主要な管理データ構造は、リンクを行う維持KeyDB:

  • clients_pending_write:クライアントのリンクにデータを送信するために、同期キューを維持し、排他的なリストをスレッド

  • clients_pending_asyncwrite:线程专属的链表,维护异步给客户链接发送数据的队列

  • clients_to_close:全局链表,维护需要异步关闭的客户链接

分成同步和异步两个队列,是因为redis有些联动api,比如pub/sub,pub之后需要给sub的客户端发送消息,pub执行的线程和sub的客户端所在线程不是同一个线程,为了处理这种情况,KeyDB将需要给非本线程的客户端发送数据维护在异步队列中。同步发送的逻辑比较简单,都是在本线程中完成,以下图来说明如何同步给客户端发送数据:

WEBP

image

如上文所提到的,一个链接的创建、接收数据、发送数据、释放链接都必须在同个线程执行。异步发送涉及到两个线程之间的交互。KeyDB通过管道在两个线程中传递消息:

int fdCmdWrite; //写管道int fdCmdRead; //读管道

本地线程需要异步发送数据时,先检查client是否属于本地线程,非本地线程获取到client专属的线程ID,之后给专属的线程管到发送AE_ASYNC_OP::CreateFileEvent的操作,要求添加写socket事件。专属线程在处理管道消息时将对应的请求添加到写事件中,如图所示:

WEBP

image

redis有些关闭客户端的请求并非完全是在链接所在的线程执行关闭,所以在这里维护了一个全局的异步关闭链表。

WEBP

image

锁机制

KeyDB实现了一套类似spinlock的锁机制,称之为fastlock。fastlock的主要数据结构有:

struct ticket{ uint16_t m_active; //解锁+1 uint16_t m_avail; //加锁+1};struct fastlock{ volatile struct ticket m_ticket; volatile int m_pidOwner; //当前解锁的线程id volatile int m_depth; //当前线程重复加锁的次数};

アトミック操作__atomic_load_2を使用して、__ atomic_fetch_add、__ atomic_compare_exchange = m_avail m_activeを比較することによってロックを取得するか否かを判定する。高速ロックは、ロックを取得する2つの方法を提供します。

  • try_lock:直接のリターンを得るために失敗

  • ロック:忙しいなど、CPU等を引き渡すためのイニシアチブ後の1024 * 1024はsched_yieldの使用など、それぞれ忙しい時間は、CPUが実行を待っているタスクの最後に移動しました。

KeyDBでは、このような多忙な出来事を避けるために、一緒にtry_lockやイベントになります。各クライアントは、最初にロックしようとするクライアントデータを読み込む前に、排他ロックを持っており、それが失敗した場合にデータが読み込まれていないため、その後、終了し、そのイベントがepoll_waitハンドルのイベントは、再び次のサイクルで処理することができます。

WEBP

画像

アクティブレプリカ

ライブ実装KeyDB機構、各レプリカは、各レプリカとの間の非書き込み読み出し専用データ同期するように配置されてもよいです。主な機能は次のとおりです。

  • 各レプリカは、環状の複製を削除するために使用される、UUIDフラグを有しています

  • 新しく追加されたrreplayのAPI、rreplayコマンドにパッケージ化コマンド増分、地元のUUIDをもたらします

  • 同じキーと番号のローカルバージョンがある場合は、キー、値タイムスタンプバージョン番号は、競合のチェックとして、データから同期したタイムスタンプ、新しい書き込み障害よりも大きくなります。左20、44に現在のタイムスタンプを加えた道の増分を使用すると、バージョン番号のキーのタイムスタンプを取得します。



おすすめ

転載: blog.51cto.com/14528283/2444773