6

I'm working on a real-time application with the following characteristics:

  • Hundreds of clients will be inserting rows/documents at the same time, each inserting a row every couple of seconds.
  • Largely append-only; almost all rows/documents, once inserted, are never changed.
  • A client should only see success when data has been flushed to disk, and thereafter read-your-writes consistency should hold.
  • Clients are willing to wait on the order of seconds for confirmation - long enough for multiple disk seeks and writes to happen.
  • There is too much data to fit in RAM (ruling out options like Redis). But written-long-ago rows are rarely accessed, so it's acceptable to not have them in memory.
  • Ideally, these writes should not block reads.
  • A key-value store is fine, but there needs to be at least one reliable auto-incrementing index.

In other words (and tl;dr), the clients can tolerate latency, but they need a lot of trustable write throughput - more throughput than "one write is one disk operation."

I'm envisioning a database that would be implemented something like this: accept a (theoretically limited by the number of file descriptors) number of TCP connections, buffer those writes in memory, log batches of them to disk as often as possible (along with the updates to the auto-incrementing index), and only respond to those TCP connections when the associated disk write operation is complete. Or it could be as simple as a lazily-writing database publishing a message that it has done a disk write (clients wait for the lazy response, then wait for the write message to report success).

I think that with such high latency tolerance, this isn't asking too much. And I'd imagine that others have had this problem, such as financial companies that can't afford to lose data, but can afford to delay the response to any one client.

Do any battle-tested database solutions like Postgres, CouchDB/Couchbase, or MongoDB support modes of operation like this?

4

1 に答える 1

11

PostgreSQL は、このワークロードにかなり適しているはずです。あなたが指定したほとんどすべてが、通常の機能セットの範囲内です。Pg は ACID に準拠し、グループ コミットをサポートして同期のオーバーヘッドを削減し、ライターはリーダーをブロックせず、キャッシュに OS を使用するため、自然にホット データ セットのみをメモリに保持する傾向があります。

「クライアントは、確認のために秒単位で待機することをいとわない - 複数のディスクのシークと書き込みが発生するのに十分な時間」

PostgreSQL を検討している場合、アプリケーションは非常に大きな に最適でcommit_delayあり、書き込みスループットが大幅に向上します。synchronous_commit = off返信する前にコミットの確認が必要なため使用できませんが、同期コストを節約するためにコミットをキューに数秒間保持することができます。

このようなジョブに Pg を使用する場合は、チェックポイントが I/O を停止させないようにチェックポイントを調整する必要があります。bgwriter が積極的にダーティ バッファを書き出していることを確認してください。自動バキュームが頻繁に実行されていることを確認してください。テーブルから削除していませんが、インデックスはまだメンテナンスが必要であり、テーブルの統計も必要です。

大量のデータが予想され、通常、クエリに一時的な要素が含まれている場合は、テーブルを最初の年に (たとえば) 1 か月のチャンクに分割し、12 か月より古いすべてのものを年ごとに分割されたテーブルに統合することを検討してください。Pg には組み込みのパーティショニングが制限されている (継承と制約の除外を使用して一緒にハッキングされている) ため、トリガーを使用して手動/スクリプトで行う必要がありますが、それで機能します。

見る:

于 2012-10-11T06:12:01.953 に答える