কম্পিউটার টিউটোরিয়াল

MongoDB অপ্টিমাইজ করা: স্টোরেজ বর্জ্য কমাতে প্রমাণিত টেকনিক

Appboy মোবাইল অ্যাপের জন্য বিশ্বের লিডিং মার্কেটিং অটোমেশন প্ল্যাটফর্ম। আমরা প্রতি মাসে বিলিয়ন বিলিয়ন ডেটা পয়েন্ট সংগ্রহ করি আমাদের কাস্টমারদের মোবাইল অ্যাপে ব্যবহারকারীরা কী করছে সেটি ট্র্যাক করে এবং তাদেরকে টার্গেট করতে দিয়ে ইমেইল, পুশ নোটিফিকেশন এবং ইন-অ্যাপ মেসেজ ব্যবহারকারীর আচরণ বা ডেমোগ্রাফিক্সের ভিত্তিতে। MongoDB আমাদের ডেটাবেস স্ট্যাকের অধিকাংশteil পাওয়ার করে, এবং আমরা ObjectRocket-এ একাধিক ক্লাস্টারের আশেপাশে দশক শার্ড হোস্ট করি।

MongoDB-এ একটি সাধারণ পারফরম্যান্স অপ্টিমাইজেশন স্ট্র্যাটেজি হলো ডকুমেন্টে শর্ট ফিল্ড নেম ব্যবহার করা। অর্থাৎ, একটি ডকুমেন্ট তৈরি করার বদলে যা দেখতে এমন...

{first_name: "Jon", last_name: "Hyman"}

...ছোট ফিল্ড নেম ব্যবহার করুন যাতে ডকুমেন্টটি দেখতে পারে এমন...

{fn: "Jon", ln: "Hyman"}

যেহেতু MongoDB-র কোনো কনসেপ্ট নয় কলাম বা প্রিডিফাইন্ড স্কিমার, এই স্ট্রাকচারটি সুবিধাজনক কারণ ফিল্ড নেমগুলো ডেটাবেসের প্রতিটি ডকুমেন্টে ডুপ্লিকেট হয়। আপনার যদি এক মিলিয়ন ডকুমেন্ট থাকে যেগুলোর প্রতিটিতে "first_name" ফিল্ড থাকে, আপনি সেই স্ট্রিংটি এক মিলিয়ন বার স্টোর করছেন। এটা প্রতি ডকুমেন্টে আরও স্পেস লيدية করে, যা চূড়ান্তে প্রভাব ফেলে কতগুলো ডকুমেন্ট মেমরিতে ফিট होতে পারে এবং, বড় স্কেলে, সামান্য পারফরম্যান্স প্রভাবিত করতে পারে, কারণ MongoDB-কে ডকুমেন্ট মেমরিতে ম্যাপ করতে হয় সেগুলো পড়ার সময়।

ইভেন্ট ডেটা সংগ্রহের পাশাপাশি, Appboy আমাদের কাস্টমারদের লেট তাদের প্রতিটি ইউজারের ওপর যা আমরা "কাস্টম অ্যাট্রিবিউট" বলি সেটি স্টোর করতে দেয়। উদাহরণস্বরূপ, একটি স্পোর্টস অ্যাপ হতে চায় একটি ব্যবহারকারীর "Favorite Player" স্টোর করতে, যখন একটি ম্যাগাজিন বা নিউজপেপার অ্যাপ স্টোর করতে চায় কিনা একজন কাস্টমার "Annual Subscriber"। Appboy-এ, আমাদের ট্র্যাক করা প্রতিটি অ্যাপের এন্ড ইউজারের জন্য একটি ডকুমেন্ট রয়েছে, এবং সেটির ওপর আমরা সেস কাস্টম অ্যাট্রিবিউট স্টোর করি ফিল্ডের পাশাপাশি যেগুলো তাদের ফার্স্ট বা লাস্ট নেম। স্পেস বাঁচাতে এবং পারফরম্যান্স উন্নত করতে, আমরা সব কিছুর ফিল্ড নেম ছোট করি যা ডকুমেন্টে স্টোর করি। जिन ফিল্ডগুলো আমরা আগে থেকে জানি (যেমন ফার্স্ট নেম, ইমেইল, জেন্ডার, ইত্যাদি) আমরা আমাদের নিজের অ্যালিয়াসিং করতে পারি (যেমন, "fn" মানে "first name"), কিন্তু আমরা প্রিডিক্ট করতে পারি না কাস্টম অ্যাট্রিবিউটের নামগুলো যা আমাদের কাস্টমাররা রেকর্ড করবে। আপনি যদি একটি কাস্টমার ডিসাইড করে একটি কাস্টম অ্যাট্রিবিউট নাম করে "supercalifragilisticexpialidocious," আমরা সেটি তাদের সব ডকুমেন্টে স্টোর করতে চাই না।

