NewSQL = NoSQL+ACID

NewSQL = NoSQL+ACID
До недавнего времени в Одноклассниках около 50 ТБ данных, обрабатываемых в реальном времени, хранилось в SQL Server. Для такого объема обеспечить быстрый и надежный, да еще и устойчивый к отказу ЦОД доступ, используя SQL СУБД, практически невозможно. Обычно в таких случаях используют одно из NoSQL-хранилищ, но не всё можно перенести в NoSQL: некоторые сущности требуют гарантий ACID-транзакций.

اس نے ہمیں NewSQL سٹوریج کے استعمال کی طرف لے جایا، یعنی ایک DBMS جو NoSQL سسٹمز کی غلطی برداشت، اسکیل ایبلٹی اور کارکردگی فراہم کرتا ہے، لیکن ساتھ ہی ساتھ ACID کو برقرار رکھنا کلاسیکی نظاموں سے واقفیت کی ضمانت دیتا ہے۔ اس نئے طبقے کے چند کام کرنے والے صنعتی نظام ہیں، اس لیے ہم نے خود ایسا نظام نافذ کیا اور اسے کمرشل آپریشن میں ڈال دیا۔

یہ کیسے کام کرتا ہے اور کیا ہوا - کٹ کے نیچے پڑھیں۔

آج، Odnoklassniki کے ماہانہ سامعین 70 ملین سے زیادہ منفرد زائرین ہیں۔ ہم входим в пятерку крупнейших соцсетей мира, и в двадцатку сайтов, на которых пользователи проводят больше всего времени. Инфраструктура «ОК» обрабатывает очень высокие нагрузки: более миллиона HTTP-запросов/сек на фронты. Части парка серверов в количестве более 8000 штук расположены близко друг от друга — в четырех московских дата-центрах, что позволяет обеспечивать сетевую задержку менее 1 мс между ними.

Мы используем Cassandra с 2010 года, начиная с версии 0.6. Сегодня в эксплуатации несколько десятков кластеров. Самый быстрый кластер обрабатывает более 4 млн операций в секунду, а крупнейший хранит 260 Тб.

Однако всё это обычные NoSQL-кластеры, использующиеся для хранения کمزور مربوط ڈیٹا ہم بنیادی مستقل اسٹوریج، مائیکروسافٹ ایس کیو ایل سرور کو تبدیل کرنا چاہتے تھے، جو Odnoklassniki کے قیام کے بعد سے استعمال کیا جا رہا ہے۔ سٹوریج میں 300 سے زیادہ SQL سرور سٹینڈرڈ ایڈیشن مشینیں شامل تھیں، جن میں 50 TB ڈیٹا - کاروباری اداروں کا تھا۔ اس ڈیٹا میں ACID ٹرانزیکشنز کے حصے کے طور پر ترمیم کی گئی ہے اور اس کی ضرورت ہے۔ اعلی مستقل مزاجی.

ایس کیو ایل سرور نوڈس میں ڈیٹا تقسیم کرنے کے لیے، ہم نے عمودی اور افقی دونوں کا استعمال کیا۔ партиционирование (شارڈنگ)۔ تاریخی طور پر، ہم نے ایک سادہ ڈیٹا شارڈنگ اسکیم کا استعمال کیا: ہر ہستی ایک ٹوکن سے منسلک تھی - entity ID کا ایک فنکشن۔ ایک ہی ٹوکن والی ہستیوں کو ایک ہی SQL سرور پر رکھا گیا تھا۔ ماسٹر ڈیٹیل ریلیشن شپ کو لاگو کیا گیا تھا تاکہ مین اور چائلڈ ریکارڈز کے ٹوکن ہمیشہ مماثل ہوں اور ایک ہی سرور پر واقع ہوں۔ سوشل نیٹ ورک میں، تقریباً تمام ریکارڈز صارف کی جانب سے تیار کیے جاتے ہیں - جس کا مطلب یہ ہے کہ ایک فنکشنل سب سسٹم کے اندر صارف کا تمام ڈیٹا ایک سرور پر محفوظ کیا جاتا ہے۔ یعنی، ایک کاروباری لین دین میں تقریباً ہمیشہ ایک ایس کیو ایل سرور سے ٹیبل شامل ہوتے ہیں، جس نے مقامی ACID ٹرانزیکشنز کا استعمال کرتے ہوئے ڈیٹا کی مستقل مزاجی کو یقینی بنایا، بغیر استعمال کے۔ سست اور ناقابل اعتماد تقسیم شدہ ACID ٹرانزیکشنز۔

شارڈنگ اور ایس کیو ایل کو تیز کرنے کا شکریہ:

  • ہم غیر ملکی کلیدی رکاوٹوں کا استعمال نہیں کرتے ہیں، کیونکہ جب ہستی ID کو شارڈ کیا جائے تو دوسرے سرور پر واقع ہو سکتا ہے۔
  • DBMS CPU پر اضافی بوجھ کی وجہ سے ہم ذخیرہ شدہ طریقہ کار اور محرکات استعمال نہیں کرتے ہیں۔
  • ہم اوپر کی تمام چیزوں اور ڈسک سے بے ترتیب پڑھنے کی وجہ سے JOINs کا استعمال نہیں کرتے ہیں۔
  • لین دین کے باہر، ہم تعطل کو کم کرنے کے لیے غیر متعلقہ تنہائی کی سطح کا استعمال کرتے ہیں۔
  • ہم صرف مختصر لین دین کرتے ہیں (اوسطاً 100 ایم ایس سے کم)۔
  • تعطل کی بڑی تعداد کی وجہ سے ہم ملٹی قطار اپ ڈیٹ اور ڈیلیٹ کا استعمال نہیں کرتے ہیں - ہم ایک وقت میں صرف ایک ریکارڈ اپ ڈیٹ کرتے ہیں۔
  • ہم ہمیشہ استفسارات صرف اشاریہ جات پر کرتے ہیں - ہمارے لیے مکمل ٹیبل اسکین پلان کے ساتھ استفسار کا مطلب ڈیٹا بیس کو اوورلوڈ کرنا اور اسے ناکام بنانا ہے۔

