Menangani semakin banyak Penyewa dalam Arsitektur Database Multi-penyewa

26

Menangani sejumlah kecil pelanggan (penyewa) di server umum dengan basis data terpisah untuk setiap instance penyewa dari aplikasi relatif mudah dan biasanya merupakan cara yang tepat untuk melakukan ini. Saat ini saya sedang melihat arsitektur untuk sebuah aplikasi di mana setiap penyewa memiliki instance database mereka sendiri.

Namun, masalahnya adalah bahwa aplikasi ini akan memiliki sejumlah besar penyewa (5.000-10.000) dengan sejumlah besar pengguna, mungkin 2.000 untuk satu penyewa. Kami perlu mendukung pengembangan sistem oleh beberapa penyewa setiap minggu.

Selain itu, semua penyewa dan penggunanya akan disajikan dengan proses masuk yang sama (yaitu setiap penyewa tidak dapat memiliki URL sendiri). Untuk melakukan ini, saya memerlukan proses login terpusat dan sarana untuk secara dinamis menambahkan database ke sistem dan mendaftarkan pengguna.

  • Bagaimana proses registrasi dan pembuatan basis data dapat diotomatisasi dengan kuat?

  • Apakah proses membuat dan mendaftarkan basis data penyewa pada sistem cenderung menyebabkan kinerja atau masalah penguncian. Jika Anda pikir ini bisa menjadi masalah, adakah yang bisa menyarankan cara untuk meredakannya?

  • Bagaimana saya bisa mengelola otentikasi pusat dengan cara di mana kredensial pengguna akan dikaitkan dengan database penyewa tertentu tetapi pengguna dapat masuk melalui halaman umum (yaitu semua melalui URL login yang sama, tetapi aplikasi rumah mereka akan berada di database penyewa tertentu) ). Penyewa harus dapat mempertahankan login dan izin mereka sendiri, tetapi sistem login pusat harus menyadarinya. Adakah yang bisa menyarankan cara untuk melakukan ini?

  • Jika saya perlu 'meningkatkan skala' dengan menambahkan beberapa server basis data, adakah yang bisa menyarankan masalah apa yang harus saya hadapi dalam mengelola identitas pengguna di seluruh server (peniruan dll) dan beberapa cara untuk mengurangi masalah-masalah itu?

coddey
sumber
1
Saya belum pernah menghadapi situasi seperti ini, tetapi intuisi saya adalah untuk menangani peluncuran penyewa dengan mengkonfigurasi server dengan sebanyak mungkin basis data penyewa seperti yang Anda pikir dapat mereka tangani dan kemudian hanya menetapkan basis data penyewa yang sudah dibangun sebagai penyewa baru Daftar. Dengan cara ini Anda tidak perlu khawatir tentang pertentangan sumber daya saat menggunakan DB penyewa setidaknya.
Joel Brown
1
Apakah Anda yakin akan mendekati 5.000-10.000 penyewa? Dan semua penyewa Anda akan berada di kisaran 2.000 pengguna? Dalam sistem saya, saya pikir jumlah terbesar pengguna aplikasi kami untuk penyewa tunggal adalah sekitar 100. Dan hanya 20 atau lebih yang secara aktif aktif. Bisakah saya bertanya apa industri / aplikasi itu?
Aaron Bertrand
@AaronBertrand Merupakan Sistem Manajemen Pembelajaran di mana layanan akan sebagian gratis dan sebagian dibayar.
coddey

Jawaban:

25

Pada ujung bawah (500 penyewa / 10.000 pengguna) ini adalah bagaimana saya melakukannya. Pertama, Anda memiliki "kontrol" database yang bersifat global, pusat dan berisi semua informasi tentang penyewa dan pengguna (saya benar-benar tidak berpikir Anda ingin mengelola ini sebagai login auth SQL). Jadi bayangkan sebuah database yang disebut "Kontrol" dengan tabel-tabel berikut:

CREATE TABLE dbo.Instances
(
  InstanceID INT PRIMARY KEY,
  Connection VARCHAR(255)
  --, ...
);

INSERT dbo.Instances SELECT 1, 'PROD1\Instance1';
INSERT dbo.Instances SELECT 1, 'PROD2\Instance1';
-- ...

CREATE TABLE dbo.Tenants
(
  TenantID INT PRIMARY KEY,
  Name NVARCHAR(255) NOT NULL UNIQUE,
  InstanceID INT -- Foreign key tells which instance this tenant's DB is on
  --, ...
);

INSERT dbo.Tenants SELECT 1, 'MyTenant', 1;
-- ...

