Nutsdb はマージ提案のソートを自動化します

バックグラウンド

実は、このアイデアは昨年提案されましたが、まだ実現していません。コミュニティの発展と成長に伴い、常に少数の人が一部の機能を実行できるわけではないため、全員がプレイできる十分なスペースを提供し、コミュニティ メンバーのプロジェクトへの理解を高め、より大きな参加意識を持たせる必要があります。達成。この機能は次のバージョンで実装する予定です。今回、私は全体の進行を担当するチームリーダーであり、開発作業に参加する小規模なパートナーを数名募集しました。ここ数回の毎週のミーティングで、私は常にこのアイデアを友人たちに繰り返し説明してきました。というのも、常に新しい人が参加しており、そのたびに全体の内容を徹底的に説明する必要があるからです。これ以上の説明は必要ありません。さらに、ドキュメントが利用可能になった後は、このドキュメントを通じてフォローアップの開発作業を実行し、プロジェクトが最近何を行っているかを全員に知らせることができます。以上がこの記事のポイントです。この記事では、問題の内容、理由、およびその解決方法について説明します。さて、さっそく本文に入りましょう。

画像-20230308083125870

問題の現状

Bitcask は、LSM-Tree と同様に、データを追加する形式で記録します。つまり、このデータの挿入、変更、削除は、基本的に新しいデータを追加する形式になります。たとえば、操作プロセスは次のようになります。

SET key_1 value_1
SET key_1 value_2
DELETE key_1

上記のレコードは key_1 のデータに対する 3 つの操作です。key_1 の初期化の値は value_1 です。2 番目の操作は key_1 の値を更新して value_2 に変更することであり、3 番目の操作はこの key_1 を削除することです。これら 3 つの操作の後、key_1 は私たちの感覚から消えるはずです。しかしそうではなく、この時のディスク上のデータの状態はこんな感じです。

画像-20230306213341671

実際にはディスク内に 3 つのデータが存在することがわかります。1 つは value_1 のデータ、もう 1 つは value_2 のデータ、そして最後のデータは削除されたデータを表しています。実際、現時点では削除を表す最後のデータのみが有用であり、メモリ インデックスはこのデータのみを指します (この部分の詳細については、Bitcask の論文を参照してください)。最初の 2 つのデータは次のとおりです。システムの観点からは無効です。ただし、それでもある程度のディスク領域を占有します。Merge メソッドの役割は、これらの無効なディスク領域を再利用することです。それでは、Merge は現在どのように実装されているのでしょうか?

この問題を明確に説明するために、nutdb 全体のデータ ストレージの分布を見てみましょう。DB 全体はファイルで構成されています。データベースが初期化されると、ファイル サイズのしきい値が初期化されます。現在のファイルがしきい値のサイズに達すると、次のデータを保存するために次のファイルが作成されます。

画像-20230306213847715

現在の Merge メソッドは次のように実装されています。

  1. すべてのファイル内のすべてのデータをスキャンします (書き込み用の最新ファイルを除く)
  2. メモリインデックスに基づいてこのデータが最新かどうかを判断する(追記:メモリインデックスに格納されるインデックス情報は常にこのデータの最新バージョンのインデックス情報を指す)
  3. このデータが最新の場合は、このデータを書き換えるだけで済みます。そして、このデータのメモリインデックスは、最新のデータの場所を実行します。
  4. ファイル全体の最新データが書き換えられた場合、ファイル全体のデータは古いデータとなるため、この時点でファイル全体を削除してもよい。
  5. データベース内のすべてのファイル (最新の書き込みファイルを除く) が完了すると、データベース全体のデータ回復プロセスが終了します。

さて、問題全体の現状をここで説明します。では、現在これを行うと何が問題になるのか見てみましょう。

何が問題ですか?

まず、外部ユーザーがこれらの不要なデータを自分でリサイクルできるように、Merge メソッドを提供します。問題 1: 実際、ユーザーはデータをいつリサイクルすればよいのかわからない場合があります。言い換えれば、現時点では db 内のデータがどのような状況になっているかを知りません

おそらく、いくつかの極端な状況に遭遇するでしょう。たとえば、ディスク内に 100 件のレコードがあり、99 件のレコードが有効で、1 件のレコードが無効です。この時点で、Merge メソッドを呼び出すコストは、ディスクから 100 件のレコードを読み取り、 99 件のレコードを書き換え、1 件が正常に回復されました。これが 2 番目の問題です。この場合、Merge の実​​行コストが高すぎ、その効果が一般的すぎるということです