ان اقدامات نے ہمیں SQL سرورز سے تقریباً زیادہ سے زیادہ کارکردگی کو نچوڑنے کی اجازت دی۔ تاہم، مسائل زیادہ سے زیادہ بے شمار ہوتے گئے. آئیے ان کو دیکھتے ہیں۔

ایس کیو ایل کے ساتھ مسائل

  • چونکہ ہم نے خود تحریری شارڈنگ کا استعمال کیا ہے، نئے شارڈز کو شامل کرنا منتظمین کے ذریعہ دستی طور پر کیا گیا تھا۔ اس سارے عرصے میں، قابل توسیع ڈیٹا کی نقلیں درخواستوں کی خدمت نہیں کر رہی تھیں۔
  • جیسے جیسے ٹیبل میں ریکارڈز کی تعداد بڑھتی ہے، اندراج اور ترمیم کی رفتار کم ہوتی جاتی ہے؛ موجودہ ٹیبل میں اشاریہ جات کو شامل کرتے وقت، رفتار ایک عنصر سے گر جاتی ہے؛ اشاریہ جات کی تخلیق اور دوبارہ تخلیق ڈاؤن ٹائم کے ساتھ ہوتی ہے۔
  • پروڈکشن میں SQL سرور کے لیے ونڈوز کی تھوڑی مقدار رکھنے سے انفراسٹرکچر کا انتظام مشکل ہو جاتا ہے۔

لیکن اصل مسئلہ یہ ہے۔

غلطی کی رواداری

کلاسک ایس کیو ایل سرور میں خرابی کی رواداری ہے۔ فرض کریں کہ آپ کے پاس صرف ایک ڈیٹا بیس سرور ہے، اور یہ ہر تین سال میں ایک بار ناکام ہو جاتا ہے۔ اس دوران سائٹ 20 منٹ تک بند رہتی ہے، جو قابل قبول ہے۔ اگر آپ کے پاس 64 سرور ہیں، تو سائٹ ہر تین ہفتوں میں ایک بار ڈاؤن ہوتی ہے۔ اور اگر آپ کے پاس 200 سرور ہیں، تو سائٹ ہر ہفتے کام نہیں کرتی۔ یہ مسئلہ ہے۔

ایس کیو ایل سرور کی فالٹ ٹولرنس کو بہتر بنانے کے لیے کیا کیا جا سکتا ہے؟ ویکیپیڈیا ہمیں تعمیر کرنے کی دعوت دیتا ہے۔ انتہائی دستیاب کلسٹر: جہاں کسی بھی اجزاء کی ناکامی کی صورت میں ایک بیک اپ ہوتا ہے۔

اس کے لیے مہنگے آلات کے بیڑے کی ضرورت ہوتی ہے: متعدد نقلیں، آپٹیکل فائبر، مشترکہ اسٹوریج، اور ریزرو کی شمولیت قابل اعتماد طریقے سے کام نہیں کرتی: تقریباً 10% سوئچنگ کا اختتام مرکزی نوڈ کے پیچھے ٹرین کی طرح بیک اپ نوڈ کی ناکامی پر ہوتا ہے۔

Но главный недостаток такого высокодоступного кластера — нулевая доступность при отказе дата-центра, в котором он стоит. У «Одноклассников» четыре дата-центра, и нам необходимо обеспечивать работу при полной аварии в одном из них.

اس کے لیے ہم استعمال کر سکتے ہیں۔ Multi-Master ایس کیو ایل سرور میں تیار کردہ نقل۔ سافٹ ویئر کی لاگت کی وجہ سے یہ حل بہت زیادہ مہنگا ہے اور نقل کے ساتھ معروف مسائل سے دوچار ہے - ہم وقت ساز نقل کے ساتھ غیر متوقع لین دین میں تاخیر اور غیر مطابقت پذیر نقل کے ساتھ نقل (اور اس کے نتیجے میں، گمشدہ ترمیمات) کو لاگو کرنے میں تاخیر۔ مضمر دستی تنازعات کا حل اس اختیار کو ہمارے لیے مکمل طور پر ناقابل اطلاق بنا دیتا ہے۔

Все эти проблемы требовали кардинального решения и мы приступили к их детальному анализу. Здесь нам нужно познакомиться с тем, что в основном делает SQL Server — транзакциями.

Простая транзакция

آئیے ایک اپلائیڈ ایس کیو ایل پروگرامر کے نقطہ نظر سے آسان ترین لین دین پر غور کریں: البم میں تصویر شامل کرنا۔ البمز اور تصاویر مختلف پلیٹوں میں محفوظ ہیں۔ البم میں عوامی تصویر کا کاؤنٹر ہے۔ پھر اس طرح کے لین دین کو درج ذیل مراحل میں تقسیم کیا گیا ہے۔

  1. Блокируем альбом по ключу.
  2. فوٹو ٹیبل میں ایک اندراج بنائیں۔
  3. Если у фотографии публичный статус, то накручиваем в альбоме счетчик публичных фотографий, обновляем запись и коммитим транзакцию.

یا pseudocode میں:

