A look at how Tencent Games built service architecture based on CQRS and event sourcing patterns with Pulsar and ScyllaDB. টেনসেন্ট ইন্টারেক্টিভ বিনোদন গ্রুপ গ্লোবাল (আইএজি গ্লোবাল) এর অংশ হিসাবে, প্রক্সিমা বেটা আমাদের টিম এবং স্টুডিওগুলিকে সহায়তা করার জন্য প্রতিশ্রুতিবদ্ধ, বিশ্বব্যাপী লক্ষ লক্ষ খেলোয়াড়দের জন্য অনন্য, উত্তেজনাপূর্ণ গেমগুলি আনতে। Level Infinite (বিশ্বব্যাপী প্রকাশনার ব্র্যান্ড) এর আমাদের টিম আমাদের ব্যবসার জন্য বিভিন্ন ঝুঁকি পরিচালনা করার জন্য দায়ী - উদাহরণস্বরূপ, প্রতারণামূলক কার্যক্রম এবং ক্ষতিকর সামগ্রী। এই ব্লগে, আমরা এই রিয়েল টাইম ইভেন্ট-ভিত্তিক বিশ্লেষণ সিস্টেম তৈরির আমাদের অভিজ্ঞতা ভাগ করব. প্রথম, আমরা কেন আমরা আমাদের পরিষেবা আর্কিটেকচারটি কমান্ড এবং চাহিদা দায়িত্ব বিচ্ছিন্নতা উপর ভিত্তি করে তৈরি করেছি ( ) এবং ইভেন্ট sourcing প্যাটার্ন সঙ্গে এবং ScyllaDB. পরবর্তীতে, আমরা দেখব কিভাবে আমরা ScyllaDB ব্যবহার করে বিভিন্ন গেমপ্লে সেশনগুলিতে ইভেন্ট পাঠানোর সমস্যার সমাধান করতে পারি. অবশেষে, আমরা কীভাবে ScyllaDB কী স্পেস এবং ডেটা পুনরাবৃত্তি ব্যবহার করি যা আমাদের গ্লোবাল ডেটা ব্যবস্থাপনাকে সহজ করে তুলবে। সিপিএল Apache পুলসার ব্যবহারের ক্ষেত্রে একটি চোখ: টেনসেন্ট গেমগুলিতে ঝুঁকি মোকাবেলা আসুন একটি বাস্তব জগতের উদাহরণ দিয়ে শুরু করি আমরা কী নিয়ে কাজ করছি এবং আমাদের মুখোমুখি চ্যালেঞ্জগুলি। এটি টাওয়ার অফ ফ্যান্টাসি থেকে একটি স্ক্রিনশট, একটি 3D-অ্যাকশন ভূমিকা গেম. খেলোয়াড়রা বিভিন্ন কারণে অন্য খেলোয়াড়ের বিরুদ্ধে একটি রিপোর্ট ফাইল করার জন্য এই ডায়ালগ ব্যবহার করতে পারেন. যদি আপনি এটি জন্য একটি সাধারণ CRUD সিস্টেম ব্যবহার করতেন, তাহলে আপনি কীভাবে পরবর্তী রেকর্ডগুলি রক্ষা করবেন? প্রথম চ্যালেঞ্জটি নির্ধারণ করা হবে যে কোন টিম এই ফর্মটি সংরক্ষণ করার জন্য ডাটাবেসের মালিক হবে. একটি রিপোর্ট তৈরি করার বিভিন্ন কারণ রয়েছে (অন্যদের নামে একটি বিকল্প সহ), তাই একটি ক্ষেত্রে বিভিন্ন ফাংশনাল টিম দ্বারা হস্তক্ষেপ করা যেতে পারে. যাইহোক, আমাদের সংস্থার মধ্যে একক ফাংশনাল টিম নেই যা ফর্মটি সম্পূর্ণরূপে মালিক হতে পারে. এই কারণে এটি একটি স্বাভাবিক পছন্দ যে আমরা এই ক্ষেত্রে একটি ঘটনা হিসাবে ক্যাপচার, যেমন "একটি ক্ষেত্রে রিপোর্ট." সমস্ত তথ্য এই ঘটনা হিসাবে ক্যাপচার করা হয়. সমস্ত কার্যকরী টিম শুধুমাত্র এই ঘটনা নিবন্ধন এবং তাদের নিজস্ব ফিল্টারিং করতে হবে. যদি তারা মনে করে যে ক্ষেত্রে তাদের ডোমেইন মধ্যে পড়ে, তারা শুধুমাত্র এটি ক্যাপচার করতে পারেন এবং আরও পদক্ষেপ চালু করতে পারেন. CQRS এবং ইভেন্ট সোর্সিং এই উদাহরণের পিছনে পরিষেবা আর্কিটেকচারটি CQRS এবং ইভেন্ট সার্ভিসিং প্যাটার্নগুলির উপর ভিত্তি করে। যদি এই শর্তগুলি আপনার কাছে নতুন হয়, তবে চিন্তা করবেন না! এই পর্যালোচনাটির শেষ পর্যন্ত, আপনি এই ধারণাগুলির একটি শক্তিশালী বোঝা উচিত। . এই বিষয়টি নিয়ে ব্লগিং এখানে বোঝার প্রথম ধারণাটি ইভেন্ট সুরিং। ইভেন্ট সুরিং এর পিছনে মূল ধারণাটি হল যে একটি সিস্টেমের অবস্থার প্রতিটি পরিবর্তন একটি ইভেন্ট অজেক্টে রেকর্ড করা হয় এবং এই ইভেন্ট অজেক্টগুলি সিস্টেমের অবস্থার জন্য প্রয়োগ করা হয় এমন পর্যায়ে সংরক্ষণ করা হয়। অন্য কথায়, শুধুমাত্র বর্তমান অবস্থা রেকর্ড করার পরিবর্তে, আমরা একটি অ্যাডেন্ড মাত্র স্টোরেজ ব্যবহার করি যা সেই অবস্থার উপর নেওয়া সমস্ত কর্মের সিরিজ রেকর্ড করে। পরবর্তী ধারণাটি CQRS, যা কমান্ড চাহিদা দায়িত্ব বিচ্ছিন্নকরণের জন্য সংক্ষিপ্ত। CQRS এক দশক আগে গ্রেজ ইয়াং দ্বারা উদ্ভাবিত হয়েছিল এবং কমান্ড এবং চাহিদা বিচ্ছিন্নকরণের নীতি থেকে উত্থাপিত হয়েছিল। মৌলিক ধারণাটি হল পাঠ এবং লিখার জন্য আলাদা ডেটা মডেল তৈরি করা, উভয় উদ্দেশ্যে একই মডেল ব্যবহার করার পরিবর্তে। CQRS প্যাটার্ন অনুসরণ করে, প্রতিটি এপিআইটি একটি কমান্ড যা একটি কাজ সম্পাদন করে, অথবা একটি চাহিদা যা ডেটা কলারকে ফেরত দেয় - কিন্তু উভয়টি নয়। এই পৃথকতা কয়েকটি সুবিধা প্রদান করে। উদাহরণস্বরূপ, আমরা খরচ দক্ষতা অপ্টিমাইজ করার জন্য লেখার এবং পড়ার ক্ষমতা স্বাধীনভাবে স্ক্যালিং করতে পারি। লেখার পক্ষের উচ্চ স্তরের ওয়ার্কফ্লোকে নিম্নলিখিতভাবে সংক্ষিপ্ত করা যেতে পারে: অনেক গেমপ্লে সেশনগুলিতে ঘটে যাওয়া ইভেন্টগুলি সীমিত সংখ্যক ইভেন্ট প্রসেসরগুলিতে সরবরাহ করা হয়। বাস্তবায়নটি সহজ, সাধারণত একটি বার্তা বাস যেমন Pulsar, Kafka, বা একটি সহজ লাইন সিস্টেম যা একটি ইভেন্ট স্টোর হিসাবে কাজ করে। ক্লায়েন্টদের ইভেন্টগুলি ইভেন্ট স্টোরে থেমে থাকে এবং ইভেন্ট প্রসেসরগুলি বিষয়গুলির জন্য সাবস্ক্রাইব করে ইভেন্টগুলি ব্যবহার করে। . পূর্বে উল্লেখিত ব্লগ যদিও রেকর্ডের মতো সিস্টেমগুলি সাধারণত এক দিক থেকে প্রবাহ (উদাহরণস্বরূপ ফ্যান-ইন) পরিচালনা করার ক্ষেত্রে কার্যকর হয়, তবে তারা প্রতিটি গেম-ইন সেশনের জন্য একটি নির্দিষ্ট রেকর্ড তৈরি করার ক্ষমতা রাখে না (উদাহরণস্বরূপ, ফ্যান-আউট)। আমাদের পরিস্থিতিতে, গেমপ্লে সেশনের সংখ্যা বড় হবে এবং একটি সাধারণ রেকর্ড সিস্টেম ভালভাবে উপযুক্ত হবে না কারণ আমরা প্রতিটি গেম-ইন সেশনের জন্য একটি নির্দিষ্ট রেকর্ড তৈরি করতে পারি না। আমরা এগিয়ে যাওয়ার আগে, এখানে আমাদের পরিষেবা আর্কিটেকচারের একটি সারসংক্ষেপ। লিখা দিক থেকে শুরু করে, গেম সার্ভার কমান্ড এন্ডপয়েন্টের মাধ্যমে আমাদের সিস্টেমে ইভেন্ট পাঠায় এবং প্রতিটি ইভেন্ট একটি নির্দিষ্ট ধরনের কার্যকলাপের প্রতিনিধিত্ব করে যা একটি গেমপ্লে সেশনে ঘটেছে। ইভেন্ট প্রসেসর প্রতিটি গেমপ্লে সেশনের ইভেন্ট স্ট্রিমের বিরুদ্ধে ফলাফল বা ম্যাট্রিক্স উত্পাদন করে এবং দুই দিকের মধ্যে একটি সেতু হিসাবে কাজ করে। টাইম সিরিজ ইভেন্টের জন্য বিতরণযোগ্য র ্যাংকিং-এক রকম ইভেন্ট স্টোর এখন চলুন দেখে নেওয়া যাক কিভাবে আমরা ScyllaDB ব্যবহার করে বিভিন্ন গেমপ্লে সেশনগুলিতে ইভেন্ট পাঠানোর সমস্যাটি সমাধান করতে পারি। বিপরীতে, যদি আপনি গুগল "ক্যাসান্দ্রা" এবং "কুই", তাহলে আপনি এক দশকেরও বেশি সময় ধরে একটি নিবন্ধের মুখোমুখি হতে পারেন যা বলে যে ক্যাসান্দ্রা একটি রিং হিসাবে ব্যবহার করা একটি অ্যান্টি-প্যাটার্ন। প্রতিটি গেমপ্লে সেশনে ইভেন্টগুলির বিতরণকে সমর্থন করার জন্য, আমরা সেশনের আইডি ব্যবহার করি পার্টিশন কী হিসাবে যাতে প্রতিটি গেমপ্লে সেশনের নিজস্ব পার্টিশন থাকে এবং একটি নির্দিষ্ট গেমপ্লে সেশনের ইভেন্টগুলি সেশনের আইডি দ্বারা কার্যকরভাবে অবস্থিত হতে পারে। প্রতিটি ইভেন্টের একটি অনন্য ইভেন্ট আইডি থাকে, যা একটি সময় UUID, গ্রাসিং কী হিসাবে। যেহেতু একই পার্শ্ববর্তী রেকর্ডগুলি গ্রাসিং কী দ্বারা সাজানো হয়, ইভেন্ট আইডিটি একটি লাইনের অবস্থান আইডি হিসাবে ব্যবহার করা যেতে পারে। এই পদ্ধতি ব্যবহার করার সময় একটি সতর্কবাণী মনে রাখা উচিত: সংশ্লিষ্টতা সমস্যা. সর্বশেষ ইভেন্ট আইডি ট্র্যাকিং দ্বারা নতুন ইভেন্টগুলি পুনরুদ্ধার করা অনুমানের উপর নির্ভর করে যে কোনও ইভেন্টটি ভবিষ্যতে ছোট আইডি সহ ঘটবে না. তবে, এই অনুমানটি সত্য হতে পারে না. উদাহরণস্বরূপ, যদি দুটি নোড একই সময়ে দুটি ইভেন্ট আইডি উৎপাদন করে তবে ছোট আইডি সহ একটি ইভেন্টটি বড় আইডি সহ একটি ইভেন্টের চেয়ে পরে ইনপুট করা যেতে পারে. এই সমস্যা, যা আমি একটি "ফ্যান্টম পাঠ" হিসাবে উল্লেখ করি, এসকিউএল জগতের ঘটনাগুলির অনুরূপ যেখানে একই প্রশ্নটি পুনরাবৃত্তি করা অন্য লেনদেন দ্বারা তৈরি পরিবর্তনগুলির কারণে ভিন্ন ফলাফল উত্পাদন করতে পারে। এই সমস্যাটি সমাধান করার কয়েকটি উপায় রয়েছে. একটি সমাধান হল একটি ক্লাস্টার-ভিত্তিক অবস্থা বজায় রাখা, যা আমি একটি "পেসডো এখন" বলি, যা সমস্ত ইভেন্ট প্রসেসরগুলির মধ্যে চলমান টাইমস্ট্যাম্পগুলির সর্বনিম্ন মানের উপর ভিত্তি করে। অন্য গুরুত্বপূর্ণ বিবেচনায় TimeWindowCompactionStrategy অনুমোদন করা হয়েছে, যা কবরের পাথরের দ্বারা উত্সাহিত নেতিবাচক কর্মক্ষমতা প্রভাবকে অপসারণ করে। কবরের পাথরগুলির সংগ্রহ একটি গুরুত্বপূর্ণ সমস্যা ছিল যা TimeWindowCompactionStrategy উপলব্ধ হওয়ার আগে ক্যাসান্ডারকে একটি লাইন হিসাবে ব্যবহার করতে বাধা দেয়। এখন আমরা ScyllaDB ব্যবহারের বাইরে অন্যান্য সুবিধাগুলি আলোচনা করার জন্য এগিয়ে যাব। জটিল গ্লোবাল ডেটা বিতরণ চ্যালেঞ্জ সহজকরণ যেহেতু আমরা বিশ্বব্যাপী গ্রাহকদের সেবা করার জন্য একটি মাল্টি-টেনেন্সি সিস্টেম তৈরি করছি, এটি নিশ্চিত করা গুরুত্বপূর্ণ যে বিভিন্ন অঞ্চলের গ্রাহক ক্লাস্টারগুলির মধ্যে গ্রাহক কনফিগারেশনগুলি একমত। আমরা এই সমস্যাটি সমাধান করেছি কেবলমাত্র সমস্ত ডাটা সেন্টারগুলিতে একটি কী স্পেসে ডেটা পুনরাবৃত্তি অনুমোদন করে. এর মানে হল যে কোনও পরিবর্তন এক ডেটা সেন্টারে শেষ পর্যন্ত অন্যদের কাছে ছড়িয়ে পড়বে. ধন্যবাদ ScyllaDB, পাশাপাশি DynamoDB এবং Cassandra, এই চ্যালেঞ্জিং সমস্যাটি সামান্য মনে করে এমন ভারী লিফিংয়ের জন্য। আপনি মনে করতে পারেন যে কোনও সাধারণ RDBMS ব্যবহার করে একই ফলাফল অর্জন করতে পারে কারণ অধিকাংশ ডাটাবেস ডেটা রিপ্লিকেশন সমর্থন করে। এটি সত্য যদি একটি নির্দিষ্ট অঞ্চলে চালিত কন্ট্রোল প্যানেলের শুধুমাত্র একটি ইন্সটাফরেকশন থাকে। একটি সাধারণ প্রাথমিক / রিপ্লিকেশন আর্কিটেকচারে, শুধুমাত্র প্রাথমিক নোডটি পড়া / লিখা সমর্থন করে যখন রিপ্লিকেশন নোডগুলি শুধুমাত্র পড়া হয়। তবে, যখন আপনি বিভিন্ন অঞ্চলে কন্ট্রোল প্যানেলের একাধিক ইন্সটাফরেকশন চালানোর প্রয়োজন – উদাহরণস্বরূপ, প্রতিটি লেনদেনের একটি কন্ট্রোল প্যানেল আপনি যদি AWS DynamoDB ব্যবহার করেন, তাহলে আপনি গ্লোবাল টেবিল নামক একটি বৈশিষ্ট্যের সাথে পরিচিত হতে পারেন, যা অ্যাপ্লিকেশনগুলিকে স্থানীয়ভাবে পড়তে এবং লিখতে এবং বিশ্বব্যাপী ডেটা অ্যাক্সেস করতে দেয়। ডাটা কনটেইনার হিসাবে Keyspaces পরবর্তীতে, আমরা কীভাবে আমরা গ্লোবাল ডেটা বিতরণের স্বচ্ছতা উন্নত করার জন্য ডেটা কন্টেইনার হিসাবে কী স্পেস ব্যবহার করি তা দেখি। নীচের চার্টটি দেখুন. এটি ডেটা সুরক্ষা আইন দ্বারা বাধ্য করা একটি সাধারণ ডেটা বিতরণ সমস্যার সমাধান দেখায়. উদাহরণস্বরূপ, আশা করি অঞ্চল A তার সীমানাগুলির বাইরে নির্দিষ্ট ধরনের ডেটা প্রক্রিয়াকরণের অনুমতি দেয় যতক্ষণ না একটি মূল কপি তার অঞ্চলে সংরক্ষিত হয়. একটি পণ্য মালিক হিসাবে, আপনি কিভাবে নিশ্চিত করতে পারেন যে আপনার সমস্ত অ্যাপ্লিকেশনগুলি এই নিয়মের সাথে সামঞ্জস্যপূর্ণ? *আপনি *আপনি একটি সম্ভাব্য সমাধান হল অ্যাপ্লিকেশনগুলি প্রত্যাশিত হিসাবে সঠিক ডেটা সঠিকভাবে সঠিক অঞ্চলে পাঠানোর জন্য এন্ড-টোয়েন্টি (E2E) পরীক্ষাগুলি পরিচালনা করা। এই পদ্ধতিটি অ্যাপ্লিকেশন ডেটা বিতরণ সঠিকভাবে বাস্তবায়নের জন্য অ্যাপ্লিকেশন ডেভেলপারদের সম্পূর্ণ দায়িত্ব নেওয়ার প্রয়োজন। কীবোর্ডে ডেটা পুনরাবৃত্তি সক্ষম করে, আমরা ডেটা সঠিকভাবে বিতরণের দায়িত্বকে দুটি কাজে বিভক্ত করতে পারি: 1) ডেটা ধরনের সনাক্তকরণ এবং তাদের গন্তব্য ঘোষণা এবং 2) ডেটা কপি বা প্রত্যাশিত অবস্থানগুলিতে স্থানান্তর। এই দুটি দায়িত্বকে আলাদা করে, আমরা অ্যাপ্লিকেশন থেকে জটিল কনফিগারেশন এবং নিয়মগুলি আলাদা করতে পারি কারণ অন্য অঞ্চলে ডেটা স্থানান্তর করার প্রক্রিয়াটি প্রায়ই নেটওয়ার্ক সীমানাগুলি অতিক্রম করে, সঠিকভাবে ট্র্যাফিক এনক্রিপশন করে এবং বিরতিগুলি পরিচালনা করে। এই দুটি দায়িত্ব পৃথক করার পরে, অ্যাপ্লিকেশনগুলি শুধুমাত্র প্রথম ধাপটি সঠিকভাবে সম্পাদনা করতে হবে, যা উন্নয়ন চক্রের পূর্ববর্তী পর্যায়ে পরীক্ষার মাধ্যমে যাচাই করা অনেক সহজ। অন্যদের জন্য টিপস যারা একটি অনুরূপ পথ গ্রহণ চূড়ান্তভাবে, আমরা আপনাকে গুরুত্বপূর্ণ পাঠ দেব যা আমরা শিখেছি এবং আমরা আপনাকে সুপারিশ করি যে আপনি যদি আমাদের মত একটি পথ গ্রহণ করেন: সময় সিরিজের ডেটা হস্তান্তর করার জন্য ScyllaDB ব্যবহার করার সময়, যেমন এটি একটি ইভেন্ট-ডাসপেটিং রিং হিসাবে ব্যবহার করার সময়, সময় উইন্ডো কম্প্যাকশন কৌশল ব্যবহার করতে মনে রাখবেন। ডেটা বিতরণের দায়িত্বকে আলাদা করার জন্য কী স্পেসগুলি ডেটা কনটেইনার হিসাবে ব্যবহার করে বিবেচনা করুন. This can make complex data distribution problems much easier to manage. Tech Talks On-Demand দেখুন এই নিবন্ধটি ScyllaDB Summit 2023 এ উপস্থাপিত একটি প্রযুক্তি আলোচনার উপর ভিত্তি করে। চাহিদা অনুযায়ী প্রযুক্তি আলোচনা দেখুন