CREATE TABLE dbo.Users
(
  UserID INT PRIMARY KEY,
  Username VARCHAR(320) NOT NULL UNIQUE,
  PasswordHash VARBINARY(64), -- because you never store plain text, right?
  TenantID INT -- foreign key
  --, ...
);

INSERT dbo.Users SELECT 1, '[email protected]', 0x43..., 1;

Dalam kasus kami ketika kami menambahkan penyewa baru, kami akan membangun basis data secara dinamis, tetapi tidak ketika pengguna admin mengklik OK di UI ... kami memiliki pekerjaan latar belakang yang menarik basis data baru dari antrian setiap 5 menit, mengatur model ke single_user , dan kemudian membuat setiap database baru secara serial. Kami melakukan ini untuk (a) mencegah pengguna admin menunggu pembuatan basis data dan (b) untuk menghindari dua pengguna admin yang mencoba membuat database pada saat yang sama atau ditolak kemampuannya untuk mengunci model (diperlukan saat membuat database baru ).

Database dibuat dengan skema nama Tenant000000xxtempat xxterwakili Tenants.TenantID. Hal ini membuat pekerjaan pemeliharaan cukup mudah, daripada harus semua jenis database bernama BurgerKing, McDonalds, KFCdll Tidak bahwa kami berada di makanan cepat saji, hanya menggunakan itu sebagai contoh.

Alasan kami tidak melakukan pra-alokasi ribuan database seperti komentar yang disarankan adalah bahwa pengguna admin kami biasanya memiliki gagasan tentang seberapa besar penyewa akan menjadi, apakah mereka prioritas tinggi, dll. Jadi mereka punya pilihan dasar di UI yang akan menentukan ukuran awal dan pengaturan autogrowth, di mana disk subsistem data / file log mereka akan pergi ke, pengaturan pemulihan mereka, jadwal cadangan untuk engsel off, dan bahkan pandai tentang contoh mana untuk menyebarkan database untuk penggunaan keseimbangan terbaik ( meskipun admin kami dapat mengesampingkan ini). Setelah basis data dibuat, tabel penyewa diperbarui dengan contoh yang dipilih, pengguna admin dibuat untuk penyewa, dan admin kami mengirim email kredensial untuk meneruskan penyewa baru.

Jika Anda menggunakan satu titik masuk, tidak memungkinkan untuk mengizinkan beberapa penyewa memiliki pengguna dengan nama pengguna yang sama. Kami memilih untuk menggunakan alamat email, yang - jika semua pengguna bekerja untuk perusahaan dan menggunakan alamat email perusahaan mereka - harus baik-baik saja. Meskipun solusi kami akhirnya menjadi lebih kompleks karena dua alasan:

  1. Kami memiliki konsultan yang bekerja untuk lebih dari satu klien kami, dan membutuhkan akses ke banyak
  2. Kami memiliki penyewa yang sebenarnya terdiri dari beberapa penyewa

Jadi, kami berakhir dengan TenantUserstabel yang memungkinkan satu pengguna dikaitkan dengan beberapa penyewa.

Awalnya ketika pengguna masuk, aplikasi akan mengetahui string koneksi hanya untuk basis data kontrol. Ketika login berhasil, ia kemudian dapat membangun string koneksi berdasarkan informasi yang ditemukannya. Misalnya

SELECT i.Connection
  FROM dbo.Instances AS i
  INNER JOIN dbo.Tenants AS t
  ON i.InstanceID = t.InstanceID
  INNER JOIN dbo.TenantUsers AS u
  ON i.TenantID = u.TenantID
  WHERE u.UserID = @UserID;

Sekarang aplikasi dapat terhubung ke basis data pengguna (setiap pengguna memiliki penyewa default ) atau pengguna dapat memilih dari penyewa mana saja yang dapat mereka akses. Aplikasi kemudian hanya akan mengambil string koneksi baru, dan mengarahkan ke halaman rumah untuk penyewa itu.

Jika Anda masuk ke area pengguna 10MM yang Anda usulkan ini, Anda pasti perlu ini diseimbangkan dengan lebih baik. Anda mungkin ingin menggabungkan aplikasi sehingga mereka memiliki titik masuk yang berbeda yang terhubung ke database kontrol yang berbeda. Jika Anda memberi masing-masing penyewa subdomain (mis. TenantName.YourApplicationDomain.com) maka Anda dapat melakukan ini di belakang layar dengan DNS / perutean tanpa menyela mereka ketika Anda perlu meningkatkan skala.

Ada banyak hal lainnya - seperti @Darin saya hanya menggaruk permukaan di sini. Beritahu saya jika Anda memerlukan konsultasi yang tidak bebas. :-)