TX.start("Albums", id);
Album album = albums.lock(id);
Photo photo = photos.create(…);

if (photo.status == PUBLIC ) {
    album.incPublicPhotosCount();
}
album.update();

TX.commit();

Мы видим, что самый распространённый сценарий бизнес транзакции — прочитать данные из БД в память сервера приложений, что-то изменить и сохранить новые значения обратно в БД. Обычно в такой транзакции мы обновляем несколько сущностей, несколько таблиц.

ایک ٹرانزیکشن کو انجام دیتے وقت، دوسرے سسٹم سے اسی ڈیٹا کی ہم آہنگی میں ترمیم ہو سکتی ہے۔ مثال کے طور پر، Antispam فیصلہ کر سکتا ہے کہ صارف کسی نہ کسی طرح مشکوک ہے اور اس لیے صارف کی تمام تصاویر کو مزید عوامی نہیں ہونا چاہیے، انہیں اعتدال کے لیے بھیجنے کی ضرورت ہے، جس کا مطلب ہے photo.status کو کسی اور قدر میں تبدیل کرنا اور متعلقہ کاؤنٹرز کو بند کرنا۔ ظاہر ہے، اگر یہ آپریشن اطلاق کے جوہری ہونے اور مسابقتی ترمیمات کو الگ تھلگ کرنے کی ضمانت کے بغیر ہوتا ہے، جیسا کہ ایسڈ، پھر نتیجہ وہ نہیں ہوگا جس کی ضرورت ہے - یا تو فوٹو کاؤنٹر غلط قیمت دکھائے گا، یا تمام تصاویر اعتدال کے لیے نہیں بھیجی جائیں گی۔

Подобного кода, манипулирующего с различными бизнес-сущностями в рамках одной транзакции, за всё время существования Одноклассников написано очень много. По опыту же миграций на NoSQL с حتمی مستقل مزاجی ہم جانتے ہیں کہ سب سے بڑا چیلنج (اور وقت کی سرمایہ کاری) ڈیٹا کی مستقل مزاجی کو برقرار رکھنے کے لیے کوڈ تیار کرنے سے آتا ہے۔ لہذا، ہم نے نئے سٹوریج کے لیے اصل ضرورت کو ایپلی کیشن لاجک کے لیے حقیقی ACID ٹرانزیکشنز کی فراہمی پر غور کیا۔

دیگر، کم اہم نہیں، ضروریات یہ تھیں:

  • اگر ڈیٹا سینٹر ناکام ہو جاتا ہے، تو نئے اسٹوریج میں پڑھنا اور لکھنا دونوں دستیاب ہونا چاہیے۔
  • Сохранение текущей скорости разработки. То есть при работе с новым хранилищем количество кода должно быть приблизительно тем же самым, не должно появляться необходимости дописывать что-то в хранилище, разрабатывать алгоритмы разрешения конфликтов, поддержания вторичных индексов и т.п.
  • Скорость работы нового хранилища должна быть достаточно высокой, как при чтении данных, так и при обработке транзакций, что эффективно означало неприменимость академически строгих, универсальных, но медленных решений, как, например, دو فیز کمٹ.
  • خودکار آن دی فلائی اسکیلنگ۔
  • غیر ملکی ہارڈ ویئر خریدنے کی ضرورت کے بغیر، باقاعدہ سستے سرورز کا استعمال۔
  • Возможность развития хранилища силами разработчиков компании. Иными словами, приоритет отдавался своим или основанным на открытом коде решениям, желательно на Java.

فیصلے، فیصلے

Анализируя возможные решения, мы пришли к двум возможным выборам архитектуры:

سب سے پہلے کسی بھی ایس کیو ایل سرور کو لینا اور مطلوبہ فالٹ ٹولرنس، اسکیلنگ میکانزم، فیل اوور کلسٹر، تنازعات کا حل اور تقسیم شدہ، قابل اعتماد اور تیز رفتار ACID ٹرانزیکشنز کو نافذ کرنا ہے۔ ہم نے اس اختیار کو انتہائی غیر معمولی اور محنت طلب قرار دیا۔

Второй вариант — взять готовое NoSQL-хранилище с реализованным масштабированием, отказоустойчивым кластером, разрешением конфликтов и реализовать транзакции и SQL самим. На первый взгляд даже задача реализации SQL, не говоря уж об ACID транзакциях, выглядит задачкой на года. Но потом мы поняли, что набор возможностей SQL, который мы используем на практике, далек от ANSI SQL так же далеко, как کیسینڈرا سی کیو ایل ANSI SQL سے بہت دور۔ سی کیو ایل پر مزید گہری نظر ڈالتے ہوئے، ہم نے محسوس کیا کہ یہ ہماری ضرورت کے بالکل قریب تھا۔

Cassandra и CQL

تو، کیسینڈرا کے بارے میں کیا دلچسپ ہے، اس میں کیا صلاحیتیں ہیں؟

سب سے پہلے، یہاں آپ مختلف قسم کے ڈیٹا کو سپورٹ کرنے والے ٹیبل بنا سکتے ہیں؛ آپ بنیادی کلید پر SELECT یا UPDATE کر سکتے ہیں۔

CREATE TABLE photos (id bigint KEY, owner bigint,…);
SELECT * FROM photos WHERE id=?;
UPDATE photos SET … WHERE id=?;

