জ্যাঙ্গো একটি জনপ্রিয় ফ্রেমওয়ার্ক যা আপনি আপনার কোম্পানির জন্য একটি অ্যাপ্লিকেশন বিকাশ করতে নির্বাচন করতে পারেন। কিন্তু আপনি যদি একটি SaaS অ্যাপ্লিকেশন তৈরি করতে চান যা একাধিক ক্লায়েন্ট ব্যবহার করবে? আপনি কি স্থাপত্য চয়ন করা উচিত? আসুন দেখি কিভাবে এই কাজটি করা যায়। একক ভাড়াটে আর্কিটেকচার আপনার কাছে থাকা প্রতিটি ক্লায়েন্টের জন্য একটি পৃথক উদাহরণ তৈরি করা সবচেয়ে সহজ পদ্ধতি। ধরা যাক আমাদের একটি জ্যাঙ্গো অ্যাপ্লিকেশন এবং একটি ডাটাবেস আছে। তারপর, প্রতিটি ক্লায়েন্টের জন্য, আমাদের নিজস্ব ডাটাবেস এবং অ্যাপ্লিকেশন উদাহরণ চালাতে হবে। এর মানে হল যে প্রতিটি আবেদনের উদাহরণে শুধুমাত্র একজন ভাড়াটে থাকে। এই পদ্ধতিটি বাস্তবায়ন করা সহজ: আপনাকে আপনার কাছে থাকা প্রতিটি পরিষেবার একটি নতুন উদাহরণ শুরু করতে হবে। কিন্তু একই সময়ে, এটি একটি সমস্যা সৃষ্টি করতে পারে: প্রতিটি ক্লায়েন্ট অবকাঠামোর করবে। আপনি যদি মাত্র কয়েকটি ক্লায়েন্ট রাখার পরিকল্পনা করেন বা প্রতিটি উদাহরণ ছোট হয় তবে এটি একটি বড় ব্যাপার নাও হতে পারে। খরচ উল্লেখযোগ্যভাবে বৃদ্ধি যাইহোক, ধরা যাক যে আমরা একটি বড় কোম্পানি তৈরি করছি যেটি 100,000 প্রতিষ্ঠানকে একটি কর্পোরেট মেসেঞ্জার প্রদান করে। কল্পনা করুন, প্রতিটি নতুন ক্লায়েন্টের জন্য পুরো পরিকাঠামো নকল করা কতটা ব্যয়বহুল হতে পারে! এবং, যখন আমাদের অ্যাপ্লিকেশন সংস্করণ আপডেট করতে হবে, তখন আমাদের প্রতিটি ক্লায়েন্টের জন্য এটি স্থাপন করতে হবে, তাই ৷ স্থাপনাটিও ধীর হয়ে যাবে মাল্টি-টেন্যান্ট আর্কিটেকচার আরেকটি পদ্ধতি আছে যা একটি পরিস্থিতিতে সাহায্য করতে পারে যখন আমাদের কাছে অ্যাপ্লিকেশনের জন্য প্রচুর ক্লায়েন্ট থাকে: একটি মাল্টি-টেন্যান্ট আর্কিটেকচার। এর মানে হল যে আমাদের একাধিক ক্লায়েন্ট আছে, যাকে আমরা বলি, কিন্তু তারা সবাই অ্যাপ্লিকেশনের একটি মাত্র উদাহরণ ব্যবহার করে। ভাড়াটে যদিও এই আর্কিটেকচারটি প্রতিটি ক্লায়েন্টের জন্য ডেডিকেটেড দৃষ্টান্তের উচ্চ খরচের সমস্যা সমাধান করে, এটি একটি নতুন সমস্যা প্রবর্তন করে: কীভাবে আমরা নিশ্চিত হতে পারি যে ক্লায়েন্টের ডেটা অন্য ক্লায়েন্টদের থেকে নিরাপদে বিচ্ছিন্ন হয়েছে? আমরা নিম্নলিখিত পদ্ধতিগুলি নিয়ে আলোচনা করব: ব্যবহার করে: আমরা প্রতিটি ডাটাবেস টেবিলে যোগ করতে হবে এমন বিদেশী কী দ্বারা কোন ভাড়াটে ডেটার মালিক তা শনাক্ত করতে পারি। একটি শেয়ার্ড ডাটাবেস এবং শেয়ার্ড ডাটাবেস স্কিমা : এইভাবে, আমাদের একাধিক ডাটাবেস দৃষ্টান্ত বজায় রাখতে হবে না তবে ভাড়াটে ডেটা বিচ্ছিন্নতার একটি ভাল স্তর পাবেন। একটি ভাগ করা ডাটাবেস ব্যবহার করা, কিন্তু পৃথক ডাটাবেস স্কিমা ব্যবহার করা: এটি একক-ভাড়াটেদের উদাহরণের মতো দেখায়, কিন্তু একই রকম হবে না, কারণ আমরা এখনও একটি ভাগ করা অ্যাপ্লিকেশন উদাহরণ ব্যবহার করব এবং ভাড়াটে চেক করে কোন ডাটাবেস ব্যবহার করতে হবে তা নির্বাচন করব৷ পৃথক ডাটাবেস আসুন এই ধারণাগুলির আরও গভীরে ডুব দেওয়া যাক এবং দেখুন কিভাবে জ্যাঙ্গো অ্যাপ্লিকেশনের সাথে তাদের একীভূত করা যায়। শেয়ার্ড স্কিমা সহ একটি ভাগ করা ডাটাবেস এই বিকল্পটি প্রথম মনে আসতে পারে: টেবিলে একটি ForeignKey যোগ করতে এবং প্রতিটি ভাড়াটেদের জন্য উপযুক্ত ডেটা নির্বাচন করতে এটি ব্যবহার করুন। যাইহোক, এর একটি বিশাল অসুবিধা রয়েছে: ভাড়াটেদের ডেটা একেবারেই আলাদা করা হয় না, তাই একটি ছোট প্রোগ্রামিং ত্রুটি ভাড়াটেদের ডেটা ভুল ক্লায়েন্টের কাছে ফাঁস করার জন্য যথেষ্ট হতে পারে। থেকে ডাটাবেস গঠনের একটি উদাহরণ নেওয়া যাক: জ্যাঙ্গো ডকুমেন্টেশন from django.db import models class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField("date published") class Choice(models.Model): question = models.ForeignKey(Question, on_delete=models.CASCADE) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0) আমাদের চিহ্নিত করতে হবে কোন রেকর্ডগুলো কোন ভাড়াটিয়ার মালিকানাধীন। সুতরাং, প্রতিটি বিদ্যমান টেবিলে আমাদের একটি টেবিল এবং একটি বিদেশী কী যোগ করতে হবে: Tenant class Tenant(models.Model): name = models.CharField(max_length=200) class Question(models.Model): tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE) question_text = models.CharField(max_length=200) pub_date = models.DateTimeField("date published") class Choice(models.Model): tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE) question = models.ForeignKey(Question, on_delete=models.CASCADE) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0) কোডটিকে কিছুটা সরল করার জন্য, আমরা একটি বিমূর্ত বেস মডেল তৈরি করতে পারি যা আমাদের তৈরি করা একে অপরের মডেলে পুনরায় ব্যবহার করা হবে। class Tenant(models.Model): name = models.CharField(max_length=200) class BaseModel(models.Model): tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE) class Meta: abstract = True class Question(BaseModel): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField("date published") class Choice(BaseModel): question = models.ForeignKey(Question, on_delete=models.CASCADE) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0) আপনি দেখতে পাচ্ছেন, এখানে কমপক্ষে দুটি বড় ঝুঁকি রয়েছে: একজন , অথবা একজন বিকাশকারী নতুন মডেলে একটি ভাড়াটে ক্ষেত্র যোগ করতে ভুলে যেতে পারেন বিকাশকারী ডেটা ফিল্টার করার সময় এই ক্ষেত্রটি ব্যবহার করতে ভুলে যেতে পারেন। এই উদাহরণের সোর্স কোডটি GitHub-এ পাওয়া যাবে: । https://github.com/bp72/django-multitenancy-examples/tree/main/01_shared_database_shared_schema পৃথক স্কিমা সহ একটি ভাগ করা ডাটাবেস শেয়ার্ড স্কিমার ঝুঁকির কথা মাথায় রেখে, আরেকটি বিকল্প বিবেচনা করা যাক: ডাটাবেস এখনও শেয়ার করা হবে, কিন্তু আমরা প্রতিটি ভাড়াটেদের জন্য একটি ডেডিকেটেড স্কিমা তৈরি করব। বাস্তবায়নের জন্য, আমরা একটি জনপ্রিয় লাইব্রেরি ( ) দেখতে পারি। জ্যাঙ্গো-টেন্যান্ট ডকুমেন্টেশন আসুন আমাদের ছোট প্রকল্পে যোগ করি (অফিসিয়াল ইনস্টলেশন পদক্ষেপগুলি পাওয়া যাবে)। django-tenants এখানে প্রথম ধাপ হল মাধ্যমে লাইব্রেরি ইনস্টলেশন: pip pip install django-tenants মডেলগুলি পরিবর্তন করুন: মডেলটি এখন একটি পৃথক অ্যাপে থাকবে এবং মডেলের আর ভাড়াটেদের সাথে কোনো সংযোগ থাকবে না৷ যেহেতু বিভিন্ন ভাড়াটেদের ডেটা আলাদা স্কিমাতে থাকবে, তাই আমাদের আর ভাড়াটেদের সারিগুলির সাথে পৃথক রেকর্ডগুলি লিঙ্ক করার প্রয়োজন হবে না। Tenant Question Choice ফাইল tenants/models.py from django.db import models from django_tenants.models import TenantMixin, DomainMixin class Tenant(TenantMixin): name = models.CharField(max_length=200) # default true, schema will be automatically created and synced when it is saved auto_create_schema = True class Domain(DomainMixin): # a required table for django-tenants too ... ফাইল polls/models.py from django.db import models class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField("date published") class Choice(models.Model): question = models.ForeignKey(Question, on_delete=models.CASCADE) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0) লক্ষ্য করুন যে প্রশ্ন এবং পছন্দের টেন্যান্টের কাছে আর বিদেশী কী নেই! অন্য যে জিনিসটি পরিবর্তন করা হয়েছে তা হল টেন্যান্ট এখন একটি আলাদা অ্যাপে রয়েছে: এটি শুধুমাত্র ডোমেনগুলিকে আলাদা করার জন্য নয়, এটি গুরুত্বপূর্ণও কারণ আমাদের শেয়ার্ড স্কিমাতে টেবিল সংরক্ষণ করতে হবে এবং প্রতিটি ভাড়াটেদের জন্য টেবিল তৈরি করা হবে স্কিমা tenants polls একাধিক স্কিমা এবং ভাড়াটেদের সমর্থন করতে ফাইলে পরিবর্তন করুন: settings.py DATABASES = { 'default': { 'ENGINE': 'django_tenants.postgresql_backend', # .. } } DATABASE_ROUTERS = ( 'django_tenants.routers.TenantSyncRouter', ) MIDDLEWARE = ( 'django_tenants.middleware.main.TenantMainMiddleware', #... ) TEMPLATES = [ { #... 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.request', #... ], }, }, ] SHARED_APPS = ( 'django_tenants', # mandatory 'tenants', # you must list the app where your tenant model resides in 'django.contrib.contenttypes', # everything below here is optional 'django.contrib.auth', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.admin', ) TENANT_APPS = ( # your tenant-specific apps 'polls', ) INSTALLED_APPS = list(SHARED_APPS) + [app for app in TENANT_APPS if app not in SHARED_APPS] TENANT_MODEL = "tenants.Tenant" TENANT_DOMAIN_MODEL = "tenants.Domain" এর পরে, আসুন মাইগ্রেশন তৈরি এবং প্রয়োগ করি: python manage.py makemigrations python manage.py migrate_schemas --shared ফলস্বরূপ, আমরা দেখব যে সর্বজনীন স্কিমা তৈরি হবে এবং এতে শুধুমাত্র ভাগ করা টেবিল থাকবে। আমাদের স্কিমার জন্য একটি ডিফল্ট ভাড়াটে তৈরি করতে হবে: public python manage.py create_tenant --domain-domain=default.com --schema_name=public --name=default_tenant জিজ্ঞাসা করা হলে কে এ সেট করুন। is_primary True এবং তারপর, আমরা পরিষেবার প্রকৃত ভাড়াটে তৈরি করা শুরু করতে পারি: python manage.py create_tenant --domain-domain=tenant1.com --schema_name=tenant1 --name=tenant_1 python manage.py create_tenant --domain-domain=tenant2.com --schema_name=tenant2 --name=tenant_2 লক্ষ্য করুন যে ডাটাবেসে এখন আরও 2টি স্কিমা রয়েছে যাতে টেবিল রয়েছে: polls এখন, আপনি বিভিন্ন স্কিমা থেকে প্রশ্ন এবং পছন্দ পাবেন যখন আপনি ভাড়াটেদের জন্য সেট আপ করেছেন এমন ডোমেনে API কল করবেন - সব শেষ! যদিও সেটআপটি আরও জটিল এবং সম্ভবত আরও কঠিন দেখায় যদি আপনি বিদ্যমান অ্যাপটি স্থানান্তরিত করেন, তবে পদ্ধতিতে এখনও ডেটার নিরাপত্তার মতো অনেক সুবিধা রয়েছে। উদাহরণের কোড পাওয়া যাবে। এখানে পৃথক ডাটাবেস আজকে আমরা যে শেষ পন্থা নিয়ে আলোচনা করব তা হল আরও এগিয়ে যাওয়া এবং ভাড়াটেদের জন্য আলাদা ডেটাবেস থাকা। এই সময়, আমাদের কাছে কয়েকটি ডাটাবেস থাকবে: আমরা ভাগ করা ডেটা সংরক্ষণ করব যেমন টেন্যান্টের ম্যাপিং ডেটাবেসগুলির নামের সাথে এবং প্রতিটি ভাড়াটে জন্য একটি পৃথক ডাটাবেস তৈরি করব৷ default_db তারপরে আমাদের settings.py-এ ডেটাবেস কনফিগারেশন সেট করতে হবে: DATABASES = { 'default': { 'NAME': 'default_db', ... }, 'tenant_1': { 'NAME': 'tenant_1', ... }, 'tenant_2': { 'NAME': 'tenant_2', ... }, } এবং এখন, আমরা QuerySet পদ্ধতি কল করে প্রতিটি ভাড়াটেদের জন্য ডেটা পেতে সক্ষম হব: using Questions.objects.using('tenant_1')… পদ্ধতির নেতিবাচক দিক হল যে আপনাকে ব্যবহার করে প্রতিটি ডাটাবেসে সমস্ত মাইগ্রেশন প্রয়োগ করতে হবে: python manage.py migrate --database=tenant_1 ব্যবহারের তুলনায় বা শেয়ার্ড স্কিমা পদ্ধতির মতো একটি বিদেশী কী ব্যবহার করার তুলনায় প্রতিটি ভাড়াটেদের জন্য একটি নতুন ডাটাবেস তৈরি করা কম সুবিধাজনক হতে পারে। django-tenants অন্যদিকে, ভাড়াটেদের ডেটার বিচ্ছিন্নতা সত্যিই ভাল: ডেটাবেসগুলি শারীরিকভাবে আলাদা করা যেতে পারে। আরেকটি সুবিধা হল যে আমরা শুধুমাত্র Postgresql ব্যবহার করে সীমাবদ্ধ থাকব না কারণ এটি জন্য প্রয়োজন, আমরা আমাদের প্রয়োজন অনুসারে যে কোনও ইঞ্জিন নির্বাচন করতে পারি। django-tenants একাধিক ডাটাবেসের বিষয়ে আরও তথ্য জ্যাঙ্গো পাওয়া যাবে। ডকুমেন্টেশনে তুলনা একক ভাড়াটে শেয়ার্ড স্কিমা সহ MT পৃথক স্কিমা সহ MT পৃথক ডাটাবেস সহ MT ডেটা বিচ্ছিন্নতা ✅উচ্চ ❌ সর্বনিম্ন ✅উচ্চ ✅উচ্চ ভুলবশত ডেটা ফাঁস হওয়ার ঝুঁকি ✅ কম ❌উচ্চ ✅ কম ✅ কম অবকাঠামো খরচ ❌প্রতিটি ভাড়াটিয়ার সাথে উচ্চতর ✅নিম্ন ✅নিম্ন ✅❌ একক ভাড়াটে থেকে কম স্থাপনার গতি ❌প্রতিটি ভাড়াটিয়ার সাথে কম ✅ ✅❌ মাইগ্রেশন ধীর হবে কারণ সেগুলি প্রতিটি স্কিমার জন্য কার্যকর করা প্রয়োজন৷ ✅❌ মাইগ্রেশন ধীর হবে কারণ সেগুলি প্রতিটি ডাটাবেসের জন্য কার্যকর করা প্রয়োজন৷ বাস্তবায়ন সহজ ✅ ❌ যদি পরিষেবাটি ইতিমধ্যে একটি একক ভাড়াটে অ্যাপ হিসাবে প্রয়োগ করা হয় তবে অনেক পরিবর্তনের প্রয়োজন৷ ✅ ✅ উপসংহার উপরের সমস্তগুলিকে সংক্ষিপ্ত করার জন্য, মনে হচ্ছে সমস্যাটির জন্য কোনও সিলভার বুলেট নেই, প্রতিটি পদ্ধতিরই তার সুবিধা এবং অসুবিধা রয়েছে, তাই এটি বিকাশকারীদের উপর নির্ভর করে যে তারা কী ট্রেড-অফ করতে পারে তা নির্ধারণ করা। পৃথক ডাটাবেস ভাড়াটেদের ডেটার জন্য সর্বোত্তম বিচ্ছিন্নতা প্রদান করে এবং প্রয়োগ করা সহজ, তবে, এটি রক্ষণাবেক্ষণের জন্য আপনার বেশি খরচ করে: n ডেটাবেস আপডেট করতে, ডেটাবেস সংযোগের সংখ্যা বেশি। বাস্তবায়নের জন্য একটি পৃথক স্কিমা বিট জটিল সহ একটি ভাগ করা ডাটাবেস এবং মাইগ্রেশনের সাথে কিছু সমস্যা হতে পারে। একক ভাড়াটে বাস্তবায়ন করা সবচেয়ে সহজ, কিন্তু আপনার কাছে প্রতি ভাড়াটে আপনার পরিষেবার সম্পূর্ণ অনুলিপি থাকায় সম্পদের অতিরিক্ত খরচের জন্য এটি আপনাকে খরচ করে।