さらに、現在のデータベースは読み取り/書き込みロックのセット全体を使用しているため、最新のデータをデータベースに再書き込みすると書き込みロックが適用されます。さらに多くのデータが書き換えられると、データベース全体のハング時間が長くなり、ユーザーの書き込みプロセスに影響します。 。大量の db データがある場合、すべての db ファイルを走査するのにかかる時間が許容できないレベルに達する可能性があります。

解決

那么怎么解决上述问题呢?其实上述的问题通过一个方法就可以解决,那就是建立一个对磁盘数据监控的机制,触发了某种指标的阈值,就自动执行Merge操作,就可以解决了。首先用户不知道磁盘中数据的情况,就不知道该不该执行Merge操作去回收掉无效的磁盘空间。我们帮助他去监控磁盘情况,也帮助他触发回收,最后把这个操作弄成配置,用户可以选择开启或者关闭这个功能即可。

那么新的问题来了,该建立怎么样的监控体系呢?来让我们看下下面的问题拆解。

如何建立监控体系

首先让我们来回顾整个Merge操作的流程,我们会发现,对于一个文件来说,Merge操作会读出所有的数据,也就是全量读取这个文件是不可避免的,判断当前这条数据是最新的之后会重新写入这条数据。也就是所有这个文件中的最新数据都会重新写入一遍。嗯?等会?如果写入少了是不是就更省写入资源了?操作也就更快了,db hang住的时间也就更短了? 优化点这不就来了吗?

问题的解决之道在上面的分析中已经找到了,首先对于整个文件的读取,我们是没办法避免的,能优化的地方就是让Merge操作尽量少的写入。那么整个流程效率就会高很多。所以要建立的指标有以下两个:

  1. 统计一个文件中的数据总量以及无效数据的量(有效的也可以)
  2. 统计一个文件中有效的磁盘空间和无效的磁盘空间。

影响写入的因素有两种,一是写入数据的次数,二是写入数据的大小。通过建立上述两个指标,在设置一个阈值,这两个指标其中之一到达阈值之后我们可以触发一次针对一个文件的Merge。Merge精细到文件粒度,也就是说每次触发Merge只会Merge单个文件,而不会Merge整个db的文件,这样可以减少Merge的操作时间,从而降低对用的影响。

FAQ

FAQ环节记录在和社区小伙伴们开周会期间被问到的一些问题。

1. 有了针对单个文件的Merge是否还需要针对db所有文件的Merge?

回答:その必要はないと思います。なぜ?データベース全体の回復しきい値を 40% に設定すると、つまり、データベースの無効なキーまたはスペースが 40% に達すると、データベース全体のマージが実行されます。この 40% は、データベース内のすべてのファイルの無効な平均値として理解できます。この値よりも高いファイルと、この値よりも低いファイルが常に存在します。もちろん、この値より高いファイルはリサイクルできます。ただし、この値より低い場合、ファイル回復の効率は期待に応えられません。たとえば、データベース内の 1 つのファイルの無効なデータの割合が 100% で、もう 1 つのファイルが 0% である場合、データベース全体の自動回復戦略が構築されており、最初のファイルをマージする必要があることは明らかです。早期に、もう一方はマージをリサイクルしないでください。つまり、データベース全体のリサイクル戦略では、データ分散の問題を回避することはできません。

2. 古いデータが新しいデータを上書きする問題はありますか?

答え: いいえ。Merge では現在のデータが最新かどうかをインデックスから判断し、最新でない場合は書き換えません。最新であれば書き換え後にメモリインデックスが更新されるため、この問題は発生しません。

要約する

今回は、主にこの問題の原因と影響、解決策についてお話しさせていただき、その後、機能全体のオーナーとして、実装を進めてまいります。初期実装と実装が異なる場合がありますが、機能全体が完成したらまたまとめ記事を書く予定です。この問題についてご質問がある場合は、プライベート メッセージで私にご連絡いただくか、以下の github アドレスにコメントしてください。見てからまた連絡します。ありがたい。

参考文献

  1. 発行アドレス: github.com/nutsdb/nuts…

おすすめ

転載: juejin.im/post/7256014547067207717
おすすめ