نقل ڈیٹا کی مستقل مزاجی کو یقینی بنانے کے لیے، کیسینڈرا استعمال کرتی ہے۔ کورم نقطہ نظر. سادہ ترین صورت میں، اس کا مطلب یہ ہے کہ جب ایک ہی قطار کی تین نقلیں کلسٹر کے مختلف نوڈس پر رکھی جاتی ہیں، تو تحریر کو کامیاب سمجھا جاتا ہے اگر نوڈس کی اکثریت (یعنی تین میں سے دو) اس تحریری آپریشن کی کامیابی کی تصدیق کرتی ہے۔ . قطار کے اعداد و شمار کو مستقل سمجھا جاتا ہے اگر، پڑھتے وقت، نوڈس کی اکثریت پول ہوئی اور ان کی تصدیق کی گئی۔ اس طرح، تین نقلوں کے ساتھ، مکمل اور فوری ڈیٹا کی مستقل مزاجی کی ضمانت دی جاتی ہے اگر ایک نوڈ ناکام ہوجاتا ہے۔ اس نقطہ نظر نے ہمیں ایک اور بھی زیادہ قابل اعتماد اسکیم کو نافذ کرنے کی اجازت دی: ہمیشہ تینوں نقلوں کو درخواستیں بھیجیں، دو تیز ترین لوگوں کے جواب کا انتظار کریں۔ اس معاملے میں تیسری نقل کے دیر سے جواب کو رد کر دیا گیا ہے۔ ایک نوڈ جو جواب دینے میں دیر کر رہا ہے اس میں سنگین مسائل ہو سکتے ہیں - بریک، JVM میں کچرا جمع کرنا، لینکس کرنل میں براہ راست میموری کا دوبارہ دعوی کرنا، ہارڈ ویئر کی ناکامی، نیٹ ورک سے رابطہ منقطع ہونا۔ تاہم، یہ کسی بھی طرح سے کلائنٹ کے آپریشنز یا ڈیٹا کو متاثر نہیں کرتا ہے۔

نقطہ نظر جب ہم تین نوڈس سے رابطہ کرتے ہیں اور دو سے جواب وصول کرتے ہیں تو اسے کہا جاتا ہے۔ قیاس: اضافی نقلوں کی درخواست "گرنے" سے پہلے ہی بھیجی جاتی ہے۔

Cassandra کا ایک اور فائدہ Batchlog ہے، ایک ایسا طریقہ کار جو اس بات کو یقینی بناتا ہے کہ آپ کی تبدیلیوں کا ایک بیچ یا تو مکمل طور پر لاگو ہوتا ہے یا بالکل لاگو نہیں ہوتا ہے۔ یہ ہمیں ACID میں A کو حل کرنے کی اجازت دیتا ہے - باکس سے باہر جوہری۔

کیسینڈرا میں لین دین کی قریب ترین چیز نام نہاد "lightweight transactions" لیکن وہ "حقیقی" ACID لین دین سے بہت دور ہیں: حقیقت میں، یہ کرنے کا ایک موقع ہے۔ سی اے ایس ہیوی ویٹ Paxos پروٹوکول کا استعمال کرتے ہوئے اتفاق رائے کا استعمال کرتے ہوئے، صرف ایک ریکارڈ سے ڈیٹا پر۔ لہذا، اس طرح کے لین دین کی رفتار کم ہے.

کیسینڈرا میں ہم کیا کھو رہے تھے۔

لہذا، ہمیں کیسنڈرا میں حقیقی ACID لین دین کو لاگو کرنا پڑا۔ جس کا استعمال کرتے ہوئے ہم کلاسک DBMS کی دو دیگر آسان خصوصیات کو آسانی سے نافذ کر سکتے ہیں: مستقل تیز انڈیکسز، جو ہمیں نہ صرف بنیادی کلید کے ذریعے ڈیٹا کا انتخاب کرنے کی اجازت دیتا ہے، اور monotonic auto-incrementing IDs کا باقاعدہ جنریٹر۔

سی* ایک

اس طرح ایک نیا DBMS پیدا ہوا۔ سی* ایک، تین قسم کے سرور نوڈس پر مشتمل ہے:

  • سٹوریج - (تقریباً) معیاری کیسینڈرا سرورز جو مقامی ڈسکوں پر ڈیٹا ذخیرہ کرنے کے لیے ذمہ دار ہیں۔ جیسے جیسے ڈیٹا کا بوجھ اور حجم بڑھتا ہے، ان کی مقدار کو آسانی سے دسیوں اور سینکڑوں تک بڑھایا جا سکتا ہے۔
  • ٹرانزیکشن کوآرڈینیٹرز - لین دین کے عمل کو یقینی بنائیں۔
  • کلائنٹس ایپلیکیشن سرورز ہیں جو کاروباری آپریشنز کو نافذ کرتے ہیں اور لین دین شروع کرتے ہیں۔ ایسے ہزاروں کلائنٹ ہو سکتے ہیں۔

NewSQL = NoSQL+ACID

تمام اقسام کے سرور ایک مشترکہ کلسٹر کا حصہ ہیں، ایک دوسرے کے ساتھ بات چیت کرنے کے لیے اندرونی کیسنڈرا میسج پروٹوکول کا استعمال کریں اور گپ شپ کلسٹر معلومات کے تبادلے کے لیے۔ ہارٹ بیٹ کے ساتھ، سرور باہمی ناکامیوں کے بارے میں سیکھتے ہیں، ایک واحد ڈیٹا اسکیما کو برقرار رکھتے ہیں - میزیں، ان کی ساخت اور نقل؛ تقسیم کاری اسکیم، کلسٹر ٹوپولوجی، وغیرہ۔

گاہک

NewSQL = NoSQL+ACID

