ก่อนที่จะดำเนินการต่อ โปรดพิจารณาให้ดาว GitHub แก่เรา ️ ขอบคุณ!
ภาษาอื่น ๆ: 简体中文 日本語 เกาหลี어
เว็บไซต์ • เอกสาร • เริ่มต้นอย่างรวดเร็ว • ความไม่ลงรอยกันของชุมชน • ฟอรั่มแมลงปอ • เข้าร่วมชุมชนแมลงปอ
การสนทนา GitHub • ปัญหา GitHub • การมีส่วนร่วม • Dragonfly Cloud
Dragonfly เป็นที่เก็บข้อมูลในหน่วยความจำที่สร้างขึ้นสำหรับปริมาณงานแอปพลิเคชันสมัยใหม่
Dragonfly เข้ากันได้อย่างสมบูรณ์กับ Redis และ Memcached API ไม่จำเป็นต้องเปลี่ยนแปลงโค้ดเพื่อนำไปใช้ เมื่อเปรียบเทียบกับพื้นที่เก็บข้อมูลในหน่วยความจำแบบเดิม Dragonfly ให้ปริมาณงานมากกว่า 25 เท่า อัตราการเข้าถึงแคชที่สูงขึ้นพร้อมเวลาแฝงที่ต่ำกว่า และสามารถทำงานได้บนทรัพยากรน้อยลงสูงสุดถึง 80% สำหรับเวิร์กโหลดที่มีขนาดเท่ากัน
อันดับแรก เราจะเปรียบเทียบ Dragonfly กับ Redis บนอินสแตนซ์ m5.large
ซึ่งมักใช้ในการรัน Redis เนื่องจากสถาปัตยกรรมแบบเธรดเดียว โปรแกรมวัดประสิทธิภาพทำงานจากอินสแตนซ์ทดสอบโหลดอื่น (c5n) ใน AZ เดียวกันโดยใช้ memtier_benchmark -c 20 --test-time 100 -t 4 -d 256 --distinct-client-seed
แมลงปอแสดงประสิทธิภาพที่เทียบเคียงได้:
--ratio 1:0
):เรดิส | ดีเอฟ |
---|---|
คิวพีเอส: 159K, P99.9: 1.16ms, P99: 0.82ms | QPS:173K, P99.9: 1.26ms, P99: 0.9ms |
--ratio 0:1
):เรดิส | ดีเอฟ |
---|---|
คิวพีเอส: 194K, P99.9: 0.8ms, P99: 0.65ms | คิวพีเอส: 191K, P99.9: 0.95ms, P99: 0.8ms |
เกณฑ์มาตรฐานข้างต้นแสดงให้เห็นว่าเลเยอร์อัลกอริธึมภายใน DF ที่ช่วยให้สามารถขยายขนาดในแนวตั้งได้นั้นไม่ได้ส่งผลเสียมากนักเมื่อรันแบบเธรดเดียว
อย่างไรก็ตาม หากเราใช้อินสแตนซ์ที่แข็งแกร่งขึ้นอีกเล็กน้อย (m5.xlarge) ช่องว่างระหว่าง DF และ Redis ก็เริ่มเพิ่มขึ้น ( memtier_benchmark -c 20 --test-time 100 -t 6 -d 256 --distinct-client-seed
):
--ratio 1:0
):เรดิส | ดีเอฟ |
---|---|
คิวพีเอส: 190K, P99.9: 2.45ms, P99: 0.97ms | คิวพีเอส: 279K , P99.9: 1.95ms, P99: 1.48ms |
--ratio 0:1
):เรดิส | ดีเอฟ |
---|---|
คิวพีเอส: 220K, P99.9: 0.98ms , P99: 0.8ms | คิวพีเอส: 305K, P99.9: 1.03ms, P99: 0.87ms |
ความจุปริมาณการประมวลผลของ Dragonfly ยังคงเพิ่มขึ้นตามขนาดอินสแตนซ์ ในขณะที่ Redis แบบเธรดเดี่ยวมีปัญหาคอขวดบน CPU และถึงจุดสูงสุดในพื้นที่ในแง่ของประสิทธิภาพ
หากเราเปรียบเทียบ Dragonfly และ Redis บนอินสแตนซ์ c6gn.16xlarge ที่รองรับเครือข่ายได้มากที่สุด Dragonfly แสดงปริมาณการประมวลผลเพิ่มขึ้น 25 เท่า เมื่อเทียบกับ Redis กระบวนการเดียว โดยข้าม 3.8M QPS
ตัวชี้วัดเวลาแฝงที่ 99 ของ Dragonfly ที่ปริมาณงานสูงสุด:
ปฏิบัติการ | r6g | c6gn | c7g |
---|---|---|---|
ชุด | 0.8ms | 1ms | 1ms |
รับ | 0.9ms | 0.9ms | 0.8ms |
เซเท็กซ์ | 0.9ms | 1.1ms | 1.3ms |
การวัดประสิทธิภาพทั้งหมดดำเนินการโดยใช้ memtier_benchmark
(ดูด้านล่าง) พร้อมจำนวนเธรดที่ปรับต่อเซิร์ฟเวอร์และประเภทอินสแตนซ์ memtier
ทำงานบนเครื่อง c6gn.16xlarge แยกต่างหาก เราตั้งเวลาหมดอายุเป็น 500 สำหรับเกณฑ์มาตรฐาน SETEX เพื่อให้แน่ใจว่าจะรอดพ้นเมื่อสิ้นสุดการทดสอบ
memtier_benchmark --ratio ... -t < threads > -c 30 -n 200000 --distinct-client-seed -d 256
--expiry-range=...
ในโหมดไปป์ไลน์ --pipeline=30
Dragonfly เข้าถึง 10M QPS สำหรับ SET และ 15M QPS สำหรับการดำเนินการ GET
เราเปรียบเทียบ Dragonfly กับ Memcached บนอินสแตนซ์ c6gn.16xlarge บน AWS
ด้วยเวลาแฝงที่เทียบเคียงได้ ปริมาณการประมวลผลของ Dragonfly มีประสิทธิภาพเหนือกว่าปริมาณงาน Memcached ทั้งในเวิร์กโหลดการเขียนและการอ่าน Dragonfly แสดงให้เห็นเวลาแฝงที่ดีขึ้นในปริมาณงานการเขียนเนื่องจากการโต้แย้งบนเส้นทางการเขียนใน Memcached
เซิร์ฟเวอร์ | QPS(พันคิวพีเอส) | เวลาแฝง 99% | 99.9% |
---|---|---|---|
แมลงปอ | - 3844 | - 0.9ms | - 2.4ms |
เมคแคช | 806 | 1.6ms | 3.2ms |
เซิร์ฟเวอร์ | QPS(พันคิวพีเอส) | เวลาแฝง 99% | 99.9% |
---|---|---|---|
แมลงปอ | - 3717 | 1ms | 2.4ms |
เมคแคช | 2100 | - 0.34ms | - 0.6ms |
Memcached แสดงเวลาแฝงที่ต่ำกว่าสำหรับเกณฑ์มาตรฐานการอ่าน แต่ยังมีปริมาณการประมวลผลที่ต่ำกว่าอีกด้วย
เพื่อทดสอบประสิทธิภาพของหน่วยความจำ เราได้เติมข้อมูลประมาณ 5GB ให้กับ Dragonfly และ Redis โดยใช้คำสั่ง debug populate 5000000 key 1024
ส่งการรับส่งข้อมูลการอัปเดตด้วย memtier
และเริ่มการถ่ายภาพสแน็ปช็อตด้วยคำสั่ง bgsave
รูปนี้แสดงให้เห็นว่าแต่ละเซิร์ฟเวอร์ทำงานอย่างไรในแง่ของประสิทธิภาพของหน่วยความจำ
Dragonfly มีประสิทธิภาพหน่วยความจำมากกว่า Redis ถึง 30% ในสถานะไม่ได้ใช้งาน และไม่แสดงการใช้หน่วยความจำที่เพิ่มขึ้นอย่างเห็นได้ชัดในระหว่างขั้นตอนสแน็ปช็อต เมื่อถึงจุดสูงสุด การใช้หน่วยความจำ Redis เพิ่มขึ้นเป็นเกือบ 3 เท่าของ Dragonfly
แมลงปอถ่ายภาพเสร็จเร็วขึ้นภายในไม่กี่วินาที
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับประสิทธิภาพของหน่วยความจำใน Dragonfly โปรดดูเอกสาร Dashtable ของเรา
Dragonfly รองรับอาร์กิวเมนต์ Redis ทั่วไปตามความเหมาะสม ตัวอย่างเช่น คุณสามารถเรียกใช้: dragonfly --requirepass=foo --bind localhost
ปัจจุบัน Dragonfly รองรับข้อโต้แย้งเฉพาะ Redis ต่อไปนี้:
port
: พอร์ตการเชื่อมต่อ Redis ( default: 6379
)bind
: ใช้ localhost
เพื่ออนุญาตเฉพาะการเชื่อมต่อ localhost หรือที่อยู่ IP สาธารณะเพื่ออนุญาตการเชื่อมต่อ กับที่อยู่ IP นั้น (เช่นจากภายนอกด้วย) ใช้ 0.0.0.0
เพื่ออนุญาต IPv4 ทั้งหมดrequirepass
: รหัสผ่านสำหรับการตรวจสอบสิทธิ์ AUTH ( default: ""
)maxmemory
: จำกัดหน่วยความจำสูงสุด (เป็นไบต์ที่มนุษย์สามารถอ่านได้) ที่ใช้โดยฐานข้อมูล ( default: 0
) ค่า maxmemory
เป็น 0
หมายความว่าโปรแกรมจะกำหนดการใช้งานหน่วยความจำสูงสุดโดยอัตโนมัติdir
: Dragonfly Docker ใช้โฟลเดอร์ /data
สำหรับการถ่ายภาพสแน็ปช็อตตามค่าเริ่มต้น CLI จะใช้ ""
คุณสามารถใช้ตัวเลือก -v
Docker เพื่อแมปมันกับโฟลเดอร์โฮสต์ของคุณdbfilename
: ชื่อไฟล์ที่จะบันทึกและโหลดฐานข้อมูล ( default: dump
)นอกจากนี้ยังมีข้อโต้แย้งเฉพาะของแมลงปอด้วย:
memcached_port
: พอร์ตสำหรับเปิดใช้งาน API ที่เข้ากันได้กับ Memcached ( default: disabled
)
keys_output_limit
: จำนวนคีย์ที่ส่งคืนสูงสุดในคำสั่ง keys
( default: 8192
) โปรดทราบว่า keys
เป็นคำสั่งที่อันตราย เราตัดทอนผลลัพธ์เพื่อหลีกเลี่ยงการใช้หน่วยความจำมากเกินไปเมื่อดึงคีย์มากเกินไป
dbnum
: จำนวนฐานข้อมูลสูงสุดที่รองรับสำหรับ select
.
cache_mode
: ดูส่วนการออกแบบแคชใหม่ด้านล่าง
hz
: ความถี่ในการประเมินการหมดอายุของคีย์ ( default: 100
) ความถี่ที่ต่ำกว่าจะใช้ CPU น้อยลงเมื่อไม่ได้ใช้งาน โดยมีอัตราการไล่ออกที่ช้าลง
snapshot_cron
: นิพจน์กำหนดการ Cron สำหรับสแน็ปช็อตการสำรองข้อมูลอัตโนมัติโดยใช้ไวยากรณ์ cron มาตรฐานพร้อมรายละเอียดเป็นนาที ( default: ""
) ต่อไปนี้เป็นตัวอย่างนิพจน์กำหนดการ cron ด้านล่าง และโปรดอ่านเพิ่มเติมเกี่ยวกับข้อโต้แย้งนี้ในเอกสารประกอบของเรา
นิพจน์กำหนดการ Cron | คำอธิบาย |
---|---|
* * * * * | ในทุกนาที |
*/5 * * * * | ทุกๆนาทีที่ 5 |
5 */2 * * * | นาทีที่ 5 ผ่านไปทุกชั่วโมงที่ 2 |
0 0 * * * | เวลา 00.00 น. (เที่ยงคืน) ทุกวัน |
0 6 * * 1-5 | เวลา 06:00 น. (รุ่งเช้า) ตั้งแต่วันจันทร์ถึงวันศุกร์ |
primary_port_http_enabled
: อนุญาตให้เข้าถึงคอนโซล HTTP บนพอร์ต TCP หลักหากเป็น true
( default: true
)
admin_port
: เพื่อเปิดใช้งานการเข้าถึงของผู้ดูแลระบบไปยังคอนโซลบนพอร์ตที่กำหนด ( default: disabled
) รองรับทั้งโปรโตคอล HTTP และ RESP
admin_bind
: เพื่อผูกการเชื่อมต่อ TCP คอนโซลผู้ดูแลระบบกับที่อยู่ที่กำหนด ( default: any
) รองรับทั้งโปรโตคอล HTTP และ RESP
admin_nopass
: เพื่อเปิดใช้งานการเข้าถึงคอนโซลของผู้ดูแลระบบแบบเปิดบนพอร์ตที่กำหนด โดยไม่ต้องใช้โทเค็นการรับรองความถูกต้อง ( default: false
) รองรับทั้งโปรโตคอล HTTP และ RESP
cluster_mode
: รองรับโหมดคลัสเตอร์ ( default: ""
) ปัจจุบันรองรับ emulated
เท่านั้น
cluster_announce_ip
: IP ที่คำสั่งคลัสเตอร์ประกาศไปยังไคลเอ็นต์
announce_port
: พอร์ตที่คำสั่งคลัสเตอร์ประกาศไปยังไคลเอ็นต์ และไปยังต้นแบบการจำลอง
./dragonfly-x86_64 --logtostderr --requirepass=youshallnotpass --cache_mode=true -dbnum 1 --bind localhost --port 6379 --maxmemory=12gb --keys_output_limit=12288 --dbfilename dump.rdb
นอกจากนี้ยังสามารถให้ข้อโต้แย้งผ่านทาง:
--flagfile <filename>
: ไฟล์ควรแสดงรายการหนึ่งแฟล็กต่อบรรทัด โดยมีเครื่องหมายเท่ากับแทนการเว้นวรรคสำหรับแฟล็กคีย์-ค่า ไม่จำเป็นต้องมีเครื่องหมายคำพูดสำหรับค่าแฟล็กDFLY_x
โดยที่ x
คือชื่อที่แน่นอนของแฟล็ก โดยคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ หากต้องการตัวเลือกเพิ่มเติม เช่น การจัดการบันทึกหรือการสนับสนุน TLS ให้เรียกใช้ dragonfly --help
ปัจจุบัน Dragonfly รองรับคำสั่ง Redis ประมาณ 185 คำสั่งและคำสั่ง Memcached ทั้งหมด นอกเหนือจาก cas
เกือบจะเทียบเท่ากับ Redis 5 API แล้ว เป้าหมายถัดไปของ Dragonfly คือการรักษาเสถียรภาพของฟังก์ชันพื้นฐานและการนำ API การจำลองไปใช้ หากมีคำสั่งที่คุณต้องการแต่ยังไม่ได้ดำเนินการ โปรดเปิดปัญหา
สำหรับการจำลองแบบ Dragonfly-native เรากำลังออกแบบรูปแบบบันทึกแบบกระจายที่จะรองรับความเร็วที่สูงกว่าตามลำดับขนาด
หลังจากฟีเจอร์การจำลอง เราจะเพิ่มคำสั่งที่ขาดหายไปสำหรับ Redis เวอร์ชัน 3-6 API ต่อไป
โปรดดูการอ้างอิงคำสั่งของเราสำหรับคำสั่งปัจจุบันที่ Dragonfly รองรับ
Dragonfly มีอัลกอริธึมแคชแบบรวมเป็นหนึ่งเดียวที่ปรับเปลี่ยนได้ ซึ่งเรียบง่ายและมีประสิทธิภาพหน่วยความจำ
คุณสามารถเปิดใช้งานโหมดแคชได้โดยส่งแฟล็ก --cache_mode=true
เมื่อเปิดโหมดนี้ แมลงปอจะกำจัดไอเทมที่มีแนวโน้มว่าจะสะดุดน้อยที่สุดในอนาคต แต่จะกำจัดเมื่อใกล้ถึงขีดจำกัดหน่วย maxmemory
เท่านั้น
ช่วงการหมดอายุจำกัดอยู่ที่ ~8 ปี
กำหนดเวลาหมดอายุที่มีความแม่นยำระดับมิลลิวินาที (PEXPIRE, PSETEX ฯลฯ) จะถูกปัดเศษเป็นวินาทีที่ใกล้เคียงที่สุด สำหรับกำหนดเวลาที่มากกว่า 2^28ms ซึ่งมีข้อผิดพลาดน้อยกว่า 0.001% และควรยอมรับได้สำหรับช่วงขนาดใหญ่ หากสิ่งนี้ไม่เหมาะกับกรณีการใช้งานของคุณ โปรดติดต่อหรือเปิดประเด็นเพื่ออธิบายกรณีของคุณ
สำหรับความแตกต่างโดยละเอียดเพิ่มเติมระหว่างกำหนดเวลาหมดอายุของ Dragonfly และการใช้งาน Redis โปรดดูที่นี่
ตามค่าเริ่มต้น Dragonfly อนุญาตให้เข้าถึง HTTP ผ่านพอร์ต TCP หลัก (6379) ถูกต้อง คุณสามารถเชื่อมต่อกับ Dragonfly ผ่านโปรโตคอล Redis และผ่านโปรโตคอล HTTP ได้ — เซิร์ฟเวอร์จะจดจำโปรโตคอลโดยอัตโนมัติระหว่างการเริ่มต้นการเชื่อมต่อ ไปข้างหน้าและลองใช้เบราว์เซอร์ของคุณ ขณะนี้การเข้าถึง HTTP ไม่มีข้อมูลมากนัก แต่จะรวมข้อมูลการแก้ไขข้อบกพร่องและการจัดการที่เป็นประโยชน์ในอนาคต
ไปที่ URL :6379/metrics
เพื่อดูตัววัดที่เข้ากันได้กับ Prometheus
ตัววัดที่ส่งออกของ Prometheus เข้ากันได้กับแดชบอร์ด Grafana ดูที่นี่
สำคัญ! คอนโซล HTTP มีไว้เพื่อให้เข้าถึงได้ภายในเครือข่ายที่ปลอดภัย หากคุณเปิดเผยพอร์ต TCP ของ Dragonfly ภายนอก เราขอแนะนำให้คุณปิดการใช้งานคอนโซลด้วย --http_admin_console=false
หรือ --nohttp_admin_console
Dragonfly เริ่มต้นจากการทดลองเพื่อดูว่าพื้นที่เก็บข้อมูลในหน่วยความจำจะมีลักษณะอย่างไรหากได้รับการออกแบบในปี 2022 จากบทเรียนที่เรียนรู้จากประสบการณ์ของเราในฐานะผู้ใช้พื้นที่จัดเก็บหน่วยความจำและวิศวกรที่ทำงานให้กับบริษัทระบบคลาวด์ เรารู้ว่าเราต้องอนุรักษ์สองแห่ง คุณสมบัติหลักของ Dragonfly: Atomicity รับประกันการทำงานทั้งหมดและความหน่วงต่ำ ต่ำกว่ามิลลิวินาทีผ่านปริมาณงานที่สูงมาก
ความท้าทายแรกของเราคือการใช้ทรัพยากร CPU, หน่วยความจำ และ I/O อย่างเต็มที่โดยใช้เซิร์ฟเวอร์ที่พร้อมใช้งานในระบบคลาวด์สาธารณะในปัจจุบัน เพื่อแก้ปัญหานี้ เราใช้สถาปัตยกรรมที่ไม่มีการแชร์ ซึ่งช่วยให้เราสามารถแบ่งพาร์ติชันคีย์สเปซของที่เก็บหน่วยความจำระหว่างเธรด เพื่อให้แต่ละเธรดสามารถจัดการข้อมูลพจนานุกรมของตนเองได้ เราเรียกชิ้นเหล่านี้ว่า "เศษ" ไลบรารีที่ขับเคลื่อนการจัดการเธรดและ I/O สำหรับสถาปัตยกรรมที่ไม่มีการแบ่งปันนั้นเป็นโอเพ่นซอร์สที่นี่
เพื่อให้การรับประกันความเป็นอะตอมมิกสำหรับการดำเนินงานแบบหลายคีย์ เราใช้ความก้าวหน้าจากการวิจัยทางวิชาการล่าสุด เราเลือกเอกสาร "VLL: การออกแบบตัวจัดการการล็อกใหม่สำหรับระบบฐานข้อมูลหน่วยความจำหลัก" เพื่อพัฒนากรอบงานธุรกรรมสำหรับ Dragonfly การเลือกสถาปัตยกรรมแบบไม่มีการแบ่งปันและ VLL ช่วยให้เราสามารถเขียนการดำเนินการแบบหลายคีย์แบบอะตอมมิกได้โดยไม่ต้องใช้ mutexes หรือ spinlocks สิ่งนี้ เป็นเหตุการณ์สำคัญสำหรับ PoC ของเรา และประสิทธิภาพของมันโดดเด่นกว่าโซลูชันเชิงพาณิชย์และโอเพ่นซอร์สอื่นๆ
ความท้าทายประการที่สองของเราคือการออกแบบโครงสร้างข้อมูลที่มีประสิทธิภาพมากขึ้นสำหรับร้านค้าใหม่ เพื่อให้บรรลุเป้าหมายนี้ เราได้ใช้โครงสร้างแฮชเทเบิลหลักของเราบนรายงาน "Dash: Scalable Hashing on Persistent Memory" บทความนี้มีศูนย์กลางอยู่ที่โดเมนหน่วยความจำถาวร และไม่เกี่ยวข้องโดยตรงกับที่เก็บหน่วยความจำหลัก แต่ยังคงใช้ได้กับปัญหาของเรามากที่สุด การออกแบบแฮชเทเบิลที่แนะนำในบทความนี้ช่วยให้เราสามารถรักษาคุณสมบัติพิเศษสองประการที่มีอยู่ในพจนานุกรม Redis ได้: ความสามารถในการแฮชที่เพิ่มขึ้นในระหว่างการเติบโตของพื้นที่เก็บข้อมูล ความสามารถในการสำรวจพจนานุกรมภายใต้การเปลี่ยนแปลงโดยใช้การดำเนินการสแกนแบบไร้สัญชาติ นอกจากคุณสมบัติทั้งสองนี้แล้ว Dash ยังมีประสิทธิภาพในการใช้ CPU และหน่วยความจำมากกว่า ด้วยการใช้ประโยชน์จากการออกแบบของ Dash เราจึงสามารถสร้างสรรค์สิ่งใหม่ๆ เพิ่มเติมด้วยคุณสมบัติต่อไปนี้:
เมื่อเราสร้างรากฐานสำหรับ Dragonfly และเราพอใจกับประสิทธิภาพของมันแล้ว เราก็เริ่มใช้ฟังก์ชัน Redis และ Memcached ต่อไป เราต้องใช้คำสั่ง Redis ประมาณ 185 คำสั่ง (เทียบเท่ากับ Redis 5.0 API) และคำสั่ง Memcached 13 คำสั่ง
และสุดท้าย
ภารกิจของเราคือการสร้างพื้นที่เก็บข้อมูลในหน่วยความจำที่ออกแบบมาอย่างดี รวดเร็วเป็นพิเศษ และคุ้มต้นทุนสำหรับปริมาณงานบนคลาวด์ที่ใช้ประโยชน์จากความก้าวหน้าของฮาร์ดแวร์ล่าสุด เราตั้งใจที่จะแก้ไขจุดบกพร่องของโซลูชันปัจจุบันในขณะเดียวกันก็รักษา API และข้อเสนอของผลิตภัณฑ์ไว้