อัลกอริทึมสำหรับรายการที่หมดอายุในการจัดเก็บคีย์ - ค่าคืออะไร?


10

ฉันคิดว่าการจัดเก็บคีย์ - ค่าปัจจุบันใช้ "วันหมดอายุ" สำหรับรายการอย่างไร ขณะนี้ฉันมี 2 ตัวแปรสำหรับสิ่งนั้นในใจ:

  1. พวกเขาไม่ได้ทำอะไร (เก็บข้อมูลที่หมดอายุ) และจะตรวจสอบเมื่อคุณทำเช่น GET โดยคีย์บางอย่าง ปัญหาที่นี่คือถ้าคุณถูก จำกัด ในหน่วยความจำรายการที่หมดอายุจะไม่ถูกลบ
  2. พวกเขาเก็บโครงสร้างข้อมูลเพิ่มเติมเพื่อให้ได้ "เร็วที่สุดที่จะหมดอายุ" ฉันเห็นมันสามารถทำได้กับบางสิ่งเช่นนี้

    storage_data = dict(key -> [value, expire_timestamp])
    expire_tree = SomeBinaryLikeTree(expire_timestamp -> [keys])
    

คำตอบ:


6

ปัญหาของการลบรายการที่หมดอายุในแคชนั้นเทียบเท่ากับการเก็บขยะอย่างมากลบความซับซ้อนทั้งหมดของการนับการอ้างอิง

คนที่ Nasza-Klasa ได้เสนอ O (1) อัลกอริทึมสำหรับ Memcache ดังนี้:

ดูเหมือนว่าหลายคนเชื่อว่าด้วยเหตุผลบางอย่างว่าการยกเลิกรายการที่หมดอายุนั้นไม่สามารถทำได้ใน O (1) หรือแม้กระทั่งว่าต้องมีการดำเนินการของโอเมก้า (N) การใช้ฮีปหรือโครงสร้างข้อมูลคิวลำดับความสำคัญอื่น ๆ สามารถให้ O (log N) ได้ชัด แต่แพตช์ด้านล่างมีเป้าหมายที่ O (1) นี่คือความสำเร็จโดยมีหนึ่งถังสำหรับแต่ละวินาทีและโดยการใส่แต่ละรายการในถังที่เหมาะสมโดยดูที่เวลาหมดอายุ จากนั้นในแต่ละวินาทีเราแค่ปล่อยองค์ประกอบจากที่เก็บข้อมูลถัดไป เห็นได้ชัดว่านี่เป็นเวลา O (1) ที่ถูกตัดจำหน่าย แต่อาจเกิดขึ้นได้ว่าคุณมีองค์ประกอบจำนวนมากที่หมดอายุในเวลาเดียวกันดังนั้นแพทช์มีข้อ จำกัด ที่แน่นอนสำหรับจำนวนของการดำเนินการที่คุณเต็มใจที่จะดำเนินการต่อหนึ่งคำขอ เพื่อให้การรวบรวมขยะทำงานได้ราบรื่นขึ้น

ดูข้อเสนอทั้งหมดที่มีรหัสที่แนบมา


ขอบคุณ ฉันยังคิดเกี่ยวกับการแก้ปัญหา "ถัง" เป็นวิธีหนึ่ง นอกจากนี้ยังไม่มีปัญหากับ "รายการที่มากเกินไปในถัง" เนื่องจากคุณสามารถไปกับอัลกอริทึม "นำถังที่คุณไม่ได้ใช้ครั้งสุดท้ายและกลับมาเมื่อเสร็จแล้ว"
Kostiantyn Rybnikov

@k_bx: นั่นเป็นเหตุผลที่พวกเขาเสนอรายการเชื่อมโยงสองครั้งเพื่อให้คุณสามารถกลับไปที่ถังก่อนหน้า
vartec

หากที่เก็บข้อมูลมีลักษณะคล้ายวินาทีคุณก็ไม่จำเป็นต้องมีรายการลิงก์เลย หากต้องการไปก่อนหน้านี้คุณเพียงกดปุ่มลด :) :)
Kostiantyn Rybnikov