معیاری ڈرائیوروں کے بجائے، موٹی کلائنٹ موڈ استعمال کیا جاتا ہے. اس طرح کا نوڈ ڈیٹا کو ذخیرہ نہیں کرتا ہے، لیکن درخواست پر عمل درآمد کے لیے کوآرڈینیٹر کے طور پر کام کر سکتا ہے، یعنی کلائنٹ خود اپنی درخواستوں کے کوآرڈینیٹر کے طور پر کام کرتا ہے: یہ سٹوریج کی نقلوں سے استفسار کرتا ہے اور تنازعات کو حل کرتا ہے۔ یہ نہ صرف معیاری ڈرائیور سے زیادہ قابل اعتماد اور تیز ہے، جس کے لیے ریموٹ کوآرڈینیٹر کے ساتھ بات چیت کی ضرورت ہوتی ہے، بلکہ یہ آپ کو درخواستوں کی ترسیل کو کنٹرول کرنے کی بھی اجازت دیتا ہے۔ کلائنٹ پر کھلے ٹرانزیکشن کے باہر، ریپوزٹری کو درخواستیں بھیجی جاتی ہیں۔ اگر کلائنٹ نے ٹرانزیکشن کھولی ہے، تو ٹرانزیکشن کے اندر تمام درخواستیں ٹرانزیکشن کوآرڈینیٹر کو بھیجی جاتی ہیں۔
NewSQL = NoSQL+ACID

C*ون ٹرانزیکشن کوآرڈینیٹر

Координатор — то, что мы реализовали для C*One с нуля. Он отвечает за управление транзакциями, блокировками и порядком применения транзакций.

ہر سروسڈ ٹرانزیکشن کے لیے، کوآرڈینیٹر ٹائم اسٹیمپ تیار کرتا ہے: ہر بعد کی ٹرانزیکشن پچھلی ٹرانزیکشن سے زیادہ ہوتی ہے۔ چونکہ کیسینڈرا کا تنازعات کے حل کا نظام ٹائم اسٹیمپ پر مبنی ہے (دو متضاد ریکارڈوں میں سے، تازہ ترین ٹائم اسٹیمپ والا موجودہ سمجھا جاتا ہے)، تنازعہ کو ہمیشہ بعد کے لین دین کے حق میں حل کیا جائے گا۔ اس طرح ہم نے عمل درآمد کیا۔ لیمپورٹ گھڑی - تقسیم شدہ نظام میں تنازعات کو حل کرنے کا ایک سستا طریقہ۔

تالے

Для обеспечения изоляции мы решили использовать самый простой способ — пессимистичные блокировки по первичному ключу записи. Другими словами, в транзакции запись необходимо сначала заблокировать, только затем прочитать, модифицировать и сохранить. Только после успешного коммита запись может быть разблокирована, чтобы конкурирующие транзакции могли ее использовать.

غیر تقسیم شدہ ماحول میں اس طرح کی تالا لگانا آسان ہے۔ تقسیم شدہ نظام میں، دو اہم اختیارات ہوتے ہیں: یا تو کلسٹر پر ڈسٹری بیوٹڈ لاکنگ کو لاگو کریں، یا لین دین کو تقسیم کریں تاکہ ایک ہی ریکارڈ پر مشتمل لین دین ہمیشہ ایک ہی کوآرڈینیٹر کے ذریعہ پیش کیا جائے۔

چونکہ ہمارے معاملے میں ڈیٹا پہلے ہی ایس کیو ایل میں مقامی لین دین کے گروپوں میں تقسیم کیا جاتا ہے، اس لیے مقامی ٹرانزیکشن گروپس کو کوآرڈینیٹرز کو تفویض کرنے کا فیصلہ کیا گیا: ایک کوآرڈینیٹر 0 سے 9 تک کے ٹوکنز کے ساتھ تمام لین دین کرتا ہے، دوسرا - 10 سے 19 تک کے ٹوکنز کے ساتھ، اور اسی طرح. نتیجے کے طور پر، کوآرڈینیٹر مثالوں میں سے ہر ایک ٹرانزیکشن گروپ کا ماسٹر بن جاتا ہے۔

اس کے بعد کوآرڈینیٹر کی یاد میں ایک عام HashMap کی شکل میں تالے لاگو کیے جا سکتے ہیں۔

کوآرڈینیٹر کی ناکامی۔

چونکہ ایک کوآرڈینیٹر خصوصی طور پر لین دین کے ایک گروپ کی خدمت کرتا ہے، اس لیے اس کی ناکامی کی حقیقت کا فوری تعین کرنا بہت ضروری ہے تاکہ لین دین کو انجام دینے کی دوسری کوشش کا وقت ختم ہو جائے۔ اسے تیز اور قابل اعتماد بنانے کے لیے، ہم نے مکمل طور پر مربوط کورم ہیئر بیٹ پروٹوکول کا استعمال کیا:

ہر ڈیٹا سینٹر کم از کم دو کوآرڈینیٹر نوڈس کی میزبانی کرتا ہے۔ وقتاً فوقتاً، ہر کوآرڈینیٹر دوسرے کوآرڈینیٹرز کو دل کی دھڑکن کا پیغام بھیجتا ہے اور انہیں اس کے کام کرنے کے بارے میں آگاہ کرتا ہے، اور ساتھ ہی اسے آخری بار کلسٹر میں کن کوآرڈینیٹرز سے دل کی دھڑکن کے کون سے پیغامات موصول ہوئے تھے۔

NewSQL = NoSQL+ACID

