مدت هاست که مفاهیم کانتینر سازی و همچنین Auto Scalability و Horizontal Scaling صحبت داغ محافل دنیای توسعه نرم افزار بوده و به همین دلیل کوبرنتیز تبدیل به پرطرفدار ترین Orchestrator کانتینر ها در سطح کلان کسب و کار ها شده تا جایی که شاهد مهاجرت هر چه بیشتر شرکت های بزرگ جهانی به این پلتفرم برای دستیابی به مزایای آن باعث شده کلاستر هایی با چند صد ترابایت رم، ده ها هزار پردازنده و همچنین هزاران node به وجود بیایند و هر روز این کلاستر ها بزرگتر و بزرگتر شوند.
برای یکی از پروژه ها، ما نیز که توضیع یکسانی از ترافیک در ساعات روز نداشت و نیاز به بهینه سازی و Automatic Scaling داشتیم و همچنین تعداد سرویس های زیادی که محصول نهایی رو شکل میداد ما هم تصمیم گرفتیم از این Orchestrator یعنی کوبرنتیز استفاده نموده و محیط عملیاتی را کاملا به کوبرنتیز منتقل کنیم.
خب برای کانتیرایز کردن نرم افزار ها هیچ مشکلی به دلیل استفاده از دات نت کور و انگولار نداشتیم اما به دلیل پیروی از بهروش های توسعه یک سیستم میکروسرویس Event-Based نیاز بود تعداد زیادی دیتابیس از انواع مختلف رو برای سرویس هامون رو داخل کانتینر و بر روی کوبرنتیز Orchestrate کنیم. کلاستر های Redis، ETCD، Zookeeper، MongoDB، Elasticsearch و ……… اما وقتی داستان به دیتابیس های رابطه ای رسید وارد داستان جالبی شدیم. خب همون طور که همه میدونید دیتابیس مایکروسافت یعنی همان SQL Server معروف از نسخه ۲۰۱۷ به بعد داخل کانتینر ها قابلیت راه اندازی را به دست آورده و سیستم عامل پیشنهادی مایکروسافت برای پیاده سازی دیتابیس رابطه ایش در نسخه ۲۰۱۹ لینوکس هست. از آن جایی که کلاستر کوبرنتیز ها ما بر روی لینوکس centos نسخه ۷ پیاده سازی شده بود به این فکر افتادیم که SQL Server را به عنوان دیتابیس رابطه خودمون انتخاب کنیم و به عنوان یک Statefulset در کوبرنتیز Deploy کنیم.
اما بعد از چند لود تست روی نرم افزارمون که از دیتابیس SQL Sever 2019 روی ویندوز سرور ۲۰۱۹ متوجه یکسری عملکرد ضعیف در رابطه با SQL Server شدیم. (هارد سرور هامون همگی SSD هستند و Raid 10) بنابراین تصمیم گرفتیم که SQL Server رو با رقیب متن باز دیتابیس های تجاری یعنی PostgreSQL رو توی کوبرنتیز قبل از مهاجرت بنچمارک کنیم. نکته ای که وجود داره هر چی جستجو میکردیم همیشه صحبت از عملکرد وحشتناک SQL Server توی بنچمارک های TPC-H بود ولی همیشه روی سرور های خیلی قدرتمند.اما توی کوبرنتیز چطور با سرور های کوچیک تر؟
بریم با هم ببینیم نتیجه رو:
اول از همه چیز اطلاعات محیط بنچمارک:
نسخه دیتابیس هایی که برای بنچمارک استفاده شدند SQL Server 2019-latest و همچنین PostgreSQL 14.1 بودند که به صورت یک Statefulset در معماری Standalone روی کلاستر کوبرنتیز ما که همه چیز کلاستر (kubelet kubeadm kubectl) نسخه ۱.۲۲.۴ بود.
میزان منابع اختصاصی به هر دیتابیس (کانتینر) شامل ۴ گیگابایت رم و ۴ هزار میلی کور CPU بود و پادها از طریق Nodeport به بیرون Expose شده بودند.
سرور تست یک سیستم دسکتاپ با پردازنده Core i5 9400 با ۱۶ گیگ رم و هارد NVME بود و ابزار تست هم JMeter (البته میدونم که خیلی مناسبی برای تست دیتابیس نیست) بوده. و اما بقیه ماجرا و بنچمارک…..
بنچمارک Insert:
به دلیل اینکه همینجوری سیستم ما بار خیلی زیادی روش بود کلا بیخیال تست با ۱۰۰ تا کانکشن شدیم و رفتیم روی تست با ۸۰۰ تا کانکشن همزمان.
دیتابیس محیط تست ما شامل ۵ تا جدول بود که یک جدول مستر و ۴ جدول وابسته که از طریق Foreign Key به هم متصل شده بودند. فیلد ID هم Auto Increment و هرInsert یک Record به هر چهار جدول اضافه میکرد.
تعداد کانکشن های باز SQL Server به صورت پیشفرض ۳۲۷۶۷ کانکشن بزرگترین عدد مثبت ۲ بایتی بود ولی PostgreSQL کلا ۱۰۰ کانکشن باز پیش فرض بیشتر نداشت. به همین دلیل یکم دستکاریش کردیم و تعداد کانکشن های باز رو کردیم ۱۰۰۰ عدد.
Insert هم توی هر دو تا دیتابیس با دستورات زیر انجام می شد :
SQL Server:
insert into tbl_master ( col1, col2 ,col3 ,col4 ,col5,col6)
values( ${random_number} ,${random_number}, ‘2008-11-11 13:23:44′,’2008-11-11’, ‘${__RandomString(1000,abcdefghijklmnopqrstuvwxyz,randstr)}’, ‘${__RandomString(2000,abcdefghijklmnopqrstuvwxyz,randstr)}’)
PostgreSQL:
insert into tbl_master ( col1, col2 ,col3 ,col4 ,col5,col6
VALUES( ${random_number} ,${random_number}, ‘2020-11-11 13:23:44′,’2008-11-11’, ‘${__RandomString(1000,abcdefghijklmnopqrstuvwxyz,randstr)}’,
‘${__RandomString(1000,abcdefghijklmnopqrstuvwxyz,randstr)}’)
و اما نتیجه تست Insert پس از چند بار تکرار یکسان بود و میتونید در تصویر پایین نتیجه رو مشاهده کنید.
مدت زمان تست ۳ دقیقه بود که با ۸۰ کانکشن شروع و در ۱۰ قدم هر ۶ ثانیه ۸۰ کانکشن اضافه میشد و سپس به مدت ۲ دقیقه کامل روی ۸۰۰ کانکشن تست ادامه پیدا میکرد.
تعداد Insert ها تغریبا برابر بوده که این اتفاق به خاطر JMeter بود. قسمت های نگران کننده میزان تاخیر های SQL Server و همچنین تعداد خطاهایی بود که با اونا رو به رو می شد. اما PostgreSQL نمایشی قدرتمند رو روی صحنه آورد و با تاخیر های بسیار کم و همچنین بدون هیچگونه خطایی تمامی عملیاتی رو انجام داد.
پ. ن: اعدادی که در تصویر در بخش های Average, Median, 90% Line, 95% line, 99% line, Min & Max میبینیم بر حسب میلی ثانیه هستند.
توی نمودار های زیر یک نگاه به عوامل یکسان توی بنچمارک به صورت بصری میکنیم.
بنچمارک Select:
توی بنچمارک کوئری ۵ رکورد آخر تمامی ستون های هر جدول بازیابی می شدند. متاسفانه توی این مورد هم SQL Server یه نمایش خیلی ضعیف رو داشت ولی PostgreSQL فوق العاده قدرتمند ظاهر شد.
پایین جدول اطلاعات بنچمارک و همچنین بعد از اون نمودار های مقایسه ایش رو میتونید ببینید. توی بنچمارک کوئری هم مدت زمان تست ۳ دقیقه بود و ۸۰۰ کانکشن که با ۸۰ کانکشن شروع شده و ۸۰ تا ۸۰ تا افزایش پیدا میکرد و در نهایتا توی دقیقه ۱ به ۸۰۰ کانکشن میرسید.
برای بازیابی ۵ رکورد آخر هم از دستورات زیر استفاده کردیم:
SQL Server:
select top(5) * from tbl_master
PostgreSQL:
select * from tbl_master order by pk desc limit 5
توی ادامه میتونید گزارش نتیجه JMeter و همچنین نمودار های مقایسه ای رو ببینید.
بنچمارک Update
میرسیم به نقطه ای که برای ما حیاتی محسوب میشد. عملیات آپدیت!!! سیستم ما بیش از هر چیزی به آپدیت وابسته بود به همین دلیل وقت زیاد تری رو روی تیون کردن مکانیزم آپدیتمون گذاشتیم.
توی تست آپدیت به صورت رندوم یک رکورد انتخاب میشد و سپس یکسری از مقادیر فیلدهاش به صورت رندوم آپدیت می شدند.
توی بنچمارک آپدیت هم مدت زمان تست ۳ دقیقه بود و ۸۰۰ کانکشن؛ که با ۸۰ کانکشن شروع شده و ۸۰ تا ۸۰ تا افزایش پیدا میکرد و در نهایتا توی دقیقه ۱ به ۸۰۰ کانکشن میرسید و بعد از اون ۲ دقیقه به صورت مدام ادامه پیدا میکرد.
برای عملیا آپدیت هم از دستورات زیر استفاده کردیم:
SQL Server:
UPDATE tbl_master
SET col1 = ${number}, col2 = ${number}, col3 =’2008-11-11 13:23:44′ ,col4=’2008-11-11′ , col5 =’${__RandomString(1000,abcdefghijklmnopqrstuvwxyz,randstr)}’ , col6 = ‘${__RandomString(2000,abcdefghijklmnopqrstuvwxyz,randstr)}’
WHERE pk = ${number};
PostgreSQL:
update tbl_master
set col1 = ${number}, col2 = ${number}, col3 = ‘2000-11-11 13:23:44’,col4 = ‘2000-11-11’,
col5 = ‘${__RandomString(10,abcdefghijklmnopqrstuvwxyz,randstr)}’,
col6 = ‘${__RandomString(1000,abcdefghijklmnopqrstuvwxyz,randstr)}’
where pk = ${number}
توی ادامه توجه هتون رو به نتایج تست جلب میکنم.
نتیجه:
در نهایت بعد از چند بار تکرار تست ها و مشاهده یکسان نتایج در تمامی موارد و تمامی دوره های تست PostgreSQL نمایش بهتری رو به اجرا گذاشت. همچنین نکته دیگه ای که خیلی قابل توجه بود حجم منابعی بود که هر کانتینر مصرف میکردند که توی تمامی تست ها SQL Server به صورت میانگین ۳ برابر منابع بیشتر مصرف میکرد و همچنین کانتینر SQL Server در طول تست ها در مجموع ۲۹ بار Restart شد!!!!
از طرفی هم این بنچمارک متناسب با نیاز داخلی خود ما انجام شده و ممکنه توی سناریو های مختلف و یا استاندارد TPC-H نتایج دیگه ای رو به دنبال داشته باشه.
به همین دلیل توصیه میکنم در صورتی که میخواین برای شرایط خاص و یا Mission Critical Application دیتابیس تکنولوژی یا هر چیزی انتخاب میکنید مطمئن بشید مناسب اون موقعیت خاص براتون باشه. تعصب توی دنیای IT جایی نداره واقعا.
خوشحال میشم اگر سوال یا موضوعی هست که دوست دارید در موردش صحبت کنیم باهام در تماس باشید. برای ارتباط هم میتونید توی وب سایتم کامنت بزارید یا توی لینکدین باهام در ارتباط باشید یا برام ایمیل بفرستید.
با تشکر
دیدگاه خود را بنویسید