I feel the need, the need for speed
אמר טום קרוז בימים היפים שלו לפני שהצטרף לכת scientology.
רובנו מכירים את מסד הנתונים MYSQL שהוא מהיר, פונקציונאלי ונפוץ. אבל למתכנתים זה לא מספיק כנראה לכן הומצאה מתודולוגיה שונה לשמירת נתונים – NoSQL. תוכנות כמו Redis, Cassandra, MongoDB שומרות נתונים בזיכרון ומאפשרות לענקיות כמו פייסבוק גוגל וטוויטר לדחוף ולמשוך מסה של נתונים במהירות.
SQL
משנות השבעים בסיס הנתונים הפופולרי ביותר שנמצא בשימוש הוא בסיס נתונים טבלאי שמבוסס על טבלאות, רשומות ושדות. צריך לתכנן אותו מראש וליצור סכמה (scheme) שהיא השלד של בסיס הנתונים. יש צורך לקבוע מראש את סוגי הנתונים שיהיו בשדות לדוגמה int או float וגם לקבוע מפתח ראשי ומשני. אין ספק שבסיס נתונים זה מהווה הצלחה מסחררת וניתן למצוא אותו באתרי אינטרנט, בנקים חברות ביטוח ומוסדות אחרים.
מהרגע שחברת אורקל שחררה את גרסת MYSQL בקוד פתוח היא הפכה לברירת המחדל של מפתחים ומתכנתים. יש שפה די פשוטה שנקראת SQL (query language) שמשמשת לשאילתות של דחיפת ומשיכת נתונים, יש אפשרות לצירוף טבלאות (join) ועוד עשרות פונקציות שונות שהפכו אותה לבסיס הנתונים הפופולרי ביותר .
מאפייני SQL:
- אמין מאוד, אין אובדן מידע
- בסיס נתונים יחסי (relational)
- מהיר מאוד בשביל רוב האפליקציות
- לוקח די הרבה משאבים מהשרת
- מתאים לשאילתות מסובכות
- דורש הגדרת סכמה מראש, הגדרת סוג הנתונים
- מבנה נוקשה, קשה לשנות את הסכמה
- נפוץ ברוב השרתים
- נפח זכרון גדול כנפח הדיסק הקשיח
NOSQL
בשנים האחרונות, עם ההתפתחות של חברות ענק כמו פייסבוק וטוויטר וגם חברות big data חלק מהן עברו להשתמש בבסיס נתונים שנקרא nosql שהוא אינו יחסי ולא מבוסס על טבלאות. הוא מהיר בהרבה ומאפשר גמישות שבסיס נתונים רגיל לא מאפשר. הסיבה העיקרית למהירות היא שהנתונים נשמרים בזיכרון הזמני ולא על הדיסק אבל יש עוד כמה סיבות לכך שהוא מהיר כמו למשל פחות בדיקות של נתונים וגם מבנה נתונים שונה. המידע עדיין יכול להישמר על הדיסק בזמנים שקבענו, אבל אם יש הפסקת חשמל פתאומית או אם יש הפרשי זמן גדולים בשמירה על הדיסק אז המידע אינו מהימן. ברוב המקרים, כמו ברדיס, המידע נשמר במבנה נתונים של “מפתח-ערך” מה שנקרא “key-value”.
מאפייני NOSQL:
- התקנה קלה ופשוטה
- לא לוקח הרבה משאבים מהשרת
- מהיר מהיר מהיר, יכול להגיע לפי 10 מהירות יותר מבסיס נתונים סטנדרטי
- גמיש מאוד ניתן להשתמש באיזה סוגי נתונים שרוצים
- נפח הזכרון מוגבל ל RAM של המחשב
- יכול להווצר אובדן מידע
- ניתן לדחוף מסה של נתונים במהירות
- לא קיימת כמעט תמיכה בשרתים
בסופו של דבר שילוב בין שניהם הוא האופטימלי ביותר וזה שרוב החברות הגדולות הולכות עליו.
התקנה על הרספברי פיי
אחרי שסקרנו את היתרונות והחסרונות של כל אחד מהם, אין ספק שבשביל פרויקטים קטנים שצריכים שמירה של נתונים, בסיס נתונים כמו רדיס הוא אופטימלי למחשב זעיר כמו הרספברי פיי או למערכת משובצת אחרת של לינוקס. אם אנחנו רוצים לספור משהו או לשמור מידע מחיישנים אין לנו צורך בבסיס נתונים טבלאי כמו MYSQL. אנחנו רוצים תוכנה מהירה, גמישה וקלת משקל ולא תוכנה מסורבלת כמו שנמצאת בבנקים וחברות ביטוח. אז יאללה להתקנה….
ההתקנה לוקחת בחשבון שיש על הרספברי פיי שרת(APACHE או NGINX) וגם PHP.
קודם כל נתקין את רדיס:
sudo apt-get install redis-server
ועכשיו את התוסף ל PHP:
sudo apt-get install php5-redis
פונקציות בסיסיות
קודם כל עדיף לקרוא את התיעוד של התוכנה.
כדי לבדוק שרדיס עובד נקליד מתוך הרספברי פיי:
redis-cli
דבר זה יפתח ממשק של רדיס בתוך הטרמינל בפורט 6379.
עכשיו ניצור מפתח-ערך חדש בבסיס הנתונים:
set hello "world"
יצרנו מפתח חדש שנקרא hello. כדי לשלוף את הערך שלו נרשום:
get hello
עוד מבנה נתונים שימושי ברדיס חוץ ממחרוזות הוא רשימות – lists. כדי ליצור רשימה ולדחוף אליה נתונים נקליד:
lpush list value1 value2 value3
כדי לשלוף את הנתונים נשתמש בפקודה lrange ונכניס את טווח הנתונים שרוצים לשלוף:
lrange list 0 -1
-1 הוא האיבר האחרון ברשימה.
שימוש עם הרספברי פיי
בדוגמה הבאה ניצור סופר לחיצות שיעלה באחד בכל פעם שנלחץ על כפתור שמחובר לESP וישמור את התוצאה בבסיס הנתונים.
להלן קוד PHP שמקבל את הבקשה ושומר אותה בבסיס הנתונים. הקובץ נקרא increment.php:
<?php $redis = new Redis();// start redis instance $redis->pconnect('127.0.0.1', 6379); // connect to redis $redis->incr("button_counter"); // increment button_counter by 1 $redis->close(); // close redis connection ?>
להלן קוד של ESP ששולח בקשה ברגע שלוחצים על הכפתור:
#include <ESP8266WiFi.h> const char* ssid = "your-ssid"; const char* password = "your-password"; const char* host = "192.168.1.101"; const int httpPort = 80; void setup() { Serial.begin(115200); delay(10); WiFi.begin(ssid,password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.println("....."); } } void loop() { delay(10); WiFiClient client; String url = "/increment.php"; if (digitalRead(2) == HIGH){ if (client.connect(host, httpPort)){ delay(10); if(client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n")){ delay(300); Serial.print("ok"); } } } }
עכשיו נדחוף לרדיס נתוני טמפרטורה ולחות מחיישן שנמצא על ESP8266. אפשר לבחור במבנה נתונים של רשימה(list) או שאפשר לעשות משהו מורכב יותר עם מבנה נתונים של hash שהוא כמו אובייקט. כדי לפשט את הדברים נשמור את הנתונים בשלוש רשימות – טמפרטורה, לחות ושעה. הנה הקוד של PHP שמקבל את הנתונים מחיישן הטמפרטורה והלחות ודוחף אותם לרדיס כל חצי שניה!!!
<?php date_default_timezone_set('Asia/Jerusalem'); $temp = $_GET['temp']; $humidity = $_GET['humidity']; $time = date("H:i"); $redis = new Redis(); $redis->pconnect('127.0.0.1', 6379); $redis->lpush("temperature", $temp); $redis->lpush("humidity", $humidity); $redis->lpush("time", $time); $redis->close(); ?>
אני לא אחזור פה שוב על התהליך של שליחת נתונים מחיישן שנמצא על ESP8226 אבל אפשר להיזכר איך עושים את זה כאן.
הנתונים מתמלאים במהירות בבסיס הנתונים וכך זה נראה אחרי כמה דקות:
כאמור כדי לראות את התוצאה צריך להקליד:
lrange temperature 0 -1
רדיס לא מזיע אפילו כשהוא דוחף מסה של מידע לבסיס הנתונים. כך זה נראה שמקלידים את פקודת top:
עוד פקודה חיונית ברדיס היא info שנותנת לראות את כל הפרטים החשובים בתוכנה כולל כמות הזיכרון שהיא לוקחת ופרמטרים נוספים.
שמירה על הדיסק
אפשר לאתחל את הרספברי פיי ולראות שכל המידע שהיה בזיכרון נשמר על הדיסק ברגע שהוא נכבה וכל הנתונים שנשמרו על הדיסק הועתקו חזרה לזכרון כשהוא נדלק. הפקודה bgsave שומרת את הנתונים על הדיסק הקשיח(ברספברי פיי כרטיס הזכרון) בצורה ידנית , אבל ללא קשר הנתונים נשמרים בצורה אוטומטית כל זמן מסוים או לאחר שעבר סף מסוים של שינויים. כל הנתונים נשמרים על קובץ יעודי מסוג RDB. ניתן לשנות את ההגדרות אבל מהניסיון שלי הגדרות ברירת המחדל הן מצוינות ולא נתקלתי במקרה של איבוד נתונים משמעותי.
דבר אחרון שצריך לזכור הוא שהנתונים נשמרים בזיכרון הזמני של הרספברי פיי(RAM). יש לו 1GB וזה נראה הרבה אבל אחרי כמה דקות של דחיפת נתונים מסיבית אני כבר נמצא על קרוב ל1MB. אפשר לפתור את זה על ידי פקודת EXPIRE שמוחקת את הערך ואת המפתח אחרי מספר שניות שקבענו ובאותו הזמן להעתיק את הקובץ ששמור בזיכרון למקום אחר בדיסק.
נכון להיום וגם בעתיד רדיס יהפוך לברירת המחדל החדשה שלי בכל פעם שארצה לשמור מידע בבסיס נתונים.