Получая аналогичную информацию от остальных в составе их heartbeat-сообщений, каждый координатор решает для себя, какие ноды кластера функционируют, а какие нет, руководствуясь принципом кворума: если нода Х получила от большинства нод в кластере информацию о нормальном получении сообщений с ноды Y, значит, Y работает. И наоборот, как только большинство сообщит о пропаже сообщений с ноды Y, значит, Y отказал. Любопытно, что если кворум сообщит ноде Х, что не получает от нее более сообщений, значит сама нода X будет считать себя отказавшей.

دل کی دھڑکن کے پیغامات ہائی فریکوئنسی کے ساتھ بھیجے جاتے ہیں، تقریباً 20 بار فی سیکنڈ، 50 ایم ایس کی مدت کے ساتھ۔ جاوا میں، ردی کی ٹوکری جمع کرنے والے کی وجہ سے وقفے کی لمبائی کی وجہ سے 50 ایم ایس کے اندر درخواست کے جواب کی ضمانت دینا مشکل ہے۔ ہم G1 ردی کی ٹوکری کے جمع کرنے والے کا استعمال کرتے ہوئے اس جوابی وقت کو حاصل کرنے کے قابل تھے، جو ہمیں GC کے وقفوں کی مدت کے لیے ایک ہدف کی وضاحت کرنے کی اجازت دیتا ہے۔ تاہم، بعض اوقات، بہت ہی کم، کلکٹر کا وقفہ 50 ایم ایس سے زیادہ ہوتا ہے، جو غلط غلطی کا پتہ لگانے کا باعث بن سکتا ہے۔ ایسا ہونے سے روکنے کے لیے، کوآرڈینیٹر ریموٹ نوڈ کی ناکامی کی اطلاع نہیں دیتا جب اس سے دل کی دھڑکن کا پہلا پیغام غائب ہو جاتا ہے، صرف اس صورت میں جب کئی مسلسل غائب ہو گئے ہوں۔ MS.

لیکن یہ جلدی سمجھنا کافی نہیں ہے کہ کون سے نوڈ نے کام کرنا بند کر دیا ہے۔ ہمیں اس بارے میں کچھ کرنے کی ضرورت ہے۔

بکنگ

کلاسک اسکیم میں، ماسٹر کی ناکامی کی صورت میں، ان میں سے کسی ایک کا استعمال کرتے ہوئے نیا الیکشن شروع کرنا شامل ہے۔ فیشن ایبل عالمگیر алгоритмов. Однако, у подобных алгоритмов есть хорошо известные проблемы со сходимостью во времени и длительностью самого процесса выборов. Подобных дополнительных задержек нам удалось избежать с помощью схемы замещения координаторов в полносвязной сети:

NewSQL = NoSQL+ACID

Допустим, мы хотим выполнить транзакцию в группе 50. Заранее определим схему замещения, то есть какие ноды будут исполнять транзакции 50 группы в случае отказа основного координатора. Наша цель — сохранить работоспособность системы при отказе дата-центра. Определим, что первым резервом будет нода из другого дата-центра, а вторым резервом — нода из третьего. Эта схема выбирается один раз и не меняется до тех пор, пока не поменяется топология кластера, то есть пока в него не войдут новые ноды (что случается очень редко). Порядок выбора нового активного мастера при отказе старого будет всегда таким: активным мастером станет первый резерв, а если и он перестал функционировать — второй резерв.

یہ اسکیم عالمگیر الگورتھم سے زیادہ قابل اعتماد ہے، کیونکہ نئے ماسٹر کو چالو کرنے کے لیے یہ پرانے کی ناکامی کا تعین کرنے کے لیے کافی ہے۔

لیکن کلائنٹ کیسے سمجھیں گے کہ اب کون سا ماسٹر کام کر رہا ہے؟ 50 ms میں ہزاروں کلائنٹس کو معلومات بھیجنا ناممکن ہے۔ ایسی صورت حال ممکن ہے جب کوئی کلائنٹ ٹرانزیکشن کھولنے کی درخواست بھیجتا ہے، اسے یہ معلوم نہیں ہوتا کہ یہ ماسٹر اب کام نہیں کر رہا ہے، اور درخواست کا وقت ختم ہو جائے گا۔ ایسا ہونے سے روکنے کے لیے، کلائنٹس قیاس آرائی کے ساتھ گروپ ماسٹر اور اس کے دونوں ذخائر کو ایک ساتھ لین دین کھولنے کی درخواست بھیجتے ہیں، لیکن صرف وہی جو اس وقت فعال ماسٹر ہے اس درخواست کا جواب دے گا۔ کلائنٹ صرف ایکٹو ماسٹر کے ساتھ لین دین کے اندر تمام بعد کی بات چیت کرے گا۔

بیک اپ ماسٹرز پلیس کو ان لین دین کے لیے درخواستیں موصول ہوتی ہیں جو ان کی نہیں ہیں غیر پیدائشی لین دین کی قطار میں، جہاں انہیں کچھ وقت کے لیے محفوظ کیا جاتا ہے۔ اگر ایکٹو ماسٹر مر جاتا ہے، تو نیا ماسٹر اپنی قطار سے لین دین کھولنے کی درخواستوں پر کارروائی کرتا ہے اور کلائنٹ کو جواب دیتا ہے۔ اگر کلائنٹ نے پہلے ہی پرانے ماسٹر کے ساتھ ایک ٹرانزیکشن کھول دیا ہے، تو دوسرے جواب کو نظر انداز کر دیا جاتا ہے (اور، ظاہر ہے، اس طرح کا لین دین مکمل نہیں ہوگا اور کلائنٹ کی طرف سے دہرایا جائے گا)۔

لین دین کیسے کام کرتا ہے۔