এটি সমাধান করতে, আমরা কাস্টম অ্যাট্রিবিউট ফিল্ড নেম টোকেনাইজ করি যা আমরা "নেম স্টোর" বলি। কার্যকরভাবে, এটি MongoDB-এ একটি ডকুমেন্ট যা মানগুলিকে ম্যাপ করে যেমন "Favorite Player" একটি ইউনিক, প্রিডিক্টেবল, খুব ছোট স্ট্রিং-এ। আমরা এই ম্যাপ জেনারেট করতে পারি শুধু MongoDB-এর অ্যাটমিক অপারেটর ব্যবহার করে।

নেম স্টোর ডকুমেন্ট স্কিমা অত্যন্ত বেসিক: প্রতিটি কাস্টমারের জন্য একটি ডকুমেন্ট রয়েছে, এবং প্রতিটি ডকুমেন্টে শুধু একটি অ্যারে ফিল্ড রয়েছে যেটি নাম করা হয়েছে "list"। আইডিয়া হলো অ্যারেটিতে কাস্টম অ্যাট্রিবিউটের সব ভ্যালু থাকবে এবং একটি দিয়ে যেওয়া স্ট্রিংয়ের ইনডেক্সই তার টোকেন হবে। তাই যদি আমরা "Favorite Player" কে একটি ছোট, প্রিডিক্টেবল ফিল্ড নেমে ট্রান্সলেট করতে চাই, আমরা সিম্পলি "list"-এ চেক করব কোথায় সেটি অ্যারেতে রয়েছে। যদি সেটি সেখানে না থাকে, আমরা একটি অ্যাটমিক পুশ ইস্যু করতে পারি এলিমেন্টটি অ্যারেতে শেষে যোগ করার জন্য, (db.custom_attribute_name_stores.update({_id : X, list: {$ne : "Favorite Player"}}, {$push: {list: "Favorite Player"}})), ডকুমেন্টটি রিলোড করুন এবং ইনডেক্স নির্ধারণ করুন। আদর্শভাবে, আমরা $addToSet ব্যবহার করতাম, কিন্তু $addToSet অর্ডারিং গ্যারান্টি দেয় না, যেখানে $push ডকুমেন্টেড হয় ডিফল্টভাবে শেষে অ্যাপেন্ড করার জন্য।

এই পয়েন্টে, আমরা "Favorite Player" এর মত কিছুকে একটি ইন্টিজার ভ্যালুতে ট্রান্সলেট করতে পারি। বলুন সেটি ১ হয়। তাহলে আমাদের ইউজার ডকুমেন্ট দেখাবে এমন:

{ fn: "Jon", ln: "Hyman", custom: { 1: "LeBron James" } }

ফিল্ড নেম ছোট এবং টিডি! এর একটি দারুণ সাইড ইফেক্ট হলো আমাদের কাস্টমাররা যেই ক্যারেক্টার ব্যবহার করে MongoDB সাপোর্ট করে না এমন=escaping ছাড়া, যেমন ডলার সাইন বা পিরিয়ড, সেগুলোর চিন্তা করতে হয় না।

এখন, আপনি হয়তো চিন্তা করছেন MongoDB লেগ acostantly growing documents-র বিরুদ্ধে সতর্ক করে এবং আমাদের নেম স্টোর ডকুমেন্ট আনবাউন্ডেডلي বৃদ্ধি পেতে পারে। প্র্যাকটিসে, আমরা আমাদের ইমপ্লিমেন্টেশন কিছুটা এক্সটেন্ড করেছি যাতে আমরা একাধিক ডকুমেন্ট প্রতি কাস্টমার স্টোর করতে পারি। এটি আমাদের একটিリーズনেবল ক্যাপ রাখতে দেয় কতগুলো অ্যারে এলিমেন্ট আলো করব নতুন ডকুমেন্ট জেনারেট করার আগে। সেরা পার্ট হলো আমরা এখনও সব কিছু অ্যাটমিক্যালি করতে পারি শুধু MongoDB ব্যবহার করে! এটিকে অর্জন করতে, আমরা একটি আরো ফিল্ড যোগ করি প্রতিটি ডকুমেন্টে যেটি নাম করা হয় "leastvalue"। "leastvalue" ফিল্ডটি রিপ্রেজেন্ট করে কতগুলো এলিমেন্ট প্রিভিয়াস ডকুমেন্টগুলোর যোগ হয়েছে এই ডকুমেন্ট তৈরি হওয়ার আগে। তাই যদি আমরা একটি ডকুমেন্ট দেখি যার "leastvalue" ১০০ এবং একটি "list" ["Season Ticket Holder", "Favorite Player"], তাহলে "Favorite Player"-এর টোকেন ভ্যালু হবে ১০১ (আমরা জিরো-বেসড ইন্ডেক্সিং ব্যবহার করছি)। এই উদাহরণে, আমরা শুধু ১০০ ভ্যালু স্টোর করছি "list" অ্যারেতে নতুন ডকুমেন্ট তৈরি করার আগে। এখন, ইনসার্ট করার সময়, আমরা পুশটি কিছুটা মডিফাই করি যাতে সেটি সেটি ডকুমেন্টের ওপর অপারেট করে যেটির "leastvalue" সবচেয়ে বেশি, এবং এছাড়া নিশ্চিত করি "list.99" এক্সিস্ট করে না (অর্থাৎ ইনডেক্স ৯৯-এ "list" অ্যারেতে কিছু নেই)। যদি সেই ইনডেক্সে ইতিমধ্যে একটি এলিমেন্ট থাকে, পুশ অপারেশন কিছুই করবে না। সেক্ষেত্রে, আমরা জানি আমাদের একটি নতুন নেম স্টোর ডকুমেন্ট তৈরি করতে হবে যার "least_value" সমান সব ডকুমেন্টগুলোর মোট এলিমেন্টের সংখ্যা। একটি অ্যাটমিক $findAndModify ব্যবহার করে, আমরা নতুন ডকুমেন্ট তৈরি করতে পারি যদি সেটি এক্সিস্ট না করে, সেটি ফেচ করে ফিরিয়ে আনি এবং তারপর $push আবার রিট্রাই করি।

