Bagikan melalui


Model aplikasi SaaS multi-penyewa di Azure Cosmos DB for PostgreSQL

BERLAKU UNTUK: Azure Cosmos DB for PostgreSQL (didukung oleh ekstensi database Citus ke PostgreSQL)

ID penyewa sebagai kunci shard

ID penyewa adalah kolom di akar beban kerja, atau bagian atas hierarki dalam model data Anda. Misalnya, dalam skema e-niaga SaaS ini, itu akan menjadi ID toko:

Diagram tabel, dengan kolom store_id ditandai.

Model data ini akan menjadi tipikal untuk bisnis seperti Shopify. Ini menghosting situs untuk beberapa penyimpanan online, di mana setiap penyimpanan berinteraksi dengan datanya sendiri.

  • Model data ini memiliki banyak tabel: penyimpanan, produk, pesanan, item baris, dan negara.
  • Tabel penyimpanan berada di bagian atas hierarki. Produk, pesanan, dan item baris semuanya terkait dengan penyimpanan, sehingga lebih rendah dalam hierarki.
  • Tabel negara tidak terkait dengan masing-masing penyimpanan, melainkan di antara seluruh penyimpanan.

Dalam contoh ini, store_id, yang berada di bagian atas hierarki, adalah pengidentifikasi untuk penyewa. Ini adalah kunci shard yang tepat. Memilih store_id sebagai kunci shard memungkinkan mengelokasikan data di semua tabel untuk satu penyimpanan pada satu pekerja.

Mengkolokasi tabel berdasarkan toko memiliki kelebihan:

  • Menyediakan cakupan SQL seperti kunci asing, JOIN. Transaksi untuk satu penyewa dilokalkan pada satu node pekerja tempat setiap penyewa berada.
  • Mencapai performa dalam rentang satu hingga sembilan milidetik. Kueri untuk pengguna tunggal dirutekan ke satu node alih-alih diparalelkan, yang membantu mengoptimalkan lompatan jaringan dan tetap menskalakan komputasi/memori.
  • Ini dapat diskalakan. Seiring bertambahnya jumlah penyewa, Anda dapat menambahkan node dan menyeimbangkan penyewa ke node baru, atau bahkan mengisolasi penyewa besar ke node mereka sendiri. Isolasi penyewa memungkinkan Anda menyediakan sumber daya khusus.

Diagram tabel yang ditempatkan bersama pada node yang sama.

Model data optimal untuk aplikasi multi-penyewa

Dalam contoh ini, kami harus mendistribusikan tabel khusus penyimpanan menurut ID penyimpanan, dan membuat countries tabel referensi.

Diagram tabel dengan store_id yang lebih universal ditandai.

Perhatikan bahwa tabel khusus penyewa memiliki ID penyewa dan didistribusikan. Dalam contoh kami, toko, produk, dan barang_baris didistribusikan. Tabel lainnya adalah tabel referensi. Dalam contoh kami, tabel negara adalah tabel referensi.

-- Distribute large tables by the tenant ID

SELECT create_distributed_table('stores', 'store_id');
SELECT create_distributed_table('products', 'store_id', colocate_with => 'stores');
-- etc for the rest of the tenant tables...

-- Then, make "countries" a reference table, with a synchronized copy of the
-- table maintained on every worker node

SELECT create_reference_table('countries');

Semua tabel besar seharusnya memiliki ID penyewa.

  • Jika Anda memigrasikan aplikasi multi-penyewa yang ada ke Azure Cosmos DB for PostgreSQL, Anda mungkin perlu mendenormalisasi sedikit dan menambahkan kolom ID penyewa ke tabel besar jika hilang, lalu isi ulang nilai kolom yang hilang.
  • Untuk aplikasi baru di Azure Cosmos DB for PostgreSQL, pastikan ID penyewa ada di semua tabel khusus penyewa.

Pastikan untuk menyertakan ID penyewa pada batasan kunci primer, unik, dan asing pada tabel terdistribusi dalam bentuk kunci komposit. Misalnya, jika sebuah tabel memiliki kunci primer id, ubahlah menjadi kunci komposit (tenant_id,id). Tidak perlu mengubah kunci untuk tabel referensi.

Pertimbangan kueri untuk performa terbaik

Kueri terdistribusi yang memfilter berdasarkan ID penyewa berfungsi paling efisien di aplikasi multi-penyewa. Pastikan bahwa kueri Anda selalu dibatasi ke satu penyewa.

SELECT *
  FROM orders
 WHERE order_id = 123
   AND store_id = 42;  -- ← tenant ID filter

Anda perlu menambahkan filter ID tenant meskipun kondisi filter asli sudah dengan jelas mengidentifikasi baris yang Anda inginkan. Filter ID penyewa, meskipun tampaknya berlebihan, memberi tahu Azure Cosmos DB for PostgreSQL cara merutekan kueri ke simpul pekerja tunggal.

Demikian pula, saat Anda menggabungkan dua tabel terdistribusi, pastikan kedua tabel tersebut dicakup untuk satu penyewa. Pencakupan dapat dilakukan dengan memastikan bahwa kondisi penggabungan termasuk ID penyewa.

SELECT sum(l.quantity)
  FROM line_items l
 INNER JOIN products p
    ON l.product_id = p.product_id
   AND l.store_id = p.store_id   -- ← tenant ID in join
 WHERE p.name='Awesome Wool Pants'
   AND l.store_id='8c69aa0d-3f13-4440-86ca-443566c1fc75';
       -- ↑ tenant ID filter

Ada pustaka pembantu untuk beberapa kerangka kerja aplikasi populer yang memudahkan untuk menyertakan ID penyewa dalam kueri. Berikut adalah petunjuknya:

Langkah berikutnya

Sekarang kita telah selesai mempelajari pemodelan data untuk aplikasi yang dapat diskalakan. Langkah selanjutnya adalah menyambungkan dan mengkueri database dengan bahasa pemrograman pilihan Anda.