مان لیں کہ ایک کلائنٹ نے کوآرڈینیٹر کو ایک درخواست بھیجی ہے کہ فلاں فلاں ادارے کے لیے فلاں اور فلاں بنیادی کلید کے ساتھ لین دین کھولیں۔ کوآرڈینیٹر اس ہستی کو لاک کر دیتا ہے اور اسے میموری میں لاک ٹیبل میں رکھتا ہے۔ اگر ضروری ہو تو، کوآرڈینیٹر اس ہستی کو سٹوریج سے پڑھتا ہے اور نتیجے میں آنے والے ڈیٹا کو کوآرڈینیٹر کی میموری میں لین دین کی حالت میں محفوظ کرتا ہے۔

NewSQL = NoSQL+ACID

جب ایک کلائنٹ کسی ٹرانزیکشن میں ڈیٹا کو تبدیل کرنا چاہتا ہے، تو وہ کوآرڈینیٹر کو ہستی میں ترمیم کرنے کی درخواست بھیجتا ہے، اور کوآرڈینیٹر نئے ڈیٹا کو ٹرانزیکشن اسٹیٹس ٹیبل میں میموری میں رکھتا ہے۔ یہ ریکارڈنگ مکمل کرتا ہے - اسٹوریج میں کوئی ریکارڈنگ نہیں کی جاتی ہے۔

NewSQL = NoSQL+ACID

جب کوئی کلائنٹ ایک فعال لین دین کے حصے کے طور پر اپنے تبدیل شدہ ڈیٹا کی درخواست کرتا ہے، تو کوآرڈینیٹر مندرجہ ذیل کام کرتا ہے:

  • اگر ID پہلے سے ہی لین دین میں ہے، تو ڈیٹا میموری سے لیا جاتا ہے۔
  • اگر ID میموری میں نہیں ہے، تو گمشدہ ڈیٹا کو اسٹوریج نوڈس سے پڑھا جاتا ہے، جو پہلے سے میموری میں موجود ہیں، اور نتیجہ کلائنٹ کو دیا جاتا ہے۔

اس طرح، کلائنٹ اپنی تبدیلیوں کو پڑھ سکتا ہے، لیکن دوسرے کلائنٹس کو یہ تبدیلیاں نظر نہیں آتیں، کیونکہ یہ صرف کوآرڈینیٹر کی یاد میں محفوظ ہوتی ہیں؛ وہ ابھی تک کیسینڈرا نوڈس میں نہیں ہیں۔

NewSQL = NoSQL+ACID

جب کلائنٹ کمٹ بھیجتا ہے، وہ حالت جو سروس کی میموری میں تھی کوآرڈینیٹر لاگ ان بیچ میں محفوظ کر لیتا ہے، اور کیسینڈرا اسٹوریج میں لاگ شدہ بیچ کے طور پر بھیجا جاتا ہے۔ اسٹورز اس بات کو یقینی بنانے کے لیے ہر ضروری کام کرتے ہیں کہ یہ پیکیج جوہری طور پر (مکمل طور پر) لاگو ہو، اور کوآرڈینیٹر کو جواب واپس کریں، جو تالے جاری کرتا ہے اور کلائنٹ کو لین دین کی کامیابی کی تصدیق کرتا ہے۔

NewSQL = NoSQL+ACID

اور رول بیک کرنے کے لیے، کوآرڈینیٹر کو صرف لین دین کی حالت کے زیر قبضہ میموری کو آزاد کرنے کی ضرورت ہے۔

В результате вышеописанных доработок мы реализовали принципы ACID:

  • Атомарность. Это гарантия того, что никакая транзакция не будет зафиксирована в системе частично, будут либо выполнены все её подоперации, либо не выполнено ни одной. У нас этот принцип соблюдается за счёт logged batch в Cassandra.
  • مستقل مزاجی. ہر کامیاب لین دین، تعریف کے مطابق، صرف درست نتائج ریکارڈ کرتا ہے۔ اگر، ایک ٹرانزیکشن کھولنے اور آپریشن کا حصہ انجام دینے کے بعد، یہ پتہ چلتا ہے کہ نتیجہ غلط ہے، ایک رول بیک کیا جاتا ہے.
  • علیحدگی. جب کوئی لین دین عمل میں آتا ہے، تو ہم آہنگی کے لین دین سے اس کے نتائج کو متاثر نہیں کرنا چاہیے۔ مسابقتی لین دین کو آرڈینیٹر پر مایوسی کے تالے کا استعمال کرتے ہوئے الگ تھلگ کیا جاتا ہے۔ ٹرانزیکشن کے باہر پڑھنے کے لیے، الگ تھلگ اصول کو Read Committed سطح پر دیکھا جاتا ہے۔
  • استحکام. Независимо от проблем на нижних уровнях — обесточивание системы, сбой в оборудовании, — изменения, сделанные успешно завершённой транзакцией, должны остаться сохраненными после возобновления функционирования.

اشاریہ جات کے حساب سے پڑھنا

آئیے ایک سادہ ٹیبل لیتے ہیں:

CREATE TABLE photos (
id bigint primary key,
owner bigint,
modified timestamp,
…)

У нее есть ID (первичный ключ), владелец и дата изменения. Нужно сделать очень простой запрос — выбрать данные по владельцу с датой изменения «за последние сутки».

SELECT *
WHERE owner=?
AND modified>?

اس طرح کے استفسار پر تیزی سے کارروائی کرنے کے لیے، کلاسک SQL DBMS میں آپ کو کالم (مالک، ترمیم شدہ) کے حساب سے ایک انڈیکس بنانے کی ضرورت ہے۔ ہم یہ بہت آسانی سے کر سکتے ہیں، کیونکہ اب ہمارے پاس ACID کی ضمانتیں ہیں!

