১০০ কোটির বেশি ChatGPT ব্যবহারকারীর জন্য অনলাইন সংরক্ষণের দ্রুত সম্প্রসারণ (দ্বিতীয় পর্ব)
অভূতপূর্ব বৃদ্ধি সামলাতে আমাদের অ্যাপ্লিকেশন সংরক্ষণ প্ল্যাটফর্ম Habitat-এ কীভাবে Azure Cosmos DB উন্নত করেছি.
OpenAI-এর সব পণ্যে দ্রুত ও নির্ভরযোগ্যভাবে ডেটা পাওয়া দরকার. আমাদের সংরক্ষণ প্ল্যাটফর্ম Habitat সেই সুবিধা দেয়. ৪০টি ভৌগোলিক অঞ্চলে ১০০ কোটির বেশি ব্যবহারকারীকে মিলিসেকেন্ডের মধ্যে সাড়া দিতে হয় একে. আমাদের অবকাঠামোর সামনে ছিল অসাধারণ এক চ্যালেঞ্জ: বিপুল গতির বৃদ্ধি ও নতুন ব্যবহার সামলানোর পাশাপাশি নির্ভরযোগ্যতা, কর্মক্ষমতা এবং পণ্য উন্নয়নের গতি বাড়িয়ে যাওয়া. এই চ্যালেঞ্জ সমাধানে আমাদের অনলাইন সংরক্ষণ প্ল্যাটফর্মের নকশা ও পরিচালনাপদ্ধতি নতুন করে ভাবতে হয়েছে. আমরা সব সময় সুবিধা-অসুবিধা যাচাই করেছি এই ক্রমে: আগে অত্যাবশ্যক পণ্যের অনুরোধ সামলানোর মতো নির্ভরযোগ্যতা, তারপর বিশ্বব্যাপী ব্যবহারকারীদের জন্য যথেষ্ট গতি, সবশেষে বিশাল পরিসরে দক্ষ পরিচালনা.
দুই পর্বের এই ধারাবাহিকে ব্যাখ্যা করা হয়েছে, কীভাবে একটি সাধারণ ক্লায়েন্ট লাইব্রেরি ও ডেটাবেস থেকে Habitat-কে বিশ্বজুড়ে বিস্তৃত সংরক্ষণ প্ল্যাটফর্মে রূপ দিয়েছি, যা ৫০০ পেটাবাইটের বেশি ডেটা সরবরাহ করে. প্রথম পর্বে Python ক্লায়েন্ট থেকে সেবায় Habitat-এর বিবর্তন তুলে ধরা হয়েছে. সেখানে এমন কৌশলও আলোচনা করা হয়েছে, যেগুলোর সাহায্যে Python-ভিত্তিক একটি সেবাকে অনেকের ধারণার বাস্তবসীমার বহু দূর পর্যন্ত নিয়ে যেতে পেরেছি.
এই দ্বিতীয় পর্বে আমরা দেখাব, কীভাবে এর অন্তর্নিহিত সংরক্ষণ উপাদান Azure Cosmos DB-এর সক্ষমতা বাড়িয়েছি. Azure দলের সঙ্গে ঘনিষ্ঠভাবে কাজ করে আমরা যৌথভাবে পরিচালিত কনটেইনারে একটি কার্যকর বহু-ভাড়াটে পদ্ধতি গড়েছি, যা বিশ্বব্যাপী বিশাল পরিসরে ডেটা পড়ার চমৎকার কর্মক্ষমতা দেয়.
চিত্র 01 · Habitat কী?
অনলাইন স্টোরেজ প্ল্যাটফর্ম
OpenAI-এর পণ্যগুলো যাতে প্রয়োজনীয় তথ্য দ্রুত ও নির্ভরযোগ্যভাবে অ্যাক্সেস করতে পারে, সেজন্য আমরা যে অনলাইন স্টোরেজ প্ল্যাটফর্মটি তৈরি করেছি তা-ই হলো Habitat.
- অনুরোধ
- রেসপন্স
- পরিবর্তন (CDC)
প্রতিষ্ঠানের পরিসর বাড়লে অবকাঠামো দলগুলো প্রায়ই একক ভাড়াটে ব্যবস্থা থেকে বহু-ভাড়াটে ব্যবস্থা পরিচালনার দিকে এগোয়. একক ভাড়াটে ব্যবস্থায় পণ্যের প্রতিটি অংশের দল নিজস্ব ব্যবস্থা রক্ষণাবেক্ষণ করে. এতে সমস্যার প্রভাব সীমিত থাকে, দায়িত্বের সীমানা স্পষ্ট হয় এবং কাজের চাপ আলাদা রাখা সহজ হয়. দল ও পণ্যের পরিধি বাড়লে এটি চালানো ব্যয়বহুল হয়ে ওঠে. একক ভাড়াটে ব্যবস্থায় প্রতিটি পণ্য উন্নয়ন দলকে সক্ষমতার পরিকল্পনা করতে হয়. এর ফলে প্রায়ই প্রয়োজনের তুলনায় অনেক বেশি সম্পদ বরাদ্দ হয়.
অন্যদিকে বহু-ভাড়াটে ব্যবস্থায় নিয়ন্ত্রণ থাকে একটি কেন্দ্রীয় ডেটাবেস দলের হাতে, যাদের সম্পদ বরাদ্দের জ্ঞান ও অভিজ্ঞতা বেশি. তবে বহু-ভাড়াটে ব্যবস্থার নিজস্ব সমস্যাও আছে. যেমন, কোনো ভাড়াটে অস্বাভাবিক বেশি সম্পদ ব্যবহার করে অন্যদের ক্ষতি করতে পারে—এটাই অতিরিক্ত সম্পদ ব্যবহারকারী প্রতিবেশীর সমস্যা.
Habitat-এর জন্য বড় পরিসরে নির্ভরযোগ্য ও সাশ্রয়ী সংরক্ষণ ব্যবস্থা নকশা করতে আমাদের এই সব সুবিধা-অসুবিধা বিবেচনা করতে হয়েছে. আজ Habitat বহু OpenAI পণ্যের জন্য একটি বহু-ভাড়াটে ডেটাবেস স্তর. তবে আমরা একটি চক্র ঘুরে এসেছি: প্রথমে একটি বহু-ভাড়াটে Azure Cosmos DB কনটেইনার, তারপর পেছনে একক ভাড়াটে কনটেইনার বরাদ্দ, শেষে আবার সাধারণ ব্যবহারের জন্য বহু-ভাড়াটে কনটেইনারে ফেরা. Habitat-এর বহু-ভাড়াটে ব্যবস্থা নিয়ে আমাদের যাত্রা এখনও প্রাথমিক পর্যায়ে. আমরা নানা ধরনের ব্যবহার সমর্থন করি, তবে যেখানে সম্ভব Azure Cosmos DB-এর অন্তর্নির্মিত মৌলিক সুবিধা কাজে লাগিয়ে এ ক্ষেত্রে বিনিয়োগ পিছিয়ে দিতে পেরেছি.
Azure Cosmos DB নিয়ে আমাদের যাত্রায় যাওয়ার আগে কিছু প্রাথমিক তথ্য:
একটি Azure Cosmos DB অ্যাকাউন্ট একগুচ্ছ কনটেইনার ও প্রতিলিপি তৈরির নীতি নির্ধারণ করে
প্রতি কনটেইনারে সেকেন্ডপ্রতি অনুরোধ একক (RU/s) হিসেবে নির্দিষ্ট পরিমাণ থ্রুপুট বরাদ্দ করা হয়
প্রতিটি কনটেইনারে নির্দিষ্ট যৌক্তিক পার্টিশন কী অনুযায়ী ডেটা খণ্ডে ভাগ করে রাখা হয়. প্রতি যৌক্তিক পার্টিশন কী-এর সংরক্ষণ ও থ্রুপুটের সীমা নথিতে নির্ধারিত থাকে
Azure Cosmos DB কমসংখ্যক অন্তর্নিহিত ভৌত পার্টিশনে যৌক্তিক পার্টিশন কী-গুলো বণ্টন করে. সংরক্ষিত ডেটা নির্দিষ্ট সীমা ছাড়ালে বা বরাদ্দকৃত থ্রুপুট বজায় রাখতে আরও ভৌত পার্টিশন দরকার হলে সেগুলো একাধিক ভৌত পার্টিশনে ভাগ করে
শুরুতে ক্লায়েন্টের যেকোনো পরিমাণ অনুরোধ আমরা গ্রহণ করতাম. অতিরিক্ত চাপ ঠেকাতে প্রতি যৌক্তিক পার্টিশন কী-এর জন্য ঘোষিত ১০ হাজার RU/s সীমার ওপর নির্ভর করতাম. শুরুতে প্রতি অ্যাকাউন্টে কেবল একটি পূর্বনির্ধারিত Azure Cosmos DB কনটেইনারও ব্যবহার করতাম. এটি মোটামুটি ভালো চললেও কয়েকটি কারণে সমস্যা দেখা দেয়:
শুরুর দিকের API নকশার সিদ্ধান্তের কারণে আমরা ক্লায়েন্টদের সরাসরি যৌক্তিক পার্টিশন কী বেছে নিতে দিয়েছিলাম. ফলে ভিন্ন পণ্যের ব্যবহারে user_id বা workspace_id-এর মতো বহুল ব্যবহৃত পার্টিশন কী প্রায়ই মিলে যায়. এসব কাজ একই যৌক্তিক পার্টিশন কী-এর Azure Cosmos DB সীমা ভাগ করে নেওয়ায় এই নকশা নির্দিষ্ট ব্যবহারকারীর মোট থ্রুপুট সীমিত করে দেয়.
Habitat ও Azure Cosmos DB-তে যাওয়ার আগে Postgres-এর সক্ষমতা বাড়াতে গিয়ে আমরা একটি সাধারণ সমস্যায় পড়তাম: অতিরিক্ত ব্যবহৃত কোনো প্রতিষ্ঠান বা কী থেকে আসা বিপুল অনুরোধ পুরো ডেটাবেস অচল করে দিতে পারত. অর্থাৎ এক ভাড়াটেই অসামঞ্জস্যপূর্ণ বেশি চাপ তৈরি করত. সেই কী-গুলো ক্যাশে রাখা এবং ক্যাশে না পাওয়ার ক্ষেত্রে লিজের ব্যবস্থা করতে সবাই মিলে যথেষ্ট শ্রম দিয়েছি, যাতে ক্যাশে অনুপস্থিত ডেটা আনার চাপ অন্তর্নিহিত ডেটাবেসকে বিপর্যস্ত না করে.
Figure 02a · Logical partition key limits
Different clients, the same partition key
নথিতে ডেটার আকার ও থ্রুপুটের সীমা যৌক্তিক পার্টিশন কী-এর জন্য প্রযোজ্য হলেও বাস্তবে সীমা কার্যকর করা হয় ভৌত পার্টিশনে. এর ফলে বাস্তবে যৌক্তিক পার্টিশনগুলো ১০,০০০ RU/s-এ পৌঁছাতে পারে না. বরং একই ভৌত পার্টিশনে থাকা অন্য সব যৌক্তিক পার্টিশন কী-এর সঙ্গে সেই ভৌত পার্টিশনের সীমা ভাগ করে নিতে হয়.
ফলে অতিরিক্ত সম্পদ ব্যবহারকারী প্রতিবেশীরা সম্পর্কহীন অনেক যৌক্তিক পার্টিশন কী-কে প্রভাবিত করত. অল্প ব্যবহৃত পণ্যসুবিধার ডেটা নিয়ে কাজ করতে গিয়েও মূল লগইন ও নিবন্ধন প্রক্রিয়া ব্যাহত হতো.
Figure 02b · Noisy neighbors
Different users, the same physical partition
নির্দিষ্ট ভৌত পার্টিশনের থ্রুপুট সীমাও পরিবর্তনশীল. এটি Azure Cosmos DB কনটেইনারে বরাদ্দ করা মোট থ্রুপুটের ওপর নির্ভর করে. কনটেইনারের বরাদ্দকৃত থ্রুপুট তার ভৌত পার্টিশনগুলোর মধ্যে মোটামুটি সমানভাবে ভাগ হয়.
ডেটা বাড়লে ভৌত পার্টিশনগুলো ভাগ হয়, ফলে মোট পার্টিশনের সংখ্যা বাড়ে, কিন্তু বরাদ্দকৃত মোট থ্রুপুট অপরিবর্তিত থাকে. ফলে ডেটার আকার বাড়ার সঙ্গে সঙ্গে প্রতি পার্টিশনের কার্যকর থ্রুপুট সীমা কমতে থাকে.
আমাদের যেসব কাজে ব্লবের মতো বিপুল ডেটা সংরক্ষণ করতে হয়, সেখানে এ থেকে সমস্যা তৈরি হয়: অনুরোধের হার ও ব্যবহার স্থির থাকলেও শুধু সংরক্ষিত ডেটা বাড়ার কারণে চলমান কাজের জন্য থ্রুপুট সক্ষমতা কমে যায়.
Figure 02C · Weak partitions
The limit falls below demand
A partition splits when it reaches its storage limit. Each child receives half the throughput capacity.
আলাদা কনটেইনার ব্যবহার করলে পার্টিশন কী-এর সীমা ও অতিরিক্ত সম্পদ ব্যবহারকারী প্রতিবেশীর সমস্যা আংশিকভাবে সমাধান হয়. এভাবে প্রতিটি কনটেইনারকে নিজস্ব স্বতন্ত্র ভৌত পার্টিশন দেওয়া যায়. তখন শুধু সেই কনটেইনারের কাজগুলোর মধ্যেই অতিরিক্ত সম্পদ ব্যবহারের সমস্যা বা পার্টিশন কী মিলে যাওয়ার ঘটনা ঘটতে পারে. অন্যদিকে নতুন কনটেইনার প্রস্তুত করতে বাড়তি কাজ লাগে—প্রতিটির সক্ষমতার জন্য আলাদা পরিকল্পনা দরকার. তাই আমরা কেবল যৌক্তিকভাবে আলাদা সেবা বা ব্যবহারের ক্ষেত্রেই নতুন কনটেইনার তৈরি করতে চাই.
সম্পদ কঠোরভাবে আলাদা রাখা দরকার এমন সবচেয়ে গুরুত্বপূর্ণ নতুন কাজগুলোর জন্য আমরা পৃথক Azure Cosmos DB কনটেইনার ব্যবহার শুরু করি. পাশাপাশি দুর্বল পার্টিশন সামলাতে একটি স্ক্রিপ্ট ব্যবহার করি, যা প্রতিটি কনটেইনারের মোট বরাদ্দকৃত থ্রুপুটকে তার ভৌত পার্টিশনের সংখ্যার সঙ্গে সামঞ্জস্যপূর্ণ রাখে. এতে আগের প্রায় সব সমস্যাই এড়ানো গেছে.
তবে শুরুতে একটি পূর্বনির্ধারিত কনটেইনার ব্যবহার করায় পুরোনো অনেক গুরুত্বপূর্ণ কাজ দুর্ভাগ্যবশত সেখানেই আটকে ছিল; সেগুলো সরাতে ডেটা স্থানান্তর দরকার ছিল. যৌথভাবে ব্যবহৃত পূর্বনির্ধারিত কনটেইনারের ডেটার ওপর তখনও নির্ভরশীল গুরুত্বপূর্ণ সেবাগুলোকে সুরক্ষিত রাখতে আমরা প্রায়ই দলগুলোকে নতুন সেবা বা বড় পণ্যসুবিধার জন্য আলাদা কনটেইনার তৈরির পরামর্শ দিতাম. আমাদের পরিসর বাড়ার সঙ্গে সঙ্গে পূর্বনির্ধারিত কনটেইনারের চাপ ও চালু সেবায় সমস্যার ঘটনাও বাড়তে থাকে. শুধু পূর্বনির্ধারিত কনটেইনারকে বাড়তি চাপ থেকে রক্ষা করতেই আমরা যেকোনো নতুন সেবা বা বড় পণ্যসুবিধার জন্য কনটেইনার বরাদ্দ শুরু করি.
এতে পুরো সাইট বন্ধ হয়ে যাওয়ার অনেক ঘটনা এড়ানো গেছে; ক্ষতি সীমিত থেকেছে নির্দিষ্ট সুবিধা বা সেবার মান অবনতির মধ্যে. তবে শেষ পর্যন্ত নতুন কনটেইনার প্রস্তুতের বাড়তি কাজই আমাদের জন্য সমস্যা হয়ে দাঁড়ায়:
পুরোনো যৌথ পূর্বনির্ধারিত কনটেইনারে কোনো নতুন কাজের অনুরোধের হার ০ থেকে প্রতি সেকেন্ডে ১০ লাখে পৌঁছালেও মোট ব্যবহারে উল্লেখযোগ্য পরিবর্তন হওয়ার সম্ভাবনা কম ছিল. কিন্তু পৃথক কনটেইনারে নতুন কোনো কাজের হার প্রতি সেকেন্ডে ০ থেকে ১০ লাখ অনুরোধে পৌঁছালে তা কেবল অভ্যন্তরীণ পরীক্ষামূলক ব্যবহারের প্রাথমিক চাপের তুলনায় ১,০০০ গুণ বেশি হতে পারত.
স্বতন্ত্র কনটেইনার ব্যবহারের কারণে দলগুলোকে এখন মনে করে নতুন পণ্য চালুর প্রত্যাশিত থ্রুপুট অনুযায়ী আগে থেকেই কনটেইনারের সক্ষমতা বরাদ্দ করতে হতো. পণ্য উন্নয়ন দলগুলো প্রায়ই সুবিধা চালু করার আগে সক্ষমতা বাড়াতে ভুলে যেত. ফলে চালুর দিন আমাদের জরুরি সমস্যা মোকাবিলার কক্ষে বসে শেষ মুহূর্তে কনটেইনারের সক্ষমতা বাড়ানোর চেষ্টা করতে হতো.
বিভিন্ন কাজের চাপ একসঙ্গে মেলানো বহু-ভাড়াটে ব্যবস্থার একটি মূল সুবিধা. কনটেইনারের এই কৌশলে কাজগুলো আরও ভালোভাবে আলাদা রাখতে গিয়ে আমরা সেই সুবিধা হারাই.
Figure 03 · Lack of stable aggregate growth
The same workload, different headroom
1K RU/s during load testing → 1M RU/s at launch
সময়ের সঙ্গে স্বতন্ত্র কনটেইনারের ব্যবহার পর্যবেক্ষণ করতেও পণ্য সম্পর্কে গভীর জ্ঞানের প্রয়োজন হয়—কখন অনুরোধের ধরন বদলাবে বা পরিমাণ বাড়বে, তা জানতে হতো.
বৃদ্ধির প্রবণতা অনুযায়ী প্রতিটি কনটেইনারের বরাদ্দকৃত থ্রুপুট বাড়ানোর একটি সাধারণ নিয়ন্ত্রণ স্ক্রিপ্ট আমরা দিতে পারি. কিন্তু মোট বৃদ্ধির স্থিতিশীলতা না থাকায় সঠিকভাবে সক্ষমতা বাড়াতে কার্যত OpenAI-এর প্রতিটি পণ্য উন্নয়ন দলকেই সক্ষমতার পরিকল্পনায় যুক্ত হতে হয়.
সাংগঠনিক পরিসর বাড়ার সঙ্গে এই পদ্ধতি টেকেনি. কারণ প্রতিটি সেবার দায়িত্বপ্রাপ্ত দল Azure Cosmos DB-এর সম্পদ বরাদ্দে কতটা যত্ন নিচ্ছে, তাতে ব্যাপক পার্থক্য ছিল.
প্রতিষ্ঠান বড় হওয়ার সঙ্গে সঙ্গে পরিচালনার এসব সমস্যা সামলানো কঠিন হয়ে ওঠে. পরিকল্পনার জন্য একক কেন্দ্রীয় দল না থাকায় অনেক দলের পরিকল্পনাই দুর্বল হয়. ফলে আমরা আবার বহু-ভাড়াটে সমাধানের দিকে ফিরি. Azure দলের সঙ্গে ঘনিষ্ঠভাবে কাজ করে যৌথ ভাড়াটে নকশায় আগের সমস্যাগুলোর প্রযুক্তিগত সমাধান তৈরি করি:
সবচেয়ে বেশি ব্যবহৃত কী-গুলোর অনুরোধ আগে সীমিত করলে অতিরিক্ত সম্পদ ব্যবহারকারী প্রতিবেশীরা কোনো ভৌত পার্টিশনের সব থ্রুপুট দখল করতে পারে না. এতে প্রতিবেশীর প্রভাব কমে, যেখানে একটি অতিব্যবহৃত কী-ই পুরো সাইটকে ক্ষতিগ্রস্ত করতে পারে.
অনুরোধকে স্তরে ভাগ করা QoS একইভাবে অফলাইন কাজকে—যেমন একসঙ্গে বিপুল ডেটা যোগ করা বা বের করে আনা—কোনো ভৌত পার্টিশনের সব থ্রুপুট ব্যবহার করা থেকে আটকায়. এসব কাজের অনুরোধকে কম অগ্রাধিকার দেওয়ায় আগে সেগুলোর হার সীমিত হয়. ফলে বেশি অগ্রাধিকারের, সরাসরি ব্যবহারকারীকে সেবা দেওয়া তাৎক্ষণিক অনুরোধ সীমিত করার দরকার পড়ে না.
Azure Cosmos DB-তে আগে থেকেই সার্ভারবিহীন মোড ছিল, যা পূর্ববরাদ্দকৃত মোডে আমাদের দুর্বল পার্টিশনের সমস্যাটি সমাধান করতে পারত. তবে বড় অসুবিধা ছিল: এটি শুধু সংরক্ষণ ব্যবহারের ভিত্তিতে সক্ষমতা বাড়াত এবং প্রতি ভৌত পার্টিশনে RU ব্যবহার ৫ হাজার RU/s-এ সীমিত রাখত. এতে দুর্বল পার্টিশনের সমস্যা মিটলেও বেশি RU লাগে এমন কাজের সক্ষমতা বাড়ানো যেত না.
Azure Cosmos DB দল আমাদের জন্য উন্নত একটি সার্ভারবিহীন মোড তৈরি করে. এতে প্রতিটি ভৌত পার্টিশন ১০ হাজার RU/s পর্যন্ত বাড়তে পারে এবং সংরক্ষণ ব্যবহারের পাশাপাশি RU ব্যবহারের ভিত্তিতেও ভাগ হয়. ফলে হাতে করে কনটেইনার পর্যবেক্ষণ ও সক্ষমতা বাড়ানো বন্ধ করতে পেরেছি.
এসব পরিবর্তনের ফলে আমরা আবার একটি যৌথ কনটেইনার ব্যবহারে ফিরতে পেরেছি. কাজগুলোর পৃথকতা বজায় রেখেই পণ্য উন্নয়ন দলগুলোর আগাম বা নিয়মিত সক্ষমতার পরিকল্পনার প্রয়োজন অনেক সহজ হয়েছে. পণ্য উন্নয়নের গতি বাড়লেও এরপরের কয়েক মাসে সম্পদ বরাদ্দ বা অতিরিক্ত সম্পদ ব্যবহারকারী প্রতিবেশীজনিত কোনো ঘটনা ঘটেনি.
প্রতিষ্ঠান OpenAI-এর আকারে পৌঁছালে পরিচালিত সেবা আর পুরোপুরি “পরিচালিত” থাকে না. অনেক কাজের চাপই ক্লাউড সরবরাহকারীর অবকাঠামোর সাধারণ ব্যবহার থেকে ব্যতিক্রম হয়ে ওঠে. OpenAI যখন Azure Cosmos DB-এর অন্যতম বৃহত্তম ব্যবহারকারী হয়ে ওঠে, তখন সফল পরিচালনার জন্য ভিন্ন পদ্ধতি দরকার হয়: যৌথ পরীক্ষা, যৌথ পর্যবেক্ষণপট, প্রকৌশলীদের সরাসরি যোগাযোগ এবং শুধু আমাদের পরিসরে দেখা দেওয়া ব্যর্থতাগুলোর যৌথ দায়িত্ব. আজ আমাদের বৃহত্তম Azure Cosmos DB অ্যাকাউন্টে কয়েক দশ পেটাবাইট ডেটা রয়েছে এবং এটি প্রতি সেকেন্ডে ২ কোটির বেশি অনুরোধ পূরণ করে. আমাদের জানা মতে, আমরাই একমাত্র প্রতিষ্ঠান যারা এই পরিসরে Azure Cosmos DB ব্যবহার করছে.
২০২৪ সালের শেষ দিকে একটি আঞ্চলিক সেবাবিভ্রাট দেখিয়ে দেয়, কেন এই সহযোগিতা জরুরি. তখন আমাদের বৃহত্তম Azure Cosmos DB অ্যাকাউন্টগুলোর একটির প্রধান Azure অঞ্চলে বিদ্যুৎবিভ্রাট ঘটে. এরপর বিকল্প অঞ্চলে সেবা স্থানান্তর করতে গিয়ে বুঝি, আমাদের সবচেয়ে বড় অ্যাকাউন্টগুলো স্থানান্তরে কয়েক ঘণ্টা লাগবে. আমাদের দল বা Azure Cosmos DB দল—কেউই আমাদের পরিসরে এটি পরীক্ষা করেনি.
প্রায় এক মাস পরে অ্যাকাউন্টগুলোকে মূল অঞ্চলে ফিরিয়ে আনার সময় আমাদের কার্যক্রমে আরেকটি গুরুতর সেবাবিভ্রাট ঘটে. একসঙ্গে বিপুল সংযোগের ঢল মূল অঞ্চলের Azure Cosmos DB গেটওয়েকে বিপর্যস্ত করে. গেটওয়ে মোডের Azure Cosmos DB ক্লায়েন্টের সেবা স্থানান্তর সামলানোর একটি অস্বাভাবিক আচরণের কারণে সব ক্লায়েন্ট সঙ্গে সঙ্গে মূল অঞ্চলে সংযোগ করে অনুরোধ পাঠাতে শুরু করে. অথচ তখন ভৌত পার্টিশনগুলোর কেবল একটি অংশ ওই অঞ্চলে ফিরেছিল.
প্রতি বিভ্রাটেই OpenAI ও Azure নিজেদের সমস্যা ব্যবস্থাপনার প্রক্রিয়া অনুসরণ করেছে, বেশ কিছু মূল কারণ শনাক্ত করেছে এবং সমাধান কার্যকর করেছে. তবে এসব বিভ্রাট ছিল আমাদের দল ও Azure Cosmos DB দলের পরিচালনা ও পরীক্ষাপদ্ধতির মধ্যে আরও বড় পদ্ধতিগত সমস্যার লক্ষণ. শুরুতে পরিচালিত সেবা ব্যবহারের ফলে আমরা দ্রুত এগোতে ও ব্যবসায়িক লক্ষ্যে মনোযোগ দিতে পেরেছি. বড় পরিসরে পরিচালিত সেবা আর ততটা স্বয়ংসম্পূর্ণ থাকে না. তখন নকশা থেকে পরিচালনা পর্যন্ত প্রতিটি স্তরে সেবা সরবরাহকারীর সঙ্গে গভীর সমন্বয় দরকার হয়.
আজ Habitat ও Azure-এর প্রকৌশল দল যৌথভাবে Habitat-এর প্রতিটি স্তর পর্যবেক্ষণ করে—আমাদের সেবা স্তর থেকে Azure Cosmos DB-এর ভৌত সংরক্ষণ স্তর পর্যন্ত. আমরা বাস্তব সেবার সমান আকারের, কিন্তু সরাসরি সেবায় ব্যবহৃত নয় এমন একটি Azure Cosmos DB অ্যাকাউন্টে কার্যক্রম চালাই ও পরিবর্তন পরীক্ষা করি. আমরা একসঙ্গে SDK পরীক্ষা ও উন্নত করি এবং Azure Cosmos DB অ্যাকাউন্টের আকার ও সক্ষমতা বাড়ানোর সেরা পদ্ধতি নির্ধারণ করি. Teams-এর মাধ্যমে আমাদের প্রকৌশলীরা সরাসরি একে অন্যের সঙ্গে যোগাযোগ করেন. এমনকি সহায়তার বিভিন্ন স্তর পেরোনো ছাড়াই একে অন্যকে সরাসরি জরুরি বার্তা পাঠানোর ব্যবস্থাও করেছি.
গত বছরে Azure Cosmos DB-এর নিয়ন্ত্রণ স্তর ও গেটওয়ের সম্প্রসারণক্ষমতা উন্নত করতে ব্যাপক যৌথ কাজ হয়েছে. মেটাডেটা পার্টিশন সুরক্ষিত রাখতে গেটওয়েতে অতিরিক্ত চাপ প্রতিরোধ ও বিভিন্ন Azure Cosmos DB মেটাডেটা ক্যাশে রাখার ব্যবস্থা যোগ করা হয়েছে. সংযোগ পুল ও সংযোগের পুনর্ব্যবহার বাড়িয়ে আমাদের Python habitat-service প্রসেসগুলোর চাপ কমানো হয়েছে. সম্ভব হলে কাজগুলো একই স্থানে রাখা হয়েছে এবং ভিন্ন VPC ব্যবহার করে গুরুত্বপূর্ণ কাজগুলোকে অফলাইন কাজ থেকে আলাদা করা হয়েছে.
গত বছরে আমাদের Azure Cosmos DB স্থিতিশীল রাখতে এই ঘনিষ্ঠ যৌথ প্রকৌশল কার্যক্রম অপরিহার্য ছিল. যথেষ্ট বড় বা গুরুত্বপূর্ণ যেকোনো ব্যবস্থাতেই এমন দলগত কাজ দরকার: দায়িত্বের গণ্ডি ভেঙে সাংগঠনিক সীমানা পেরিয়ে একসঙ্গে কাজ করা.
প্রথম পর্বে যেমন বলেছি, আমাদের মূল দর্শন হলো: আগে কার্যকর করুন, তারপর দ্রুত করুন, শেষে সাশ্রয়ী করুন. আগে নির্ভরযোগ্যতা, তারপর কর্মক্ষমতা, শেষে সম্পদের সাশ্রয়ী ব্যবহার. Habitat তখন OpenAI-এর অপরিহার্য অবকাঠামো হয়ে উঠেছিল, তাই প্রথম অগ্রাধিকার ছিল একে নির্ভরযোগ্য করা. ২০২৫ সালে ব্যবস্থাটি স্থিতিশীল হওয়ার এবং OpenAI বিশ্বব্যাপী বিস্তৃত হওয়ার পর ব্যবহারকারী ও পণ্য উন্নয়ন দলগুলোর জন্য পরবর্তী বাধা হয়ে ওঠে সাড়া পেতে দেরি.
গণনা ও সংরক্ষণ সক্ষমতা প্রায়ই ভিন্ন অঞ্চলে থাকত, ফলে অঞ্চলগুলোর মধ্যে অনুরোধ পাঠানো অনিবার্য ছিল.
Figure 04 · Improving performance at a global scale
Global traffic
Compute and storage capacity were often located in different regions, making cross-region requests unavoidable.
গণনা ও সংরক্ষণ ব্যবস্থার ভৌগোলিক অবস্থানগুলো কেবল বোঝানোর জন্য দেখানো হয়েছে.
ডেটা কোথায় সংরক্ষিত এবং অনুরোধ কোথা থেকে পূরণ করা হচ্ছে, তার ওপর ভিত্তি করে সাড়া দেওয়ার সময়ে বড় পার্থক্য হতো. Habitat-এর অনুরোধ দ্রুত সম্পন্ন করতে পণ্য উন্নয়নকারীরা ক্লায়েন্টের দিকে বাড়তি ক্যাশে ব্যবহার, একসঙ্গে গুচ্ছ অনুরোধ পাঠানো, ডেটাবেসে পড়া ও লেখা কমানো এবং সম্ভব হলে জরুরি প্রক্রিয়াক্রমের বাইরে কাজ সরিয়ে নেওয়ার ওপর নির্ভর করতেন. এতে ডেটাবেসের সমস্যা ভালোভাবে সামলাতে পারে এমন কিছু আকর্ষণীয় পণ্য নকশা তৈরি হয়েছিল. তবে পণ্যগুলো আরও জটিল হয়ে পড়ে এবং উন্নয়নের গতি কমে যায়. অথচ Habitat-এর লক্ষ্যই ছিল ডেটাবেসের খুঁটিনাটি না জেনে দ্রুত পণ্য তৈরি করা.
২০২৬ সালে আমরা এ বিষয়ে বিশেষ মনোযোগ দিয়েছি. Habitat-এর ৯০%-এর বেশি অনুরোধই ডেটা পড়ার জন্য, তাই পড়ার কর্মক্ষমতা বাড়াতে আমরা কয়েক স্তরের কৌশল তৈরি করেছি:
ডাটা রেসিডেন্সির শর্ত আছে এমন ব্যবহারকারীদের জন্য বিশ্বজুড়ে Azure-এর বিভিন্ন অঞ্চলে আমাদের একাধিক Azure Cosmos DB অ্যাকাউন্ট আছে. ডাটা রেসিডেন্সির কঠোর শর্ত না থাকলেও ব্যবহারকারীর কাছাকাছি ডেটা রাখলে সাড়া দিতে সময় কম লাগে, ফলে অভিজ্ঞতা উন্নত হয়.
বাস্তবে ডাটা রেসিডেন্সির প্রয়োজনের বাইরে আমরা ব্যাপকভাবে এটি করতে পারি না, কারণ ডেটা কোথায় রাখা যাবে তা ক্লাউডের ভৌত সক্ষমতার ওপর নির্ভরশীল. আমাদের ডেটাসেট এত বড় যে ব্যবহারকারীর অনুরোধে নিজ নিজ অংশের অনুপাতে প্রয়োজনীয় বিপুল সংরক্ষণ সক্ষমতা অনেক অঞ্চলেই নেই.
ডেটাসেন্টারের সক্ষমতা, বিদ্যুৎ বা শীতলীকরণের সীমাবদ্ধতা থাকা অঞ্চলে কখনো সরাসরি বেছে নিতে হয়: কাছাকাছি ডেটা রেখে Habitat-এর সাড়া দেওয়ার সময় কমাব, নাকি সেই সক্ষমতা বাড়তি গণনার কাজে ব্যবহার করে সংরক্ষণের অনুরোধ দূরে পাঠাব.
তাই ডেটার অবস্থান নির্ধারণে প্রায়ই দুটি দিকের মধ্যে সমন্বয় করতে হয়: ক) বিভিন্ন পণ্য ও ব্যবহারকারী গোষ্ঠীর সাড়া পাওয়ার সময় কমানো এবং খ) উপলব্ধ সংরক্ষণ ও গণনা সক্ষমতা.
প্রতি অনুরোধে দরকার হয় এমন পরিচয় যাচাইয়ের মেটাডেটার মতো কাজে বিলম্ব ন্যূনতম রাখা জরুরি. এসব ক্ষেত্রে বহু সহায়ক অঞ্চলে প্রতিলিপি রাখা Azure Cosmos DB অ্যাকাউন্ট ব্যবহার করে গণনা ব্যবস্থা ও Habitat-এর মধ্যে অনুরোধ যাওয়া-আসার সময় কমাই. কিছু অ্যাকাউন্ট থেকে আমরা যে ৪০টি Azure অঞ্চলে অনুরোধ পূরণ করি, তার সবগুলোতেই প্রতিলিপি রাখা হয়. অন্যগুলো থেকে প্রতি মহাদেশের অন্তত একটি অঞ্চলে প্রতিলিপি রাখা হয়.
প্রতিলিপির ভিন্ন বিন্যাস থাকা অ্যাকাউন্টগুলোর মধ্যে ডেটাসেট সরাতে আমাদের পরিকল্পনার আগেই Habitat-এ একটি ডেটা স্থানান্তর ও অনুরোধ পাঠানোর স্তর তৈরি করতে হয়েছে, যার কাজ ব্যবহারকারীর আড়ালেই চলে.
তবে শেষ পর্যন্ত এই পদ্ধতিও সক্ষমতার সীমায় আবদ্ধ, তাই এটি বাছাই করা অল্প কিছু ডেটাসেটেই ব্যবহার করা হয়.
Habitat-এর অধিকাংশ কাজই ডেটা পড়াকেন্দ্রিক. অ্যাপ্লিকেশনগুলো ক্রমাগত সেটিংস, অবস্থা ও অন্যান্য বৈশিষ্ট্য নিয়ে আসে. ঘন ঘন ব্যবহৃত অল্প কিছু ধরনের ডেটা থেকেই অনুরোধের একটি অসামঞ্জস্যপূর্ণ বড় অংশ আসে. তাই ব্যবস্থাটি বিতরণকৃত ক্যাশের জন্য বিশেষভাবে উপযোগী. একটি অঞ্চলের অবকাঠামোতে ক্যাশে কর্মক্ষমতা বাড়ায়. একাধিক অঞ্চলে কাজ করলে এর সুফল আরও বাড়ে, কারণ অঞ্চলগুলোর মধ্যকার বিলম্ব “আড়াল” করতে ক্যাশে ব্যবহার করা যায়.
আমরা Habitat-এ একটি বিতরণকৃত পার্শ্ববর্তী ক্যাশে স্তর যুক্ত করেছি. এটি সম্প্রতি ব্যবহৃত অবজেক্ট ও সম্পর্কের কপি Valkey সার্ভারে রাখে. সার্ভারগুলো আমাদের অবকাঠামোতে ব্যবহারকারীর অনুরোধ প্রক্রিয়াকরণের স্থানের কাছে থাকে. এ ধরনের ক্যাশে সাধারণত মেয়াদসীমা (TTL) ব্যবহার করে, যা ক্যাশেতে ডেটা পাওয়ার হার ও ডেটা পুরোনো হয়ে যাওয়ার মধ্যে ভারসাম্য রাখে. কম TTL ডেটা পুরোনো থাকার সময় কমায়, তবে ক্যাশের সুফলও কমায়. কারণ ক্যাশের ডেটার মেয়াদ দ্রুত শেষ হয় এবং বারবার তা আনতে হয়. বেশি TTL ক্যাশেতে ডেটা পাওয়ার হার বাড়ায়, তবে দীর্ঘ সময় পুরোনো ডেটা সরবরাহ করে. এতে ব্যবহারকারীর অভিজ্ঞতা খারাপ হয় এবং পণ্য অপ্রত্যাশিত আচরণ করে.
আরেকটি পদ্ধতি হলো, অ্যাপ্লিকেশন মূল ডেটায় লেখার সময় ক্যাশেতে সেই ডেটা সরাসরি অকার্যকর করে দেওয়া. এতে ক্যাশের ডেটা অনেক বেশি হালনাগাদ থাকে, তবে পদ্ধতিটি সঠিকভাবে কার্যকর করা কঠিন হতে পারে. আংশিক ব্যর্থতার মতো কিছু ব্যতিক্রমী পরিস্থিতিতেও ক্যাশের ডেটা পুরোনো থেকে যেতে পারে. একাধিক অঞ্চলে এই সমস্যা আরও বাড়ে: অঞ্চলগুলোর মধ্যকার নেটওয়ার্ক কম নির্ভরযোগ্য, আর ক্যাশে ও মূল সংরক্ষণ ব্যবস্থার প্রতিলিপি তৈরির সময়ে সমন্বয়হীনতা দেখা দেয়. সঙ্গে TTL ব্যবহার করলে ডেটা সর্বোচ্চ কতক্ষণ পুরোনো থাকবে তা বেঁধে দেওয়া যায়, তবে TTL-এর আগের সেই সুবিধা-অসুবিধা থেকেই যায়.
Meta-এর TAO-এর মতো ব্যবস্থার অনুসরণে ক্যাশে অকার্যকর করার আরও উন্নত পদ্ধতি নিয়েছি আমরা. Habitat-এর সমন্বিত ক্যাশে Azure Cosmos DB-এর পরিবর্তনপ্রবাহ থেকে ডেটার পরিবর্তন সংগ্রহ (CDC) করে. এতে সেকেন্ডের মধ্যেই বিশ্বজুড়ে ক্যাশে অকার্যকর করার বার্তা ছড়ায়, ফলে ক্যাশেতে ডেটা পাওয়ার হার বেশি থাকে এবং ডেটা কম সময় পুরোনো থাকে. আমাদের অবকাঠামোর একটি সেবা এই পরিবর্তনপ্রবাহ গ্রহণ করে এবং মূল ডেটা হালনাগাদ হলে স্থানীয় ক্যাশেতে সেই ডেটা অকার্যকর করে. ফলে পরেরবার পড়ার সময় ডেটা ক্যাশেতে পাওয়া যায় না এবং ক্যাশে ডেটার সর্বশেষ সংস্করণ দিয়ে পূরণ হয়.
আমরা Rust-এ কোড নতুন করে লিখে Habitat সেবার নিজস্ব বাড়তি কাজ সরিয়েও বিলম্ব অনেক কমিয়েছি. এটি মূল Python সংস্করণের চেয়ে বেশি কর্মক্ষম.
সব পরিবর্তন মিলিয়ে বিশ্বব্যাপী ডেটা পড়ার সামগ্রিক p50 সময় প্রায় ১২০ থেকে ১০ মিলিসেকেন্ডে নেমেছে. এ বছরের শুরুতে কর্মক্ষমতায় মনোযোগ দেওয়ার পর থেকে এটি ১২ গুণ উন্নতি.
Figure 05 · Improving performance at a global scale
p50 latency for reads
Three major design changes improved read latency
ক্যাশে ব্যবহারে মধ্যম সাড়ার সময় অনেক কমলেও সবচেয়ে ধীর অনুরোধগুলোর জন্য মূল সংরক্ষণ ব্যবস্থা থেকে ক্যাশে-বহির্ভূত ডেটা আনতে হয়, প্রায়ই দূরের অঞ্চল থেকে. সক্ষমতা বাড়ার ও সংরক্ষণের দক্ষতা উন্নত হওয়ার সঙ্গে আমরা আরও মৌলিক একটি সমস্যা সমাধান করতে চাই: শুরু থেকেই ডেটা ব্যবহারের স্থানের কাছে রাখা.
ডেটাবেসের পরিবর্তন পরবর্তী ব্যবস্থাগুলোতে পৌঁছানোর নির্ভরযোগ্য ও সম্প্রসারণযোগ্য CDC শুধু Habitat-এর ক্যাশে কৌশলেই নয়, আরও অনেক ক্ষেত্রেই অপরিহার্য. হাজার হাজার কনটেইনার ও লাখ লাখ কনটেইনার পার্টিশন থেকে সেকেন্ডে লাখ লাখ পরিবর্তন সংগ্রহ করে শতাধিক Kafka টপিক দিয়ে পাঠানো হয়. এতে সময়ের সঙ্গে সামঞ্জস্যপূর্ণ হওয়া গৌণ সূচি, ডেটা স্থানান্তর প্রক্রিয়া, অফলাইন বিশ্লেষণ ও অন্যান্য তাৎক্ষণিক পণ্যসুবিধাও চলে. বিশ্বজুড়ে আমাদের মূল অবকাঠামো বাড়ার সঙ্গে সারির পরিবর্তন শনাক্ত করা ক্রমেই জটিল হয়েছে. নিজের ধরনের সারি বদলালেই চলবে এমন কলব্যাক নিবন্ধন করতে ক্লায়েন্টকে প্রথমে জানতে হয়, কোন Cosmos অ্যাকাউন্ট ও কনটেইনারে তার ডেটা আছে এবং সংশ্লিষ্ট অঞ্চলে কোন CDC সেবা সেই কনটেইনারগুলোর পরিবর্তন অনুসরণ করছে. পাশাপাশি CDC কর্মীসমষ্টি, Kafka ও নিজের গ্রাহক প্রক্রিয়ার সক্ষমতাও ঠিকভাবে বাড়াতে হয়. আমাদের CDC প্ল্যাটফর্মের লক্ষ্য পণ্য উন্নয়নকারীদের এই জটিলতা থেকে মুক্ত রাখা. সহজ একটি মাধ্যমে ক্লায়েন্ট শুধু সারি বদলালে চালাতে চায় এমন ফাংশন নিবন্ধন করে; সংযোগ ও সক্ষমতা বাড়ানোর বাকি কাজ আমরা সামলাই.
একটি অভ্যন্তরীণ নিয়ন্ত্রণ স্তর সব প্রয়োজনীয় কনটেইনারের পরিবর্তন সংগ্রহ হচ্ছে কি না নিশ্চিত করে, কোন Cosmos অঞ্চল থেকে পড়বে তা বেছে নেয় এবং বিভিন্ন অঞ্চলের হাজার হাজার কর্মীর মধ্যে দক্ষভাবে কাজ বণ্টন করে. প্রতিলিপি অঞ্চল ব্যবহার ও কম অগ্রাধিকারে পরিবর্তনপ্রবাহ পড়ার মাধ্যমে পটভূমির সংগ্রহকাজ থেকে Habitat-এর বিলম্ব-সংবেদনশীল অনুরোধগুলো সুরক্ষিত থাকে. এত বড় কর্মীসমষ্টিতে কর্মী প্রক্রিয়া বন্ধ হওয়া, কনটেইনারের সমস্যা, লিজ সংরক্ষণের ত্রুটি, ভুল বিন্যাস এবং গন্তব্যের ব্যর্থতা নিয়মিত ঘটে. আমরা CDC কর্মীর জীবনচক্র ও লিজ ব্যবস্থাপনাকে আরও মজবুত করেছি, এক প্রবাহের ব্যর্থতা অন্যটিতে ছড়ানো ঠেকিয়েছি এবং বিন্যাস পরিবর্তন ও নতুন সংস্করণ চালুর সুরক্ষা গড়েছি. স্থায়ী সরবরাহ-ব্যর্থতায় সারির সামনের কাজ আটকে গিয়ে পেছনের কাজ থেমে যাওয়া ঠেকাতে ব্যর্থ বার্তার আলাদা সারি ব্যবহার করি. পাঠক প্রক্রিয়াগুলোকে বিকল্প Cosmos অঞ্চলে সরিয়ে আঞ্চলিক বিভ্রাট সামলাই. আমাদের পরিসরে Azure-এর CDC SDK-তেও পরিবর্তন করতে হয়েছে. অগ্রগতির চেকপয়েন্টগুলো মেমোরিতে গুচ্ছ করে জমিয়ে শুধু নির্দিষ্ট বিরতিতে স্থায়ীভাবে লিখে এর চেকপয়েন্ট ব্যবস্থা আরও দক্ষ করেছি.
Habitat-এর ভেতরে Azure Cosmos DB-এর ব্যবহার জটিল হলেও এর মূল সুবিধা বরাবরই ছিল অবকাঠামোর খুঁটিনাটি পণ্য উন্নয়নকারীদের আড়ালে রেখে উন্নয়নের গতি বাড়ানো. আমাদের CDC প্ল্যাটফর্মও এর ব্যতিক্রম নয়.
সংরক্ষণের API ইচ্ছাকৃতভাবে সীমিত রেখে, Python সেবার সক্ষমতা বাড়িয়ে এবং জরুরি প্রকৌশল চ্যালেঞ্জগুলোকে অগ্রাধিকার দিয়ে একটি ছোট দল দ্রুত বাড়তে থাকা সংরক্ষণ প্ল্যাটফর্ম সামলাতে পেরেছে. আমরা আগে অত্যাবশ্যক পণ্যের অনুরোধের নির্ভরযোগ্যতায়, তারপর বিশ্বব্যাপী ব্যবহারকারীদের ডেটা পড়ার কর্মক্ষমতায়, সবশেষে বড় পরিসরে পরিচালনার দক্ষতায় মনোযোগ দিয়েছি. এই পদ্ধতিতে নির্ভরযোগ্যতা, কর্মক্ষমতা ও পণ্য উন্নয়নের গতি বাড়ানোর পাশাপাশি দ্রুত বৃদ্ধি ও নতুন ব্যবহার সম্ভব হয়েছে.
পরবর্তী ১০০ কোটি ব্যবহারকারীর জন্য Habitat ও কথোপকথন সংরক্ষণের সক্ষমতা বাড়াতে আরও বড় পরিসরে আমাদের অবকাঠামোজুড়ে ডেটার প্রতিলিপি রাখার সমস্যার সমাধান করতে হবে. আগাম প্রস্তুতি হিসেবে আমরা নিজস্ব এক্সাবাইট-পরিসরের অনলাইন সংরক্ষণ ব্যবস্থা তৈরি করছি, যা Habitat-এর বড় আকারের ডেটার জন্য বিশেষভাবে উপযোগী. নির্মাণাধীন ব্যবস্থাটিতে Rockset-এর RocksDB Cloud মূল অংশের সঙ্গে Raft-ভিত্তিক প্রতিলিপি ব্যবস্থা যুক্ত করা হয়েছে. এতে Azure Cosmos DB-এর মতো একই নথি-কাঠামো ব্যবহৃত হয়. তবে গণনা থেকে পৃথক সংরক্ষণ ও ভৌত প্রতিলিপি ব্যবহার করে প্রয়োজনীয় ফ্ল্যাশ সক্ষমতা কমানো হয়, বিনিময়ে সেকেন্ডপ্রতি সর্বোচ্চ অনুরোধের হার কম থাকে.
অত্যাধুনিক পরিসরে এ ধরনের ডেটা অবকাঠামোর কাজে আগ্রহী হলে আমাদের শূন্য পদগুলো দেখুন.


