অ্যাপবয় হল মোবাইল অ্যাপের জন্য বিশ্বের শীর্ষস্থানীয় মার্কেটিং অটোমেশন প্ল্যাটফর্ম। আমাদের গ্রাহকদের মোবাইল অ্যাপে ব্যবহারকারীরা কী করছেন তা ট্র্যাক করে এবং তাদের আচরণ বা জনসংখ্যার উপর ভিত্তি করে ইমেল, পুশ বিজ্ঞপ্তি এবং অ্যাপ-মধ্যস্থ বার্তাগুলির জন্য ব্যবহারকারীদের লক্ষ্য করার অনুমতি দিয়ে আমরা প্রতি মাসে কোটি কোটি ডেটা পয়েন্ট সংগ্রহ করি। MongoDB আমাদের বেশিরভাগ ডাটাবেস স্ট্যাকের ক্ষমতা দেয়, এবং আমরা ObjectRocket-এ একাধিক ক্লাস্টার জুড়ে কয়েক ডজন শার্ড হোস্ট করি।
MongoDB-এর সাথে একটি সাধারণ কর্মক্ষমতা অপ্টিমাইজেশন কৌশল হল নথিতে ছোট ক্ষেত্রের নাম ব্যবহার করা। অর্থাৎ, এরকম দেখতে একটি নথি তৈরি করার পরিবর্তে…
{first_name: "Jon", last_name: "Hyman"}
…ছোট ক্ষেত্রের নাম ব্যবহার করুন যাতে ডকুমেন্টটি দেখতে…
{fn: "Jon", ln: "Hyman"}
যেহেতু MongoDB-তে কলাম বা পূর্বনির্ধারিত স্কিমার ধারণা নেই, তাই এই কাঠামোটি সুবিধাজনক কারণ ডাটাবেসের প্রতিটি নথিতে ফিল্ডের নাম ডুপ্লিকেট করা হয়। যদি আপনার কাছে এক মিলিয়ন নথি থাকে যেগুলির প্রতিটিতে একটি "প্রথম_নাম" ক্ষেত্র থাকে, আপনি সেই স্ট্রিংটি এক মিলিয়ন বার সংরক্ষণ করছেন। এটি প্রতি নথিতে আরও স্থানের দিকে নিয়ে যায়, যা শেষ পর্যন্ত কতগুলি নথি মেমরিতে ফিট করতে পারে তা প্রভাবিত করে এবং বড় আকারে কার্যক্ষমতাকে কিছুটা প্রভাবিত করতে পারে, কারণ MongoDB ডকুমেন্টগুলি পড়ার সাথে সাথে মেমরিতে ম্যাপ করতে হয়৷
ইভেন্ট ডেটা সংগ্রহ করার পাশাপাশি, অ্যাপবয় আমাদের গ্রাহকদের তাদের প্রতিটি ব্যবহারকারীর কাছে "কাস্টম বৈশিষ্ট্য" বলে সংরক্ষণ করতে দেয়। উদাহরণ স্বরূপ, একটি স্পোর্টস অ্যাপ ব্যবহারকারীর "প্রিয় প্লেয়ার" সঞ্চয় করতে চাইতে পারে, যখন একটি পত্রিকা বা সংবাদপত্রের অ্যাপ একটি গ্রাহক "বার্ষিক গ্রাহক" হোক বা না হোক সঞ্চয় করতে পারে। Appboy-এ, আমাদের কাছে একটি অ্যাপের প্রতিটি শেষ ব্যবহারকারীর জন্য একটি ডকুমেন্ট রয়েছে যা আমরা ট্র্যাক করি এবং এতে আমরা সেই কাস্টম বৈশিষ্ট্যগুলিকে তাদের প্রথম বা শেষ নামের মতো ক্ষেত্রগুলির পাশাপাশি সংরক্ষণ করি। স্থান বাঁচাতে এবং কর্মক্ষমতা উন্নত করতে, আমরা নথিতে সঞ্চয় করা সমস্ত কিছুর ক্ষেত্রের নাম ছোট করি। আমরা যে ক্ষেত্রগুলি আগে থেকেই জানি (যেমন প্রথম নাম, ইমেল, লিঙ্গ, ইত্যাদি) সেগুলির জন্য আমরা আমাদের নিজস্ব অ্যালিয়াসিং করতে পারি (যেমন, "fn" মানে "প্রথম নাম"), কিন্তু আমরা কাস্টম বৈশিষ্ট্যগুলির নাম ভবিষ্যদ্বাণী করতে পারি না যে আমাদের গ্রাহকরা রেকর্ড করবে। একজন গ্রাহক যদি "supercalifragilisticexpialidocious" নামে একটি কাস্টম অ্যাট্রিবিউট তৈরি করার সিদ্ধান্ত নেন, তাহলে আমরা সেটি তাদের সমস্ত নথিতে সংরক্ষণ করতে চাই না।
এটি সমাধান করার জন্য, আমরা কাস্টম অ্যাট্রিবিউট ফিল্ডের নাম টোকেনাইজ করি যাকে আমরা "নাম স্টোর" বলি। কার্যকরভাবে, এটি মঙ্গোডিবি-তে একটি নথি যা একটি অনন্য, অনুমানযোগ্য, খুব ছোট স্ট্রিং-এ "প্রিয় প্লেয়ার" এর মতো মানগুলিকে ম্যাপ করে। আমরা শুধুমাত্র MongoDB এর পারমাণবিক অপারেটর ব্যবহার করে এই মানচিত্র তৈরি করতে পারি
নাম স্টোর ডকুমেন্ট স্কিমা অত্যন্ত মৌলিক:প্রতিটি গ্রাহকের জন্য একটি নথি আছে, এবং প্রতিটি নথিতে শুধুমাত্র একটি অ্যারে ক্ষেত্র রয়েছে যার নাম "তালিকা"। ধারণাটি হল যে অ্যারেতে কাস্টম বৈশিষ্ট্যগুলির জন্য সমস্ত মান থাকবে এবং একটি প্রদত্ত স্ট্রিংয়ের সূচক হবে তার টোকেন। তাই যদি আমরা "প্রিয় প্লেয়ার"কে একটি সংক্ষিপ্ত, অনুমানযোগ্য ক্ষেত্রের নামে অনুবাদ করতে চাই, তাহলে আমরা কেবল "তালিকা" চেক করে দেখি যে এটি অ্যারেতে কোথায় আছে। যদি এটি সেখানে না থাকে, তাহলে অ্যারের শেষে উপাদান যোগ করার জন্য আমরা একটি পারমাণবিক ধাক্কা দিতে পারি, (db.custom_attribute_name_stores.update({_id :X, তালিকা:{$ne :"প্রিয় প্লেয়ার"}}, {$ push:{তালিকা:“প্রিয় প্লেয়ার”}}), নথিটি পুনরায় লোড করুন এবং সূচক নির্ধারণ করুন। আদর্শভাবে, আমরা $addToSet ব্যবহার করতাম, কিন্তু $addToSet অর্ডার দেওয়ার গ্যারান্টি দেয় না, যেখানে $push ডিফল্টভাবে শেষ পর্যন্ত যুক্ত করার জন্য নথিভুক্ত করা হয়।
সুতরাং এই মুহুর্তে, আমরা একটি পূর্ণসংখ্যা মান হিসাবে "প্রিয় প্লেয়ার" এর মত কিছু অনুবাদ করতে পারি। বলুন যে মান 1। তাহলে আমাদের ব্যবহারকারীর নথির মত দেখাবে:
{
fn: "Jon",
ln: "Hyman",
custom: {
1: "LeBron James"
}
}
মাঠের নামগুলো সংক্ষিপ্ত ও পরিপাটি! এর একটি দুর্দান্ত পার্শ্বপ্রতিক্রিয়া হল যে আমাদের গ্রাহকদের অক্ষর ব্যবহার করার বিষয়ে আমাদের চিন্তা করতে হবে না যা MongoDB পালানো ছাড়া সমর্থন করতে পারে না, যেমন ডলারের চিহ্ন বা পিরিয়ড।
এখন, আপনি হয়তো ভাবছেন যে MongoDB ক্রমাগত ক্রমবর্ধমান নথিগুলির বিরুদ্ধে সতর্ক করে এবং আমাদের নাম স্টোরের নথি সীমাহীনভাবে বৃদ্ধি পেতে পারে। বাস্তবে, আমরা আমাদের বাস্তবায়নকে কিছুটা প্রসারিত করেছি যাতে আমরা প্রতি গ্রাহকের একাধিক নথি সংরক্ষণ করতে পারি। এটি আমাদের একটি যুক্তিসঙ্গত ক্যাপ দিতে দেয় যে আমরা একটি নতুন নথি তৈরি করার আগে কতগুলি অ্যারে উপাদানের অনুমতি দিই। সবচেয়ে ভালো দিক হল আমরা এখনও শুধুমাত্র MongoDB ব্যবহার করে পারমাণবিকভাবে এই সব করতে পারি! এটি অর্জন করার জন্য, আমরা প্রতিটি নথিতে আরেকটি ক্ষেত্র যোগ করি যাকে বলা হয় "leastvalue"। "সর্বনিম্ন মান" ক্ষেত্রটি এটি তৈরি করার আগে পূর্ববর্তী নথিতে কতগুলি উপাদান যুক্ত করা হয়েছে তা উপস্থাপন করে। সুতরাং আমরা যদি “সর্বনিম্ন মান” 100 সহ একটি নথি এবং [“সিজন টিকিট হোল্ডার”, “প্রিয় প্লেয়ার”] এর একটি “তালিকা” দেখি, তাহলে “প্রিয় প্লেয়ার”-এর টোকেন মান হল 101 (আমরা শূন্য ব্যবহার করছি -ভিত্তিক ইন্ডেক্সিং)। এই উদাহরণে, আমরা একটি নতুন নথি তৈরি করার আগে শুধুমাত্র "তালিকা" অ্যারেতে 100টি মান সংরক্ষণ করছি। এখন, সন্নিবেশ করার সময়, আমরা সর্বোচ্চ “সর্বনিম্ন সহ নথিতে কাজ করার জন্য পুশটিকে সামান্য পরিবর্তন করি মান" মান, এবং এছাড়াও নিশ্চিত করুন যে "list.99" বিদ্যমান নেই (অর্থাৎ "তালিকা" অ্যারেতে সূচক 99-এ কিছুই নেই)। যদি একটি উপাদান ইতিমধ্যেই সেই সূচকে বিদ্যমান থাকে তবে পুশ অপারেশন কিছুই করবে না। সেই ক্ষেত্রে, আমরা জানি যে সমস্ত নথিতে বিদ্যমান উপাদানগুলির মোট সংখ্যার সমান একটি "least_value" সহ একটি নতুন নামের স্টোর নথি তৈরি করতে হবে। একটি পরমাণু $findAndModify ব্যবহার করে, আমরা নতুন ডকুমেন্ট তৈরি করতে পারি যদি এটি বিদ্যমান না থাকে, এটিকে ফিরিয়ে আনতে পারি এবং তারপর আবার $পুশ পুনরায় চেষ্টা করতে পারি।
যদি আমাদের গ্রাহকের কাছে কয়েকটি কাস্টম বৈশিষ্ট্যের চেয়ে বেশি থাকে, তবে মান থেকে টোকেনগুলিতে অনুবাদ করার জন্য সমস্ত নাম স্টোর নথি পড়া ব্যান্ডউইথ এবং প্রক্রিয়াকরণের ক্ষেত্রে ব্যয়বহুল হতে পারে। যাইহোক, যেহেতু একটি প্রদত্ত ক্ষেত্রের টোকেন মান সর্বদা একই থাকে একবার এটি গণনা করার পরে, আমরা অনুবাদের গতি বাড়ানোর জন্য টোকেনগুলি ক্যাশ করি৷
আমরা একটি নমনীয় স্কিমা ব্যবহার করা চালিয়ে যাওয়ার সময় ক্ষেত্রের নামের আকার কমাতে আমাদের অ্যাপ্লিকেশনের বিভিন্ন অংশে "নাম স্টোর টোকেন" দৃষ্টান্ত প্রয়োগ করেছি। এটি মানগুলির জন্যও সহায়ক হতে পারে। ধরা যাক যে একটি রেডিও স্টেশন অ্যাপ একটি কাস্টম অ্যাট্রিবিউট সঞ্চয় করে যা একজন ব্যবহারকারী শোনেন এমন শীর্ষ 50 জন পারফর্মিং শিল্পীর একটি অ্যারে। 50টি স্ট্রিং সহ একটি অ্যারে রাখার পরিবর্তে, আমরা রেডিও স্টেশনের নামগুলিকে টোকেনাইজ করতে পারি এবং পরিবর্তে ব্যবহারকারীর কাছে 50টি পূর্ণসংখ্যার একটি অ্যারে সংরক্ষণ করতে পারি। একজন নির্দিষ্ট শিল্পীকে পছন্দ করে এমন ব্যবহারকারীদের জিজ্ঞাসা করার জন্য এখন দুটি টোকেন লুকআপ জড়িত:একটি ক্ষেত্রের নামের জন্য এবং একটি মানের জন্য। কিন্তু যেহেতু আমরা অনুবাদকে মান থেকে টোকেনে ক্যাশে করি, তাই যেকোনো সংখ্যক মান অনুবাদ করার সময় ক্যাশে একটি একক রাউন্ড-ট্রিপ বজায় রাখতে আমরা আমাদের ক্যাশে স্তরে একটি মাল্টি-গেট ব্যবহার করতে পারি।
এই অপ্টিমাইজেশানটি অবশ্যই কিছু পরোক্ষতা এবং জটিলতা যোগ করে, কিন্তু আপনি যখন অ্যাপবয়-এ আমাদের মতো কয়েক মিলিয়ন ব্যবহারকারী সংরক্ষণ করেন, তখন এটি একটি সার্থক অপ্টিমাইজেশন। আমরা এই কৌশলটির মাধ্যমে শত শত গিগাবাইট ব্যয়বহুল SSD স্থান সংরক্ষণ করেছি।
আরো জানতে চান? 18ই সেপ্টেম্বর সিপ্রিয়ানিতে Rackspace Solve NYC সম্মেলনের সময় আমি অ্যাপবয়-এ ডেভপস নিয়ে আলোচনা করব।