@k_bx: ลดรหัสด้วยจำนวนเท่าไหร่ หนึ่งวินาที? จะเกิดอะไรขึ้นถ้าที่ฝากข้อมูลก่อนหน้านี้ที่ไม่สมบูรณ์หมดเวลาประมาณ 5 นาทีก่อน ลดลงทีละขั้น 1s 300 ครั้ง?
vartec

ในการเริ่มต้นเซิร์ฟเวอร์ครั้งแรกคุณเริ่มต้นตัวแปรชื่อ current_expire_bucket เป็นค่าบางค่า จากนั้นคุณเรียกใช้การล้างข้อมูลเริ่มต้นจาก current_expire_bucket สิ้นสุดวินาทีปัจจุบัน หลังจากการล้างข้อมูลสิ้นสุดคุณนอนหลับเป็นระยะเวลาสั้น ๆ หากเซิร์ฟเวอร์หยุดคุณจะต้องผ่าน "ถังหมดอายุ" อีกครั้งใช่ แต่ควรเกิดขึ้นเมื่อเซิร์ฟเวอร์หยุดเท่านั้น
Kostiantyn Rybnikov

7

ฉันถือว่าที่เก็บคีย์ - ค่านั้นใหญ่เกินไปที่จะวนซ้ำทุกคู่ kv เพื่อหาว่าอันไหนจะหมดอายุ ฉันยังสมมติว่าการเข้าถึงการอ่านแต่ละครั้งจะรีเฟรชเวลาประทับที่หมดอายุดังนั้นเฉพาะรายการที่ไม่ได้เข้าถึงในบางครั้งจะหมดอายุ

ความท้าทายคือการค้นหาระเบียนทั้งหมดที่สามารถหมดอายุได้อย่างมีประสิทธิภาพ (ทุกครั้งที่มีการล้างข้อมูล) แต่ยังรีเฟรชเวลาประทับบนการเข้าถึงการอ่านทุกครั้งได้อย่างมีประสิทธิภาพ (ดังนั้นเราต้องค้นหาคีย์ในโครงสร้างที่ใช้สำหรับการหมดอายุ)

ข้อเสนอของฉัน: กลุ่ม expiry_timestamps เป็นที่เก็บข้อมูล; ตัวอย่างเช่นหากรายการมีชีวิตอยู่เป็นเวลา 8 ชั่วโมงให้สร้างที่เก็บข้อมูลหนึ่งถังต่อชั่วโมง ถังเหล่านั้นจะถูกเก็บไว้ในรายการที่เชื่อมโยง; เมื่อหมดอายุเกิดขึ้นฝากข้อมูลแรกจะถูกลบและรายการจะลดลง จำนวนของที่เก็บข้อมูลคือช่วงอายุ / การล้างข้อมูล ที่ฝากข้อมูลแต่ละชุดประกอบด้วย hashSet ของคีย์ทั้งหมดที่ควรจะหมดอายุ การวนซ้ำของปุ่มทั้งหมดใน hashset นั้นมีประสิทธิภาพเพียงพอ

ในระหว่างการเข้าถึงการอ่านโปรแกรมจะตรวจสอบว่าที่ฝากข้อมูลรหัสใดอยู่ในปัจจุบันและที่ฝากข้อมูลที่อยู่ในขณะนี้ ในกรณีส่วนใหญ่เป็นที่เก็บข้อมูลเดียวกันดังนั้นจึงไม่จำเป็นต้องดำเนินการใด ๆ เพิ่มเติม มิฉะนั้นให้เอากุญแจออกจากที่เก็บข้อมูลอันเก่า (การลบออกจากชุดแฮชนั้นมีประสิทธิภาพ) และใส่ลงในที่ฝากข้อมูลใหม่

   +--------------+   +--------------+   +--------------+
-->+ Expiry 08:00 +-->+ Expiry 09:00 +-->+ Expiry 10:00 +
   | KeySet       |   | KeySet       |   | KeySet       |
   +--------------+   +--------------+   +--------------+
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.