Aaron Bertrand
sumber
Terima kasih telah berbagi pengalaman Anda. Memang ini yang membuat saya tercerahkan. Tapi kamu sudah menulis Non-gratis. :(
coddey
1
Maksud saya adalah saya hanya punya begitu banyak waktu untuk mengalokasikan ke saran gratis. :-)
Aaron Bertrand
+1 - pendekatan yang hampir sama persis seperti yang saya gunakan sebelumnya. ~ jumlah penyewa yang sama juga, bekerja dengan sangat baik.
AdaTheDev
Bagaimana menangani hubungan antara database master dan database penyewa? (tanpa menggunakan pemicu dll)
Jitendra Pancholi
@jitendra tidak terlalu banyak pilihan - berapa banyak data yang Anda miliki di basis data penyewa yang perlu dikaitkan dengan data dalam database induk? Saya juga tidak yakin saya memahami ketakutan umum akan pemicu - pemicu yang ditulis dengan benar bukanlah hal yang ditakuti ...
Aaron Bertrand
10

Anda memiliki proyek yang cukup menarik. Saya tidak pernah secara langsung melihat seseorang mencoba mengimplementasikan sesuatu yang besar, setidaknya pada SQL Server. Semakin saya membaca posting Anda, semakin banyak pertanyaan yang saya ajukan ...

Infrastruktur skenario kasus terburuk (yang sebenarnya merupakan skenario kasus terbaik, bisnis-bijaksana), Anda memerlukan database 10K kali pengguna 2k. Itu 20.000.000 pengguna. Anda tidak akan berhasil mencoba mengelola login SQL Server 20 M. IMO. Hanya jumlah mereka, berurusan dengan memindahkan mereka dari server ke server, mengawasi tabrakan ID dan ID yang tidak cocok, ditambah saya tidak yakin bagaimana SQL Server akan berperilaku dengan 20 baris M di sys.server_principals. Selain itu, aplikasi web Anda mungkin ingin terhubung sebagai pengguna tunggal, atau sangat sedikit. IIS tidak dapat menyatukan koneksi kecuali string DSN mereka identik. Salah satu atribut string DSN adalah nama pengguna. Pengguna yang berbeda berarti tidak ada penyatuan.

Anda harus memutar skema kredensial pengguna Anda sendiri. Itu harus dapat mengetahui penyewa milik siapa dan kemudian kode web Anda harus memilih database yang tepat. Metadata pengguna itu sangat penting, perlu disimpan di suatu tempat, perlu dikelompokkan atau dicerminkan, perlu cepat dan perlu dilindungi dengan baik (dari perspektif keamanan. IOW, mengenkripsi itu.). Dengan asumsi bahwa SQL adalah ide yang baik di sini, saya akan menjaga database ini jauh dari contoh yang digunakan oleh server tenant. Ini membantu dari sudut pandang keamanan dan dari sudut pandang beban, meskipun saya akan menebak bahwa sekali pengguna divalidasi dan aplikasi web diarahkan ke database yang benar pada contoh lain, tidak akan ada lagi permintaan metadata pengguna ini terkait dengan itu pengguna.

Pertanyaan cepat: haruskah dua pengguna berbeda, yang memiliki dua penyewa berbeda, diizinkan memiliki nama pengguna yang sama?

Pertanyaan cepat lainnya: Jika saya memberi tahu Anda bahwa saya bekerja untuk FuBar, Inc., bagaimana Anda tahu itu? Apakah FuBar akan memberi Anda daftar pengguna dan Anda mengembalikan mereka daftar nama pengguna, atau apakah mereka akan menyediakan sendiri?

Anda harus menggunakan multi-instance. Jika bahkan sebagian kecil dari pengguna tersebut memutuskan untuk menekan aplikasi sekaligus, satu contoh akan meleleh. Tidak akan ada cukup utas pekerja untuk menjalankan semua permintaan itu sekaligus. Jika hanya 1000 pengguna menekan instance Anda pada saat yang sama, itu mungkin akan kehabisan utas pekerja dan permintaan akan mulai menumpuk dan menunggu. Saya telah melihat ini terjadi; gejala terdekatnya adalah bahwa koneksi baru tidak akan dapat masuk ke instance karena tidak ada utas pekerja yang tersedia untuk melayani mereka. Jika ini perilaku yang sangat singkat, aplikasi Anda mungkin bertahan. Jika tidak, atau aplikasi Anda cerewet, pengguna akan mendapatkan kesalahan.

