โดย อังเดร เชอร์นิคอฟ
Redis เป็นตารางในหน่วยความจำยอดนิยมที่ใช้สำหรับการสื่อสารระหว่างกระบวนการและการจัดเก็บข้อมูล คุณอาจเคยได้ยินมาว่ามันให้คุณเรียกใช้สคริปต์ Lua ได้ แต่คุณก็ยังไม่แน่ใจว่าทำไม หากฟังดูเหมือนคุณ โปรดอ่านต่อ
ข้อกำหนดเบื้องต้น
คุณควรติดตั้ง Redis บนระบบของคุณเพื่อปฏิบัติตามคำแนะนำนี้ การตรวจสอบการอ้างอิงคำสั่ง Redis ขณะอ่านอาจเป็นประโยชน์
เหตุใดฉันจึงต้องมีสคริปต์ Lua
กล่าวโดยย่อ:ประสิทธิภาพเพิ่มขึ้น งานส่วนใหญ่ที่คุณทำใน Redis เกี่ยวข้องกับหลายขั้นตอน แทนที่จะทำตามขั้นตอนเหล่านี้ในภาษาของแอปพลิเคชันของคุณ คุณสามารถทำได้ภายใน Redis กับ Lua
- ซึ่งอาจส่งผลให้ประสิทธิภาพดีขึ้น
- นอกจากนี้ ขั้นตอนทั้งหมดภายในสคริปต์จะดำเนินการในลักษณะอะตอมมิก ไม่มีคำสั่ง Redis อื่นใดที่สามารถทำงานได้ในขณะที่สคริปต์กำลังดำเนินการอยู่
ตัวอย่างเช่น ฉันใช้สคริปต์ Lua เพื่อเปลี่ยนสตริง JSON ที่จัดเก็บไว้ใน Redis ฉันอธิบายรายละเอียดนี้ในตอนท้ายของบทความนี้
แต่ฉันไม่รู้จักลัวะเลย
คนที่ไม่รู้จักลัวะเลย ป>
ไม่ต้องกังวล Lua เข้าใจได้ไม่ยากนัก หากคุณรู้ภาษาใด ๆ ของตระกูล C คุณควรจะโอเคกับ Lua นอกจากนี้ ฉันกำลังยกตัวอย่างการทำงานในบทความนี้
แสดงตัวอย่าง
เริ่มต้นด้วยการเรียกใช้สคริปต์ผ่าน redis-cli . เริ่มต้นด้วย:
redis-cli
ตอนนี้รันคำสั่งต่อไปนี้:
eval “redis.call(‘set’, KEYS[1], ARGV[1])” 1 key:name value
EVAL command คือสิ่งที่บอกให้ Redis รันสคริปต์ซึ่งตามมา 01รหัส> string คือสคริปต์ของเราซึ่งมีฟังก์ชันการทำงานเหมือนกับ 14 ของ Redis คำสั่ง พารามิเตอร์สามตัวตามข้อความสคริปต์:
- จำนวนคีย์ที่ให้มา
- ชื่อคีย์
- อาร์กิวเมนต์แรก
อาร์กิวเมนต์สคริปต์แบ่งออกเป็นสองกลุ่ม:KEYS และ ARGV .
เราระบุจำนวนคีย์ที่สคริปต์ต้องการโดยมีตัวเลขตามมาทันที ในตัวอย่างของเรา มันคือ 1 . ทันทีหลังจากหมายเลขนี้ เราต้องจัดเตรียมกุญแจเหล่านี้ทีละอัน สามารถเข้าถึงได้ในรูปแบบ KEYS ตารางภายในสคริปต์ ในกรณีของเรา จะมีค่าเดียวคือ 22 ที่ดัชนี 1 .
โปรดทราบว่าตารางที่จัดทำดัชนี Lua เริ่มต้นด้วยดัชนี 1, ไม่ 0 . ป>
เราสามารถระบุอาร์กิวเมนต์จำนวนเท่าใดก็ได้หลังคีย์ ซึ่งจะพร้อมใช้งานในภาษา Lua เป็น ARGV ตาราง ในตัวอย่างนี้ เราระบุ ARGV รายการเดียว -อาร์กิวเมนต์:สตริง 33 . ตามที่คุณเดาแล้ว คำสั่งด้านบนจะตั้งค่าคีย์ 47 เป็นค่า 55 .
ถือเป็นแนวปฏิบัติที่ดีที่จะจัดเตรียมคีย์ที่สคริปต์ใช้เป็น KEYS และอาร์กิวเมนต์อื่นๆ ทั้งหมดเป็น ARGV . ดังนั้นคุณไม่ควรระบุ KEYS เป็น 0 จากนั้นระบุคีย์ทั้งหมดภายใน ARGV ตาราง
ตอนนี้เรามาตรวจสอบว่าสคริปต์เสร็จสมบูรณ์หรือไม่ เราจะดำเนินการนี้โดยการเรียกใช้สคริปต์อื่นซึ่งรับคีย์จาก Redis:
eval “return redis.call('get', KEYS[1])” 1 คีย์:ชื่อ
ผลลัพธ์ควรเป็น 65 ซึ่งหมายความว่าสคริปต์ก่อนหน้าตั้งค่าคีย์ 74 ได้สำเร็จ .
คุณช่วยอธิบายสคริปต์ได้ไหม
Doge หลังจากเห็นสคริปต์ด้านบน ป>
สคริปต์แรกของเราประกอบด้วยคำสั่งเดียว:87 ฟังก์ชัน:
redis.call(‘set’, KEYS[1], ARGV[1])
ด้วย96 คุณสามารถดำเนินการคำสั่ง Redis ใดก็ได้ อาร์กิวเมนต์แรกคือชื่อของคำสั่งนี้ตามด้วยพารามิเตอร์ ในกรณีของ 101 คำสั่ง อาร์กิวเมนต์เหล่านี้คือ คีย์ และค่า . รองรับคำสั่ง Redis ทั้งหมด ตามเอกสารประกอบ:
Redis ใช้ล่าม Lua เดียวกันเพื่อรันคำสั่งทั้งหมด ป>
สคริปต์ที่สองของเราทำมากกว่าการรันคำสั่งเดียวเพียงเล็กน้อย แต่ยังส่งคืนค่า:
eval “return redis.call(‘get’, KEYS[1])” 1 key:name
ทุกสิ่งที่สคริปต์ส่งคืนจะถูกส่งไปยังกระบวนการเรียก ในกรณีของเรา กระบวนการนี้คือ redis-cli และคุณจะเห็นผลลัพธ์ในหน้าต่างเทอร์มินัลของคุณ
มีอะไรซับซ้อนกว่านี้ไหม
บุคคลที่วางแผนจะสร้างสคริปต์ Redis ที่ซับซ้อน ป>
ฉันเคยใช้สคริปต์ Lua เพื่อส่งคืนองค์ประกอบจากแมปแฮชตามลำดับเฉพาะ ลำดับนั้นถูกระบุโดยแฮชคีย์ที่จัดเก็บไว้ในชุดที่เรียงลำดับ
ขั้นแรกเรามาตั้งค่าข้อมูลของเราด้วยการรันคำสั่งเหล่านี้ใน redis-cli :
hmset hkeys key:1 value:1 key:2 value:2 key:3 value:3 key:4 value:4 key:5 value:5 key:6 value:6
zadd order 1 key:3 2 key:1 3 key:2
คำสั่งเหล่านี้สร้างแผนที่แฮชที่คีย์ 115 และชุดที่เรียงลำดับที่คีย์ 120 ซึ่งมีคีย์ที่เลือกจาก 131 ในลำดับเฉพาะ
คุณอาจต้องการตรวจสอบ อืมเซ็ต และ แซด อ้างอิงคำสั่งเพื่อดูรายละเอียด ป>
มาเรียกใช้สคริปต์ต่อไปนี้:
eval “local order = redis.call(‘zrange’, KEYS[1], 0, -1); return redis.call(‘hmget’,KEYS[2],unpack(order));” 2 order hkeys
คุณควรเห็นผลลัพธ์ต่อไปนี้:
“value:3”
“value:1”
“value:2”
ซึ่งหมายความว่าเราได้รับค่าของคีย์ที่เราต้องการและอยู่ในลำดับที่ถูกต้อง
ฉันต้องระบุข้อความสคริปต์แบบเต็มเพื่อเรียกใช้หรือไม่
ไม่! Redis ช่วยให้คุณสามารถโหลดสคริปต์ล่วงหน้าลงในหน่วยความจำด้วย SCRIPT LOAD คำสั่ง:
script load “return redis.call(‘get’, KEYS[1])”
คุณควรเห็นผลลัพธ์ดังนี้:
“4e6d8fc8bb01276962cce5371fa795a7763657ae”
นี่คือแฮชเฉพาะของสคริปต์ที่คุณต้องระบุให้กับ EVALSHA คำสั่งเพื่อรันสคริปต์:
evalsha 4e6d8fc8bb01276962cce5371fa795a7763657ae 1 key:name
หมายเหตุ:คุณควรใช้ค่าจริง SHA1 แฮชที่ส่งคืนโดย โหลดสคริปต์ คำสั่ง แฮชด้านบนนี้เป็นเพียงตัวอย่างเท่านั้น ป>
คุณพูดถึงอะไรเกี่ยวกับการเปลี่ยน JSON
บางครั้งผู้คนเก็บวัตถุ JSON ไว้ใน Redis ไม่ว่าจะเป็นความคิดที่ดีหรือไม่ก็เป็นอีกเรื่องหนึ่ง แต่ในทางปฏิบัติ สิ่งนี้เกิดขึ้นบ่อยครั้ง
หากคุณต้องเปลี่ยนคีย์ในออบเจ็กต์ JSON นี้ คุณจะต้องรับคีย์จาก Redis แยกวิเคราะห์ เปลี่ยนคีย์ จากนั้นทำให้เป็นอนุกรมและตั้งค่ากลับเป็น Redis แนวทางนี้มีปัญหาสองสามประการ:
- การทำงานพร้อมกัน กระบวนการอื่นสามารถเปลี่ยน JSON นี้ระหว่างการดำเนินการรับและตั้งค่าของเรา ในกรณีนี้ การเปลี่ยนแปลงจะหายไป
- ประสิทธิภาพ หากคุณทำการเปลี่ยนแปลงเหล่านี้บ่อยเพียงพอและหากออบเจ็กต์ค่อนข้างใหญ่ สิ่งนี้อาจกลายเป็นปัญหาคอขวดของแอปของคุณ คุณสามารถชนะประสิทธิภาพได้โดยใช้ตรรกะนี้ใน Lua
มาเพิ่มสตริงทดสอบ JSON ให้กับ Redis ภายใต้คีย์ 140 :
set obj ‘{“a”:”foo”,”b”:”bar”}’
ตอนนี้มารันสคริปต์ของเรา:
EVAL ‘local obj = redis.call(“get”,KEYS[1]); local obj2 = string.gsub(obj,”(“ .. ARGV[1] .. “\”:)([^,}]+)”, “%1” .. ARGV[2]); return redis.call(“set”,KEYS[1],obj2);’ 1 obj b bar2
ตอนนี้เราจะมีวัตถุต่อไปนี้ภายใต้คีย์ 152 :
{“a”:”foo”,”b”:”bar2"}
คุณสามารถโหลดสคริปต์นี้ด้วย SCRIPT LOAD แทนได้ คำสั่ง:
SCRIPT LOAD ‘local obj = redis.call(“get”,KEYS[1]); local obj2 = string.gsub(obj,”(“ .. ARGV[1] .. “\”:)([^,}]+)”, “%1” .. ARGV[2]); return redis.call(“set”,KEYS[1],obj2);’
จากนั้นเรียกใช้ดังนี้:
EVALSHA <your_script_sha> 1 obj b bar2
หมายเหตุบางประการ: ป>
163รหัส> เป็นตัวดำเนินการต่อสตริงใน Lua- เราใช้รูปแบบ RegEx เพื่อจับคู่คีย์และแทนที่ค่าของมัน หากคุณไม่เข้าใจนิพจน์ทั่วไปนี้ คุณสามารถดูคำแนะนำล่าสุดของฉันได้
- ความแตกต่างประการหนึ่งของรสชาติ Lua RegEx จากรสชาติอื่นๆ ส่วนใหญ่คือเราใช้
176เป็นทั้งเครื่องหมายอ้างอิงด้านหลังและอักขระหลีกสำหรับสัญลักษณ์พิเศษ RegEx - เรายังคงหนีจาก
180ด้วย190และไม่ใช่202เพราะเรายกเว้นตัวคั่นสตริง Lua ไม่ใช่สัญลักษณ์พิเศษ RegEx
ฉันควรใช้สคริปต์ Lua เสมอหรือไม่
ไม่ ฉันแนะนำให้ใช้เมื่อคุณสามารถพิสูจน์ได้ว่าผลลัพธ์นั้นมีประสิทธิภาพดีขึ้นเท่านั้น เรียกใช้การวัดประสิทธิภาพก่อนเสมอ
หากสิ่งที่คุณต้องการคืออะตอมมิกซิตี คุณควรตรวจสอบธุรกรรม Redis แทน
นอกจากนี้สคริปต์ของคุณไม่ควรยาวเกินไป โปรดจำไว้ว่าในขณะที่สคริปต์กำลังทำงาน สิ่งอื่นๆ กำลังรอให้สคริปต์เสร็จสิ้น หากสคริปต์ของคุณใช้เวลาค่อนข้างนาน ก็อาจทำให้เกิดปัญหาคอขวดแทนที่จะปรับปรุงประสิทธิภาพได้ สคริปต์หยุดหลังจากหมดเวลา (5 วินาทีโดยค่าเริ่มต้น)
สคริปต์ Redis ไม่ควรใช้เวลานานเกินไป ป>
คำสุดท้าย
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ Lua โปรดตรวจสอบ lua.org
คุณสามารถตรวจสอบไลบรารี node.js ของฉันบน GitHub เพื่อดูตัวอย่างสคริปต์ Lua (ดู 214 โฟลเดอร์) คุณยังสามารถใช้ไลบรารีนี้ใน node.js เพื่อเปลี่ยนอ็อบเจ็กต์ JSON โดยไม่ต้องเขียนสคริปต์ Lua ด้วยตัวเอง
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —
ขอขอบคุณที่อ่านบทความนี้ คำถามและความคิดเห็นได้รับการชื่นชมมาก คุณสามารถติดตามฉันได้เช่นกัน บนทวิตเตอร์ . ป>
เรียนรู้การเขียนโค้ดฟรี หลักสูตรโอเพ่นซอร์สของ freeCodeCamp ช่วยให้ผู้คนมากกว่า 40,000 คนได้งานในตำแหน่งนักพัฒนา เริ่มต้น