আমাদের কাস্টমারের যদি কয়েকটির বেশি কাস্টম অ্যাট্রিবিউট থাকে, সব নেম স্টোর ডকুমেন্ট রিড ব্যাক করে ভ্যালু থেকে টোকেনে ট্রান্সলেট করা 익سپেনসিভ হতে পারে ব্যান্ডউইডথ এবং প্রসেসিং-র দিক থেকে। যেহেতু, একটি দিয়ে যেওয়া ফিল্ডের টোকেন ভ্যালু সবসময় একই থাকে একবার এটি কম্পিউট হওয়ার পর, আমরা টোকেনগুলো ক্যাশ করি ট্রান্সলেশন স্পিড আপ করার জন্য।

আমরা "নেম স্টোর টোকেন" প্যারাডাইম আমাদের অ্যাপ্লিকেশনের বিভিন্ন অংশে প্রয়োগ করেছি ফিল্ড নেম সাইজ কাটাতে ফ্লেক্সিবল স্কিমা ব্যবহার করার সাথে সাথে। এটি ভ্যালুগুলোর জন্যও সহায়ক হতে পারে। মনে করুন একটি রেডিও স্টেশন অ্যাপ একটি কাস্টম অ্যাট্রিবিউট স্টোর করে যা একটি অ্যারে শীর্ষ ৫০ পারফর্মিং আর্টিস্ট যেগুলো একজন ইউজার শুনে। ৫০ স্ট্রিংવાલা একটি অ্যারে রাখার বদলে, আমরা রেডিও স্টেশন নেমগুলো টোকেনাইজ করতে পারি এবং ইউজারের ওপর ৫০ ইন্টিজার অ্যারে স্টোর করতে পারি। ইউজার কোয়ারী করা যারা একটি নির্দিষ্ট আর্টিস্ট পছন্দ করে এখন দুটি টোকেন লুকআপ ইনভলভ করে: একটি ফিল্ড নেমের জন্য এবং একটি ভ্যালুয়ের জন্য। কিন্তু যেহেতু আমরা ভ্যালু থেকে টোকেনে ট্রান্সলেশন ক্যাশ করি, আমরা আমাদের ক্যাশ লেয়ারে একটি মাল্টি-গেট ব্যবহার করতে পারি যেকোনো সংখ্যক ভ্যালু ট্রান্সলেট করার সময় সিঙ্গেল রাউন্ড-ট্রিপ টু ক্যাশ মেইনটেইন করতে।

এই অপ্টিমাইজেশন নিশ্চিত কিছু ইনডিরেকশন এবং কমপ্লেক্সিটি অ্যাড করে, কিন্তু আপনি যখন সैंकड़া মিলিয়ন ইউজার স্টোর করেন আমাদের মতো Appboy-এ, এটি একটি ওয়ার্থওয়াইল অপ্টিমাইজেশন। আমরা এই ট্রিক দিয়ে সैंकড়া গিগাবাইটস এক্সপেনসিভ SSD স্পেস বাঁচিয়েছি।

আরও জানতে চান? আমি Appboy-এ devops নিয়ে আলোচনা করব Rackspace Solve NYC Conference-এ Sept 18-ত Cipriani-তে।

  1. MongoDB-তে নেস্টেড ডকুমেন্ট খোঁজা (Dot Notation)

  2. MongoDB কীভাবে Adobe Experience Manager কে উন্নত করে: একটি প্রায়োগিক গাইড

  3. মmongodb ব্যবহার করার শীর্ষ Кейস উন্নত কাস্টমার এক্সপেরিয়েন্সের জন্য

  4. MongoDB স্পেস ম্যানেজমেন্ট 습득: অ্যালোকেশন, ড্যাশবোর্ড, এবং স্কেলিং টিপস