Bahkan jika Anda tidak akan memiliki banyak penyewa untuk memulai, Anda harus mulai memikirkan masa depan dan otomatisasi karena ketika Anda melihat bahwa server Anda macet dan ada 10 penyewa baru untuk online, sudah sangat terlambat dan layanan Anda (dan klien Anda, dan calon klien Anda akan menderita sampai Anda menulis jalan keluar dari masalah.

Anda akan membutuhkan cara untuk memindahkan basis data, dari server yang kelebihan beban ke server yang sedikit dimuat (atau baru). Apakah Anda bisa mendapatkan jendela downtime akan tergantung pada SLA Anda.

Apakah Anda menyediakan aplikasi spesifik, seperti SalesForce, atau apakah database ini hanya wadah untuk apa pun yang ingin dimasukkan oleh penyewa Anda?

Seberapa besar databasenya? Jika tidak terlalu besar, Anda bisa memulihkan dari file cadangan yang menyediakan templat. (Ini tidak jauh berbeda dari apa yang dilakukan oleh model database, tapi saya belum melihat ada orang yang benar-benar menggunakan model dengan baik sejak saya menggunakan SQL 6.5.) Setelah template telah dikembalikan ke nama database baru, Anda bisa kemudian sesuaikan database baru sesuai kebutuhan untuk penyewa tertentu. Anda tidak dapat melakukan kustomisasi sebelum memiliki penyewa, jelas. Jika basis datanya besar, Anda mungkin mengikuti prosedur dasar yang sama kecuali Anda melakukan pemulihan sebelumnya, sebelum penyewa baru membutuhkan ruang. Anda mungkin menyimpan beberapa database ini, mungkin satu per instance. Jika Anda menyimpan terlalu banyak, ini akan memaksa Anda untuk mungkin membeli lebih banyak perangkat keras dan / atau penyimpanan daripada yang Anda butuhkan,

Jika ini adalah aplikasi Anda sendiri, bagaimana Anda akan menangani pembaruan untuk skema? Bagaimana Anda akan menjaga versi database tetap lurus dengan versi kode, jika Anda menggunakan URL tunggal yang masuk ke aplikasi web Anda?

Bagaimana Anda mendeteksi dan menghancurkan basis data yang tidak digunakan lagi? Apakah Anda menunggu sampai kelompok A / R Anda mengatakan bahwa seseorang belum membayar tagihan mereka selama tiga bulan?

Jika penyewa mengelola izin, itu menyiratkan bahwa mereka memiliki pemahaman tentang cara kerja aplikasi, atau bahwa aplikasi Anda memiliki struktur peran yang sangat sederhana. Menggunakan sesuatu seperti Blogger sebagai contoh kasar, pengguna dapat (membaca posting), (membaca posting dan membuat komentar), (... dan membuat posting), (... dan mengedit posting orang lain), (... dan dapat mengatur ulang kata sandi pengguna lain), atau (... dan apa pun). Memiliki peran untuk masing-masing set hak yang berbeda dan menugaskan pengguna ke satu peran atau yang lain tidak boleh terlalu sulit, tetapi Anda tidak ingin aplikasi Anda menjalankan pernyataan 'GRANT'. Hati-hati dengan peran yang memiliki hierarki dan bergantung pada warisan, itu bisa membingungkan. Jika Anda mempromosikan atau menurunkan peringkat pengguna, saya katakan menarik mereka keluar dari semua peran terkait dan kemudian menambahkannya kembali ke satu peran yang mereka butuhkan. Oh

Saya pikir saya hanya menggores permukaan di sini, dan posting ini sudah terlalu lama. Yang benar-benar Anda butuhkan adalah sebuah buku, atau setidaknya whitepaper dari seseorang yang telah melakukan ini. Kebanyakan dari mereka tidak akan berbicara, jika mereka melihatnya sebagai keunggulan kompetitif.

selat darin
sumber
Terima kasih atas komentarnya. Memang proyek ini menarik. Karena keterbatasan kata saya sangat menjaga komentar. Ini adalah Sistem Manajemen Pembelajaran di mana setiap penyewa akan memiliki sekitar 120-150 tabel. Tidak ada pengguna yang akan memiliki nama pengguna yang sama terlepas dari Penyewa. Untuk lebih mengurangi kompleksitas, pemetaan CNAME DNS akan digunakan, misalnya tenant1.abc.com. Sekarang titik didih adalah - merancang dengan cara yang benar sehingga akan memenuhi semua saran yang telah Anda bagikan dan saya khawatir. Mendapatkan whitepaper akan menjadi hal yang patut dipuji tetapi tidak mudah, mungkin. Mencari masukan lebih banyak jika Anda bisa. !!!!
coddey