Redis סיבוב שלישי

הסיבוב הבא עם Redis הולך להכריע איך יגמר הקרב ביני לבין מסד הנתונים המעצבן הזה.

הצלחתי לגרום למפרש שלי לעבוד עם כל דבר שהפרוטוקול מדבר עליו, ואפילו על מספר דברים שמצאתי שהוא לא מדבר עליו, אבל קיימים. ואז קיבלתי סנוקרת אשר הראתה לי קצת כוכבים. המכה גרמה לי לעצור יומיים ולחשוב איך להתמודד איתה, וב2 בלילה הבנתי מה אני צריך לעשות (ארכימדס, מאחוריך).

הבעיה התחילה כאשר פקודה (slowlog) אשר נוצרה לפני 7-8 חודשים במסד נתונים מחזירה משהו אשר מנוגד לגמרי לכללי הפרוטוקול של המסד. כלומר היא מחזירה ערך במבנה חוקי, אבל הפרוטוקול אינו מדבר על הדרך הזו שבכלל נתמכת. ואז בתעוד הפקודה עצמה (לא של הפרוטוקול) אני מוצא משפט קטן ומעצבן שנכתב על השימוש בתכנת ה cli של המסד עצמו:

"Note that you need a recent version of redis-cli in order to read the slow log output, since it uses some features of the protocol that were not formerly implemented in redis-cli (deeply nested multi bulk replies)"

אוף !!!

לא רק שזה לא מתועד בפרוטוקול, אלא צריך לכתוב למקרה הזה קוד חדש לגמרי, אשר סותר קוד קיים, אשר יודע לקחת רשימה (ריקה, null או עם מספר איברים) בעלת איברי bulk ולתרגם אותה כמו שצריך.

פלט לפי הפרוטוקול צריך להראות בצורה הזו (ירידת שורה נעשת על ידי CRLF):

*3
$3
foo
$-1
$3
bar

כוכבית מצביע כי זו רשימה. המספר אחריה אומר שיש שלושה איברים. דולר מסמן שזה איבר מסוג Bulk ואחריו האורך של האיבר בבתים. כלומר foo הוא באורך שלושה בתים.
המספר "מינוס אחד" אומר שהאיבר הוא null. במידה והמספר הוא אפס, זה אומר שהערך ריק, אבל לא null.
והנה התחלתם להבין את רוב הפרוטוקול של Redis, אשר על פניו נראה מאוד קל ופשוט להבנה.

אבל Nested Multi Bulk נראה ככה (ואתם מוזמנים לדלג עליו):

*4
*4
:3
:1328739539
:25
*2
$7
SLOWLOG
$3
GET
*4
:2
:1328739520
:11
*2
$7
SLOWLOG
$3
GET
*4
:1
:1328734845
:16
*2
$7
slowlog
$3
GET
*4
:0
:1328734844
:14
*4
$6
CONFIG
$3
SET
$23
slowlog-log-slower-than
$1
1

הקוד הארוך הזה, הוא רשימה מקוננת. אבל כמו שאתם רואים, יש גם איברים המתחילים בנקודותיים. ובכן נקודתיים אומרים שזה איבר מסוג Integer. שזה יכול לייצג אינדקס כלשהו, Epoch או כל דבר שדורש מספר שלם, אבל אינו מידע שהוא Bulk. לרוב הוא מגיע בשביל לקבל נתונים על המערכת עצמה, כמו כמה רשומות יש בה, גודל זיכרון שהיא תופסת, כמה זמן השרת באוויר וכו' …

התקן אבל מדבר על כך שMulti Bulk נועד לספק רשימה של Bulk. שזה מדבר בעצם לרוב (אם כי לא מחייב) על גישה של Hash Table, כלומר איבר ראשון מפתח, השני הוא הערך השלישי מפתח, הרביעי ערך וכיוב'.  למרשות שהבדגמה הראשונה שלי הדגמתי שימוש פשוט של מערך בעצם. העניין הוא כי אפשר להבין מאיפה מגיע צורך לגבי רשימה מקוננת, אבל מה פתאום מוסיפים לך גם סוג של Integer ?!

