وقتی به مقیاس(Scale) فکر میکنیم، نمیتوان توانایی موتور جستجوی گوگل در ایندکسگذاری و جستجوی دادههای جهان روی اینترنت با سرعت برقآسا را نادیده گرفت. نام گوگل مترادف است با مقیاس. در واقع نام Google یک اشتباه عمدی در تلفظ Googol است - یعنی ۱ با ۱۰۰ صفر.
نه سیستمهای ذخیرهسازی قدیمی مانند Relational Database Management Systems(RDBMS) و نه برنامهنویسی Imperative نمیتوانست پاسخگوی مقیاسی که گوگل میخواست اسناد ایندکسگذاری شده روی اینترنت را جستجو کند، باشد. این نیاز منجر به درست شدن Google File System(GFS)، MapReduce(MR) و Bigtable شد.
در حالیکه GFS یک FileSystem توزیعشده و خطاپذیر (Fault-Tolerant) در سرورهای یک کلاستر ارائه میداد، Bigtable ذخیرهسازی مقیاسپذیر دادههای ساختاریافته در GFS را فراهم میکرد. MR یک پارادایم جدید برنامهنویسی موازی برای پردازش داده با مقیاس بالا در GFS و Bigtable ارائه داد.
برنامههای MR با سیستم MapReduce در ارتباط هستند که کدهای محاسباتی (توابع Map و Reduce) را به جایی که دادهها ساکن هستند ارسال میکند؛ در این روش ساکن بودن دادهها، به انتقال دادهها به اپلیکیشن ترجیح داده میشود.
در کلاستر، Workerها محاسبات میانی را Aggregate و Reduce میکنند و یک نتیجهی نهایی از تابع Reduce بهعنوان خروجی میدهند؛ که بعد در یک فضای ذخیرهسازی توزیعشده ذخیره میشود تا برای اپلیکیشن قابل دسترسی باشد. این روش به طرز قابل توجهی ترافیک شبکه را کم میکند و بیشتر Input/Output(IO) را بهجای توزیع در شبکه، بهصورت Local نگهداری میکند.
بیشتر کار گوگل بهعنوان کار اختصاصی بود [و قابل دسترس برای عموم نبود] اما ایدههایی که در این مقالهها آمدهاند، باعث بوجود آمدن ایدههای خلاقانهای در جامعهی اوپن سورس شد - مخصوصا در Yahoo که در آن زمان با این چنین چالشهای بیگدیتا برای موتور جستجوی خود روبرو بود.
چالشهای محاسباتی و راهحلهای ارائه شده در مقالهی Google GFS، منجر به ارائهی یک طرح اولیه برای Hadoop File System (HDFS) شد. در این طرح اولیه MapReduce بهعنوان یک فریمورک برای محاسبات توزیعشده ارائه شده بود. در سال ۲۰۰۶ با بخشیدن HDFS به Apache Software Foundation، بخشی از فریمورک Apache Hadoop شد.
اگرچه Apache Hadoop خارج از یاهو اقتباسهای زیادی داشت و Contributerهای زیادی را در جامعهی اوپن سورس به خود جلب کرد و ۲ شرکت تجاری بر اساس این ابزار اوپن سورس بوجود آمد (Cloudera و Hortonworks) اما فریمورک MapReduce روی HDFS ایرادهایی داشت.
اول اینکه مدیریت آن سخت بود و پیچیدگی عملیاتی دست و پاگیری داشت. دوم، MapReduce API برای پردازش دستهای (Batch-Processing) پرکلمه و طولانی بود و احتیاج به کدهای ستاپی داشت که تکراری و زیاد بودند. سوم، با دستههای بزرگ از دادهها که هر کدام تعداد زیادی از جفت تسکهای MR داشتند، نتیجهی محاسبهشدهی میانی هر جفت بر روی دیسک محلی نوشته میشد تا در عملیات بعدی استفاده شود (شکل پایین) این عملیات تکراری I/O دیسک عواقب بدی داشت: جابهای بزرگ MR میتوانستند ساعتها و حتی روزها به طول انجامند.
و در نهایت، اگرچه Hadoop MR در جابهای با مقیاس بزرگ مفید بود اما با ترکیبهای کارهای دیگری مانند ماشین لرنینگ، استریمینگ و کوئریهای اینتراکتیو SQLمانند عملکرد بدی پیدا میکرد.
برای برطرف کردن این مشکلات، مهندسها سیستمهای سفارشی را توسعه دادند (Apache Hive,Apache Storm, Apache Impala, Apache Giraph, Apache Drill, Apache Mahout و ...) که هر کدام شامل API و پیکربندی کلاستر مخصوص خود بود. این خود باعث شد به پیچیدگی عملیاتی Hadoop اضافه و یادگیری آن برای توسعهدهندهها سختتر شود.
سوالی که پیش آمد این بود که آیا راهی وجود دارد که بتوان Hadoop و MR را سادهتر و سریعتر کرد؟ (با در نظر گرفتن جملهی Alan Kay: چیزهای ساده باید ساده باشند، چیزهای پیچیده باید ممکن باشند)
محققین در UC Berkeley که قبلا بر روی Hadoop MapReduce کار کرده بودند، این چالش را در پروژهای تحت عنوان Spark قبول کردند. آنها میدانستند که MR برای انجام محاسبات جابهای تکراری یا تعاملی ناکارآمد است و از طرفی یادگیری آن هم سخت است. پس از همان ابتدا این ایده را داشتند که Spark را سادهتر، سریعتر و راحتتر بسازند. این تلاشها در سال ۲۰۰۹ از RAD Lab شروع شد که بعدها تبدیل به AMPLab شد (و حالا نام آن RISELab است)
مقالههای ابتدایی Spark نشان میدادند که در بعضی جابها، ۱۰ تا ۲۰ برابر سریعتر از Hadoop MapReduce عمل میکرد. هدف پروژهی Spark این بود که ایدههای برگرفته شده از Hadoop MapReduce را بگیرد و سیستم را بهبود ببخشد: Fault Tolerance آن افزایش یابد، بتواند بهصورت موازی کار کند، از ذخیرهسازی درون-حافظهای پشتیبانی کند و APIهای سادهای را به زبانهای مختلف برنامهنویسی ارائه دهد. تا سال ۲۰۱۳ استفاده از Spark افزایش یافت و تعدادی از سازندهها و محققین اصلی آن یعنی Matei Zaharia, Ali Ghodsi, Reynold Xin, Patrick Wendell, Ion Stoica,and Andy Konwinski پروژه را به ASF بخشیدند و یک کمپانی با نام Databricks تاسیس کردند.
کمپانی Databricks و جامعهی توسعه دهندگان اپن سورس با هم کار کردند تا در می ۲۰۱۴ Apache Spark 1.0 را تحت نظر ASF منتشر کنند.
آپاچی اسپارک (Apache Spark) یک موتور یکپارچه برای پردازش توزیعیافتهی داده در مقیاس بالا است که محل استفادهی آن در دیتا سنترها و فضاهای ابری است.
اسپارک امکان ذخیرهسازی درونحافظهای را برای محاسبات میانی فراهم میکند که همین باعث میشود از Hadoop MapReduce سریعتر باشد. اسپارک شامل کتابخانههایی برای ماشین لرنینگ (MLlib)، SQL برای کوئریهای اینتراکتیو (Spark SQL) پردازش جریانی برای کار با دادههای لحظهای (Structered Streaming) و پردازش گراف (GraphX)
فلسفهی طراحی اسپارک ۴ مولفهی اصلی دارد:
در اینجا میخوانیم که هر کدام چه معنایی برای این فریمورک دارد.
اسپارک هدف پرسرعت بودن را به چند طریق دنبال کرده است. اول، پیادهسازی آن از پیشرفتهای اخیر تکنولوژی در زمینهی هزینه و پرفورمنس CPU و حافظه نفع میبرد. امروزه سرورها ارزان هستند و چندین گیگابایت حافظه و چند هسته دارند و سیستم عامل مبتنی بر Unix آنها از پس Multithreading و پردازش موازی بر میآید. این فریمورک از تمامی فاکتورهای گفته شده نهایت استفاده را میکند.
دوم، اسپارک محاسبات کوئری خود را بهعنوان یک Directed Acyclic Graph(DAG) انجام میدهد؛ برنامهریزی DAG و بهینهساز کوئری آن میتواند یک گراف محاسباتی بهینه را تولید کند که معمولا میتوان آن را به چند تسک تبدیل کرد که محاسبات هر کدام را میتوان بهصورت موازی در Workerهای یک Cluster انجام داد. سوم، موتور اجرای آن یعنی Tungsten برای تولید کدهای فشرده از Whole-Stage Code Generation استفاده میکند.
با نگهداری نتایج میانی در حافظه و کم بودن تعداد خواندن و نوشتن از دیسک، پرفورمنس اسپارک به طرز قابل توجهی افزایش میابد.
اسپارک با ارائهی یک ساختمان دادهی لاجیکال به نام Resilient Distributed Dataset(RDD) به ساده بودن دست پیدا کرده است. با ارائهی مجموعهای از Transformationها و Actionها بهعنوان Operation، اسپارک یک مدل برنامهنویسی ساده را ارائه میدهد که میتوان برای ساخت برنامههای بیگ دیتا در زبانهای برنامهنویسی رایج از آن استفاده کرد.
اسپارک میتواند از پس چندین نوع کار بر بیاید و از آن در زبانهای برنامهنویسی پشتیبانیشده استفاده کرد: Scala, Java, Python, SQL, R. اسپارک کتابخانههای یکپارچه با APIهایی با داکیومنت خوب را ارائه میدهد که اینها از اجزای اصلی آن است: Spark SQL, Spark Structed Streaming, Spark MLlib, GraphX که از همهی آنها میتوان در یک موتور استفاده کرد. میتوانید یک برنامهی اسپارک بنویسید که از پس همهی این کارها برمیآید.
اسپارک بهجای ذخیرهسازی، تمرکز خود را روی موتور محاسبات سریع و موازی خود میگذارد. بر خلاف Apache Hadoop که شامل هم ذخیرهسازی و هم محاسبات بود، اسپارک این دو را از هم جدا میکند. یعنی میتوانید از اسپارک استفاده کنید تا داده را از منابع مختلف بخوانید: ApacheHadoop, Apache Cassandra, Apache HBase, MongoDB, Apache Hive, RDBMS و سپس محاسبات دادهها را در حافظه انجام دهید.
یکپارچگی مفهومی نیست که مختص اسپارک باشد اما یکی از مولفههای اصلی فلسفهی طراحی و توسعهی آن بوده است. در نوامبر ۲۰۱۶ ACM جایزهی ACM Award را به سازندگان اسپارک برای این مقاله داد. این مقاله توضیح میدهد که اسپارک چگونه جایگزینی برای موتورهایی است که هر کدام مختص یک کار بهخصوص مانند تحلیل گراف و پردازش دستهای بودند. اسپارک یک موتور یکپارچه است که تمام این اجزاء را درون خود جای داده است.
همانطور که در شکل زیر میبینید، اسپارک ۴ جز اصلی را بهعنوان کتابخانه درون خود دارد. هر کدام از این اجزا از موتور Fault-Tolerant اسپارک مجزا است که در آن ما از APIها برای نوشتن برنامههای اسپارک استفاده میکنیم و اسپارک آن را تبدیل به DAG میکند که موتور اصلی آن را اجرا میکند. پس کدهایی که با استفاده از APIهای Java, R, Scala, Python نوشته شدهاند تبدیل به بایتکدهای فشردهای میشوند که در JVMهای Workerها در Cluster اجرا میشوند.
این ماژول به خوبی با دادههای ساختار یافته کار میکند. میتوانید دادههایی را که در تیبلهای RDBMS یا در فایلهای با فرمتهای دادههای ساختار یافته ذخیره شدهاند، بخوانید و سپس تیبلهای موقت یا دائمی در اسپارک بسازید. همچنین، وقتی از Structured APIهای Java, Python,Scala, R استفاده میکنید، میتوانید از کوئریهای SQLمانند برای کوئری داده استفاده کنید.
اسپارک یک کتابخانه برای الگوریتمهای رایج ماشین لرنینگ دارد که نام آن MLlib است. از ابتدای انتشار اسپارک عملکرد این کتابخانه بهتر و بهتر شده است.
آپاچی اسپارک ۲.۰ یک ویژگی آزمایشی با نام Continuous Streaming model و Structured Streaming API معرفی کرد. در نسخهی ۲.۲ Structured Streaming در دسترس عموم قرار گرفت. برای توسعه دهندگان بیگ دیتا، پاسخگویی آنی به دادههای ثابت و جریانی و ترکیب آنها امری مهم است. این مدل جدید یک جریان را به شکل یک تیبل دائما در حال بزرگ شدن میبیند که ردیفهای جدید داده به انتهای آن اضافه میشود. توسعه دهندگان میتوانند با آن به شکل یک تیبل ساختار یافته رفتار و کوئریهای خود را مانند دادههای ثابت اجرا کنند.
پشت Structured Streaming model موتور Spark SQL تمام جنبههای Fault Tolerance و دادههای اضافهشونده را مدیریت میکند تا توسعهدهنده تمرکز خود را بر نوشتن برنامههای جریانی بگذارد. اسپارک ۲ و ۳ منابع دادههای جریانی را گسترش دادند تا بتوان از Apache Kafka, Kinesis, ، HDFS-based و فضای ذخیرهسازی ابری هم بتوان استفاده کرد.
همانطور که از نامش پیداست، این کتابخانه مخصوص کار با گرافها(گرافهای شبکههای اجتماعی، جادهها و نقاط اتصال، گرافهای شبکههای توپولوژی) و انجام محاسبات موازی است. الگوریتمهایی که در این کتابخانه موجود هستند: PageRank, Connected Components, و TriangleCounting.
اگر تا به اینجای مطلب خوانده باشید، میدانید که اسپارک یک موتور پردازش دادهی توزیعیافته است که اجزای آن با همکاری یکدیگر بر روی کلاستر کار میکنند. در اینجا میخواهیم بدانیم چگونه تمام اجزای معماری توزیعیافتهی اسپارک کار میکنند و با هم در ارتباط هستند.
با شکل زیر شروع میکنیم. در سطح بالای معماری اسپارک، یک Spark Application شامل یک Driver Program است که وظیفهی هماهنگ کردن عملیات موازی را روی کلاستر اسپارک دارد. این درایور از طریق SparkSession به اجزای توزیعیافته در کلاستر دسترسی دارد یعنی Spark Executor و Cluster Manager.
چون بخشی از Spark Application وظیفهی راهاندازی SparkSession را دارد، Spark Driver چندین نقش دارد: با Cluster Manager در ارتباط است، منابع (CPU, Memory) را از Cluster Manager برای Spark Executorها(JVMها) درخواست میکند، تمام عملیات اسپارک را تبدیل به محاسبات DAG میکند، آنها را برنامهریزی میکند و اجرای آنها را بهعنوان تسک در Spark Executorها توزیع میکند. وقتی منابع اختصاص داده شدند، بهطور مستقیم با Executorها ارتباط برقرار میکند.
در اسپارک ۲.۰ SparkSession تبدیل به یک مجرای یکپارچه برای تمام عملیات اسپارک و دادهها شد. نه تنها کارهای ابتدایی قبلی اسپارک مانند SparkContext, SQLContenxt, HiveContext, SparkConf را انجام میدهد بلکه کار با اسپارک را راحتتر و سادهتر کرده است.
اگرچه در اسپارک ۲ SparkSession شامل دیگر Contextها است اما همچنان میتوان به تک تک Contextها و توابع آنها به طور مجزا دسترسی داشت. با این روش Backward Compatibility فراهم شده است تا کدهای قدیمی که در اسپارک ۱ با SparkContext و ... نوشته شدهاند، همچنان کار کنند.
با استفاده از همین یک مجرا، میتوان پارامترهای رانتایم JVM را ساخت، DataFrame و Dataset ها معرفی کرد، از منابع دادهی مختلف خواند، کوئریهای Spark SQL را اجرا کرد. SparkSession یک نقطهی آغاز یکپارچه برای تمام امکانات اسپارک را فراهم میکند.
در یک برنامهی اسپارک، میتوانید با استفاده از یکی از APIهای زبانهای سطح بالا SparkSession را درست کنید. هنگام استفاده از Spark Shell بهطور خودکار SparkSession ساخته شده است و میتوانید با استفاده از یک Global Variable به نام spark یا sc به آن دسترسی پیدا کنید.
در اسپارک ۱ باید Contextهای مجزا درست میکردید( برای Stream و SQL و ...) و برای هر کدام کدهای ابتدایی معرفی را مینوشتید، در اسپارک ۲ میتوانید به ازای هر JVM یک SparkSession بسازید و از آن برای اجرای عملیات اسپارک استفاده کنید.
مدیریت و اختصاص منابع کلاستر، وظیفهی Cluster Manager است. در حال حاضر اسپارک از ۴ Cluster Manager پشتیبانی میکند: نسخهی داخلی خود اسپارک،Apache Hadoop YARN، Apache Mesos و Kubernetes.
یک Spark Executor بر روی هر Worker Node در کلاستر اجرا میشود. این Executorها با Driver Program در ارتباط هستند و وظیفهی اجرای تسکها را بر روی Workerها بر عهده دارند. در بیشتر Deployment Modeها یک Executor به ازای هر نود اجرا میشود.
یک ویژگی جذاب اسپارک، پشتیبانی آن از تعداد زیادی Deployment Mode است که امکان اجرای اسپارک در کانفیگها و محیطهای مختلف را فراهم میسازد. از آنجایی که Cluster Manager کاری با اینکه در کجا دارد اجرا میشود ندارد( و تنها به این فکر میکند که Spark Executorها را مدیریت کند و پاسخگوی درخواستهای منابع باشد) اسپارک میتواند در محیطهای محبوب اجرا شود، مانند Apache Hadoop YARN و Kubernetes.
دادهی فیزیکی واقعی در فضای ذخیرهسازی، بهعنوان پارتیشنهایی که یا در HDFS و یا فضای ابری ساکن هستند، توزیع شده است.(شکل پایین) اگرچه داده بهعنوان پارتیشنهایی در کلاسترهای فیزیکی توزیع شده است، اسپارک با هر پارتیشن بهعنوان یک دادهی لاجیکال برخورد میکند- بهعنوان یک DataFrame در حافظه. البته این همیشه امکانپذیر نیست، به هر Spark Executor، متناسب با نزدیکی به داده، یک تسک سپرده میشود که نیاز دارد پارتیشنی را بخواند که به آن نزدیک است.
پارتیشنبندی امکان پردازش موازی بهینه را فراهم میسازد. شکستن داده به قسمتها یا پارتیشنهای مختلف این امکان را به Spark Executorها میدهد تا فقط دادههایی را که به آنها نزدیک هستند، پردازش کنند؛ که این پهنای باند شبکه را کاهش میدهد.
بیشتر توسعهدهندگانی که با بیگ دیتا سر و کار دارند مهندسهای داده، داشمندهای داده و یا مهندسهای یادگیری ماشین هستند. علت جذب شدن آنها به اسپارک این است که به آنها اجازه میدهد برنامههای مختلفی را با استفاده از یک موتور و زبانهای برنامهنویسی آشنا بسازند.
علوم داده از داده استفاده میکند تا داستانهایی را بیان کند. اما قبل از بیان داستان، دانشمندان داده باید داده را تمیز کنند، آن را جستجو کنند تا به الگوهایی برسند و مدلهایی بسازند تا چیزهایی را پیشبینی کنند. بیشتر دانشمندان داده در استفاده از SQL، کتابخانههای NumPy و Pandas و زبانهایی مانند R و Python ماهر هستند. همچنین ضروری است که بدانند چطور با داده کار کنند، آن را تبدیل کنند و چگونه از الگوریتمهای یادگیری ماشین موجود برای ساخت مدل استفاده کنند.
خوشبختانه اسپارک از این ابزارها پشتیبانی میکند. برای ساخت مدل میتوان از کتابخانهی Spark MLlib استفاده کرد.
بعد از ساخت مدلها، دانشمندان داده معمولا نیاز دارند تا با دیگر اعضای تیم که وظیفهی دیپلوی کردن مدل را دارند، در ارتباط باشند یا شاید هم باید با کسانی کار کنند تا دادهی خام را تبدیل به دادهی تمیز کنند که برای دیگر دانشمندان قابل استفاده باشد. مثلا ممکن است یک مدل Classification با دیگر اجزا مانند یک اپلیکیشن وب یا یک موتور جریانی مانند Apache Kafka در ارتباط باشد. این پایپلاین را مهندسهای داده میسازند.
مهندسهای داده آشنایی زیادی با اصول طراحی نرمافزار دارند و تواناییهای زیادی در ساخت دیتا پایپلاینهای کارآمد دارند. دیتا پایپلاینها امکان تبدیل End-to-End دادههای خام را که از منابع مختلف میآیند فراهم میسازند؛ دادهها تمیز میشوند تا توسعهدهندگان بتوانند از آنها استفاده کنند، در فضای ذخیرهسازی ابری یا در NoSQL یا RDBMS برای گزارشنویسی ذخیره میشوند.
مهندسهای داده از اسپارک استفاده میکنند چون موازیسازی محاسبات راحت و پیچیدگی آن کمتر است. این باعث میشود تا تمرکز خود را روی استفاده از APIهای مبتنی بر DataFrame و زبانهای برنامهنویسی مختص یک زمینه برای ETL، خواندن و ترکیب داده استفاده کنند.
بهبود عملکرد اسپارک در نسخههای ۲ و ۳ به لطف استفاده از Catalyst Optimizer برای SQL و Tungsten برای تولید کدهای فشرده، کار را برای مهندسهای داده آسانتر کرده است. این امکان برای آنها فراهم است که از هر کدام از ۳ API موجود استفاده کنند: RDD، DataFrame و Dataset
فارغ از اینکه مهندس داده، دانشمند داده و یا مهندس یادگیری ماشین هستید، اسپارک میتواند در این زمینهها کاربردی باشد:
اسپارک به محبوبیت زیادی در جامعهی اپن سورس دست پیدا کرده است. امروزه بیش از ۶۰۰ گروه در سراسر جهان وجود دارند که تعداد اعضای آنها نزدیک به نیم میلیون نفر میرسد. هر هفته، یک شخص در جهان یک سخنرانی یا یک پست وبلاگ دربارهی چگونگی استفاده از اسپارک در دیتا پایپلاینها به اشتراک میگذارد. در میان همهی آنها، Spark + AI Summit بزرگترین کنفرانسی است که به استفادهی اسپارک در یادگیری ماشین، مهندسی داده و علوم داده اختصاص داده شده است.