একটি বিশাল ক্লাউড প্ল্যাটফর্মে হাজার হাজার মাইক্রোসার্ভিস একসাথে চলার সময় কিছু মৌলিক সমন্বয়ের প্রয়োজন হয়: কে লিডার হবে, কোন সার্ভার লাইভ আছে আর কোনটি ক্র্যাশ করেছে, এবং ডেটাবেসে লেখার জন্য এক্সক্লুসিভ লক কীভাবে নিয়ন্ত্রিত হবে। প্রতিটি সার্ভারে আলাদা আলাদা কনসেনসাস অ্যালগরিদম কোড করা এক দুঃসাধ্য ও ঝুঁকিপূর্ণ কাজ। ২০০৬ সালে গুগল উদ্ভাবন করে চাবি (Chubby) লক সার্ভিস, যা ফাইল সিস্টেমের মতো দেখতে একটি সেন্ট্রাল লক ইঞ্জিন। ২০১০ সালে ইয়াহু ওপেন সোর্স করে অ্যাপাচি জুকিপার (Apache ZooKeeper)। জুকিপার তার বিশেষায়িত কনসেনসাস প্রটোকল জ্যাব (Zab – ZooKeeper Atomic Broadcast)-এর মাধ্যমে আধুনিক ক্লাউড সিস্টেমের সবচেয়ে নির্ভরযোগ্য কোঅর্ডিনেশন কার্নেলে পরিণত হয়েছে।

১. জুকিপারের হায়ারার্কিকাল ডেটা মডেল (znodes)

জুকিপার সমন্বয়ের জন্য ফাইল সিস্টেমের মতো একটি হায়ারার্কিকাল ট্রি স্ট্রাকচার প্রদান করে। এই ট্রির প্রতিটি উপাদানকে বলা হয় জিনোড (znode):

$$text{Root } / to text{/services} to text{/services/payment} to text{/services/payment/node-0001}$$

জিনোডের প্রকারভেদ

  • পারসিসটেন্ট (Persistent): ক্লায়েন্ট তৈরি করার পর ম্যানুয়ালি মুছে না ফেলা পর্যন্ত স্থায়ীভাবে ডিস্কে সংরক্ষিত থাকে।
  • ইফিমেরাল (Ephemeral): ক্লায়েন্টের নেটওয়ার্ক সেশনের সাথে সরাসরি যুক্ত। ক্লায়েন্ট সার্ভার যদি ক্র্যাশ করে বা নির্দিষ্ট সময় হার্টবিট না পাঠায়, তবে জুকিপার স্বয়ংক্রিয়ভাবে এই জিনোডটি মুছে ফেলে। এটি ফল্ট ডিটেকশন ও নোড মনিটরিংয়ের জন্য আদর্শ।
  • সিকোয়েনশিয়াল (Sequential): নতুন জিনোড তৈরির সময় জুকিপার স্বয়ংক্রিয়ভাবে একটি ১০-ডিজিটের বর্ধনশীল ক্রমিক সংখ্যা যুক্ত করে (যেমন `lock-0000000001`), যা ট্রানজ্যাকশন অর্ডারিংয়ের ভিত্তি।

ওয়াচ (Watches): পোলিং মুক্ত ইভেন্ট নোটিফিকেশন

জুকিপারে সার্ভারগুলোকে বারবার রিকোয়েস্ট পাঠিয়ে ডেটা পরিবর্তন হয়েছে কিনা তা যাচাই (Polling) করতে হয় না। ক্লায়েন্টরা নির্দিষ্ট জিনোডে একটি ওয়াচ (Watch) বসিয়ে রাখে। ডেটা পরিবর্তিত হওয়ার সাথে সাথে জুকিপার নিজে ক্লায়েন্টকে ইভেন্ট পুশ নোটিফিকেশন পাঠিয়ে দেয়।

২. জ্যাব (Zab) প্রটোকল: জুকিপার অ্যাটমিক ব্রডকাস্ট

জুকিপার ক্লাস্টার যে বিশেষায়িত কনসেনসাস অ্যালগরিদমের ওপর ভিত্তি করে চলে তাকে বলা হয় জ্যাব (Zab)। প্রতিটি ট্রানজ্যাকশনের সাথে একটি ৬৪-বিটের অনন্য সংখ্যা যুক্ত থাকে যাকে ZXID বলা হয়:

$$text{ZXID} = langle e, c rangle = (e ll 32) mid c$$

এর প্রথম ৩২ বিট হলো এপক (Epoch – $e$), যা প্রতিবার নতুন লিডার নির্বাচিত হলে বৃদ্ধি পায়; আর শেষ ৩২ বিট হলো ট্রানজ্যাকশন কাউন্টার $c$।

জ্যাব মূলত দুটি ফেজে কাজ করে: রিকভারি ফেজ (যেখানে সর্বোচ্চ ZXID বিশিষ্ট নোড নতুন লিডার হয় এবং লগের অসামঞ্জস্য দূর করে) এবং অ্যাটমিক ব্রডকাস্ট ফেজ (যেখানে টু-ফেজ কমিটের মতো করে কিন্তু কোনো অ্যাবর্ট ছাড়াই মেজরিটি কোরামের সম্মতিতে সমস্ত নোডে ডেটা রেপ্লিকেট করা হয়)।

৩. ক্লাসিক্যাল কোঅর্ডিনেশন রেসিপি: ফেয়ার ডিস্ট্রিবিউটেড লক

হাজার হাজার সার্ভার যদি একসাথে একটি একক লকের পেছনে ছুটে যায়, তবে নেটওয়ার্কে ট্র্যাফিক জ্যাম বা থান্ডারিং-হার্ড (Thundering Herd) সৃষ্টি হয়। জুকিপার এটি দূর করে অত্যন্ত চমৎকার অ্যালগরিদমে:

  1. প্রতিটি সার্ভার একটি ইফিমেরাল সিকোয়েনশিয়াল জিনোড তৈরি করে: `/locks/res/lock-seq`।
  2. সার্ভারটি যদি দেখে যে তার তৈরি করা ক্রমিক সংখ্যাটি সবচেয়ে ছোট, তবে সে বুঝে নেয় যে সে নিজেই লকের বর্তমান মালিক!
  3. যদি তার সংখ্যাটি সর্বনিম্ন না হয়, তবে সে সব সার্ভারের ওপর নজর না রেখে কেবল তার ঠিক আগের ক্রমিক সংখ্যার নোডটির ওপর একটি ওয়াচ বসিয়ে রাখে।
  4. পূর্ববর্তী নোডটি কাজ শেষ করে লক মুক্ত করলে জুকিপার শুধু তার পরবর্তী নোডটিকেই ডেকে তোলে। এর ফলে কোনো অপ্রয়োজনীয় ব্রডকাস্ট ছাড়াই সম্পূর্ণ সুশৃঙ্খলভাবে $mathcal{O}(1)$ ল্যাটেন্সিতে লক হস্তান্তরিত হয়।