השלב הבא הוא להוסיף גם עוד 2 סוגי ערכים אשר לא הוצגו, אבל קיימים בפרוטוקול – סטטוס המכיל גם הודעה (מזהים אותה לפי התחלה עם הסימן פלוס), ושגיאה המכילה גם הודעה (מזהים אותה לפי התחלה עם הסימן מינוס).

אתם מבינים בטח שזה הופך להיות כבר סלט. במקום לשנות את הפרוטוקול ולתת הבהרות, פשוט צריך לנסות ולעבור כמעט פקודה פקודה בשביל להבין איך תהיה התנהגות.

יש למשל פקודה בשם Monitor אשר אינה מדברת בכלל בשפת הפרוטוקול, לפחות לא כמו שאתם חושבים שהיא אמורה לדבר. והיא אף פעם לא חוזרת באמת, אלא אם שולחים לה הוראה בשם QUIT נקי ככה בטקסט, או סוגרים את החיבור.

אז בהתחלה ניסיתי להתמודד עם הבעיה בגישה אשר בה אני מנסה רק לשכתב את התמיכה ב Multi-Bulk, אבל הבנתי שאם אני לא בוחר בדרך אחת מתוך 3:

  1. להתנהג כמו שפה דינאמית, על ידי יצירת  מערכי variant זוללי זיכרון
  2. מתנהג כמו C ולהתחיל ליצור עצים באמצעות רשימות מקושרת, כאשר הגישה לא מאפשרת לי לתחזק ולהבין את הקוד בלי עודף תעוד בתוכו.
  3. מתחיל לחשוב כמו מתכנת ++C או Java ולעבוד עם Generics שאין לי רצון להתקרב אליהם, היות והם לא קריאים וגם זוללים קצת זיכרון שלדעתי מיותר, מאשר השימוש המקורי שניסיתי ליצור.

כך שנראה כאילו הכל אבוד, ואין לי פיתרון אם אני נשאר בגישה הנוכחית של המפרש שלי.

המטרה היא דבר ראשון לעשות קוד מהיר ויעיל, אבל כמה שפחות לוותר על היכולת לתחזק ולהבין אותו. כמו כן הוא צריך להשתמש בכמה שפחות משאבים של המערכת. אז הבנתי שאין ברירה, ואני צריך לשכתב מ0 את המפרש הנוכחי שלי. אז התחלתי לחשוב איך אני עושה את זה.

התחלתי לקרוא קוד שכתוב דווקא ב Java, וראיתי שהם כמעט עשו הכל כמו בגישה שלי, והמפרש שלהם נתן לי רעיון איך לכתוב את שלי. 2 דברים שהם עשו שלא קרוב לגישה שלי:

א. אני מספק לך – המתכנת גישה נמוכה יותר לשליחה וקבלה של פקודות ובנוסף גם גישה לsocket עצמו אם חייבים.

ב. אני מספק אפשרות לכתוב מידע של debug ושגיאות לlog מסויים (המפתח מנהל ומחליט הכל לבד).  ובכך אפשרות לתעד מה קורה גם כאשר נמצאים בזמן ריצה ולא במצב של debug כלשהו מאחורי gdb או כול מנפה שגיאות אחר.

אם הדרך הזו לא תפתור את כל הבעיות, והבעיות הקריטיות ימשכו, וידרשו ממני המון אנרגיה בשביל לפתור אותן, כנראה שאפסיק לפתח את התמיכה לזה, ואחפש מסד נתונים אחר שיהיה טוב יותר עבורי, והקוד יהיה עדיין זמין למי רוצה להרים את הכפפה ולהמשיך לפתח.

מחשבה אחת על “Redis סיבוב שלישי

  1. פינגבק: המפרש החדש שכתבתי ל Redis | לראות שונה

כתיבת תגובה

הזינו את פרטיכם בטופס, או לחצו על אחד מהאייקונים כדי להשתמש בחשבון קיים:

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s