سی*ون میں اشاریہ جات

تصاویر کے ساتھ ایک سورس ٹیبل ہے جس میں ریکارڈ ID بنیادی کلید ہے۔

NewSQL = NoSQL+ACID

ایک انڈیکس کے لیے، C*Oن ایک نیا ٹیبل بناتا ہے جو کہ اصل کی کاپی ہے۔ کلید انڈیکس ایکسپریشن جیسی ہی ہے، اور اس میں سورس ٹیبل سے ریکارڈ کی بنیادی کلید بھی شامل ہے:

NewSQL = NoSQL+ACID

اب "آخری دن کے لیے مالک" کے لیے استفسار کو کسی اور ٹیبل سے منتخب کے طور پر دوبارہ لکھا جا سکتا ہے:

SELECT * FROM i1_test
WHERE owner=?
AND modified>?

Согласованность данных исходной таблицы photos и индексной i1 поддерживается координатором автоматически. На основании одной только схемы данных при получении изменения координатор генерирует и запоминает изменение не только основной таблицы, но и изменения копий. Никаких дополнительных действий с таблицей индекса не выполняется, логи не считываются, блокировки не используются. То есть добавление индексов почти не потребляет ресурсы и практически не влияет на скорость применения модификаций.

ACID کا استعمال کرتے ہوئے، ہم SQL جیسے اشاریہ جات کو نافذ کرنے کے قابل تھے۔ وہ مستقل، توسیع پذیر، تیز، کمپوز ایبل، اور CQL استفسار کی زبان میں شامل ہیں۔ اشاریہ جات کو سپورٹ کرنے کے لیے ایپلیکیشن کوڈ میں کسی تبدیلی کی ضرورت نہیں ہے۔ سب کچھ اتنا ہی آسان ہے جتنا SQL میں۔ اور سب سے اہم بات، اشاریہ جات اصل ٹرانزیکشن ٹیبل میں ترمیم کی رفتار کو متاثر نہیں کرتے ہیں۔

کیا ہوا

ہم نے C*One کو تین سال پہلے تیار کیا اور اسے کمرشل آپریشن میں شروع کیا۔

آخر ہمیں کیا ملا؟ آئیے فوٹو پروسیسنگ اور اسٹوریج سب سسٹم کی مثال استعمال کرتے ہوئے اس کا اندازہ کرتے ہیں، جو کہ سوشل نیٹ ورک میں ڈیٹا کی سب سے اہم اقسام میں سے ایک ہے۔ ہم خود تصویروں کی لاشوں کے بارے میں بات نہیں کر رہے ہیں، بلکہ ہر قسم کی میٹا معلومات کے بارے میں بات کر رہے ہیں۔ اب Odnoklassniki کے پاس تقریباً 20 بلین ایسے ریکارڈز ہیں، سسٹم 80 ہزار پڑھنے کی درخواستوں کو فی سیکنڈ پروسیس کرتا ہے، ڈیٹا میں ترمیم سے منسلک 8 ہزار ACID لین دین فی سیکنڈ تک۔

Когда мы использовали SQL с replication factor = 1 (но в RAID 10), метаинформация фотографий хранилась на высокодоступном кластере из 32 машин с Microsoft SQL Server (плюс 11 резервных). Также было выделено 10 серверов для хранения бэкапов. Итого 50 дорогостоящих машин. При этом система работала на номинальной нагрузке, без запаса.

نئے سسٹم میں منتقل ہونے کے بعد، ہمیں نقل کا عنصر = 3 موصول ہوا - ہر ڈیٹا سینٹر میں ایک کاپی۔ یہ نظام کل 63 سرورز کے لیے 6 کیسنڈرا اسٹوریج نوڈس اور 69 کوآرڈینیٹر مشینوں پر مشتمل ہے۔ لیکن یہ مشینیں بہت سستی ہیں، ان کی کل لاگت SQL سسٹم کی لاگت کا تقریباً 30% ہے۔ ایک ہی وقت میں، بوجھ 30٪ پر رکھا جاتا ہے.

C*One کے متعارف ہونے کے ساتھ، تاخیر میں بھی کمی آئی: ایس کیو ایل میں، تحریری آپریشن میں تقریباً 4,5 ms کا وقت لگتا ہے۔ سی*ون میں - تقریباً 1,6 ایم ایس۔ لین دین کا دورانیہ اوسطاً 40 ایم ایس سے کم ہے، کمٹ 2 ایم ایس میں مکمل ہوتا ہے، پڑھنے اور لکھنے کا دورانیہ اوسطاً 2 ایم ایس ہے۔ 99واں پرسنٹائل - صرف 3-3,1 ms، ٹائم آؤٹ کی تعداد میں 100 گنا کمی آئی ہے - یہ سب قیاس آرائیوں کے وسیع استعمال کی وجہ سے ہے۔

К текущему моменту из эксплуатации выведена большая часть нод SQL Server, новые продукты разрабатываются только c использованием C*One. Мы адаптировали C*One для работы в нашем облаке ایک بادل, что позволило ускорить развертывание новых кластеров, упростить конфигурацию и автоматизировать эксплуатацию. Без исходного кода это сделать было бы значительно сложнее и костыльнее.

اب ہم اپنی دیگر اسٹوریج کی سہولیات کو کلاؤڈ میں منتقل کرنے پر کام کر رہے ہیں - لیکن یہ بالکل مختلف کہانی ہے۔

ماخذ: www.habr.com

نیا تبصرہ شامل کریں