การใช้ที่เก็บ git เป็นแบ็กเอนด์ฐานข้อมูล


119

ฉันกำลังทำโครงการที่เกี่ยวข้องกับฐานข้อมูลเอกสารที่มีโครงสร้าง ฉันมีต้นไม้ของหมวดหมู่ (~ 1,000 หมวดหมู่มากถึง ~ 50 หมวดหมู่ในแต่ละระดับ) แต่ละหมวดหมู่มีเอกสารที่มีโครงสร้างหลายพันรายการ (ไม่เกิน 10,000) เอกสารแต่ละฉบับมีข้อมูลหลายกิโลไบต์ในรูปแบบโครงสร้างบางรูปแบบ (ฉันต้องการ YAML แต่อาจเป็น JSON หรือ XML ก็ได้เช่นกัน)

ผู้ใช้ระบบนี้ดำเนินการหลายประเภท:

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

แน่นอนวิธีแก้ปัญหาแบบดั้งเดิมจะใช้ฐานข้อมูลเอกสารบางประเภท (เช่น CouchDB หรือ Mongo) สำหรับปัญหานี้อย่างไรก็ตามการควบคุมเวอร์ชัน (ประวัติ) นี้ล่อลวงให้ฉันเกิดความคิดที่บ้าคลั่ง - ทำไมฉันไม่ควรใช้ gitเก็บเป็น a แบ็กเอนด์ฐานข้อมูลสำหรับแอปพลิเคชันนี้หรือไม่

ในแวบแรกมันสามารถแก้ไขได้ดังนี้:

  • หมวดหมู่ = ไดเร็กทอรีเอกสาร = ไฟล์
  • รับเอกสารโดย ID => เปลี่ยนไดเร็กทอรี + อ่านไฟล์ในสำเนาที่ใช้งานได้
  • การแก้ไขเอกสารด้วยการแก้ไขความคิดเห็น => การกระทำโดยผู้ใช้ต่างๆ
  • history => บันทึก git ปกติและการดึงข้อมูลธุรกรรมที่เก่ากว่า
  • การค้นหา => นั่นเป็นส่วนที่ยากกว่าเล็กน้อยฉันเดาว่าจะต้องมีการส่งออกหมวดหมู่ไปยังฐานข้อมูลเชิงสัมพันธ์เป็นระยะพร้อมการจัดทำดัชนีคอลัมน์ที่เราอนุญาตให้ค้นหาได้

มีข้อผิดพลาดทั่วไปอื่น ๆ ในโซลูชันนี้หรือไม่? มีใครลองใช้แบ็กเอนด์ดังกล่าวแล้ว (เช่นสำหรับเฟรมเวิร์กยอดนิยม - RoR, node.js, Django, CakePHP) หรือไม่? โซลูชันนี้มีผลกระทบที่เป็นไปได้ต่อประสิทธิภาพหรือความน่าเชื่อถือหรือไม่กล่าวคือได้รับการพิสูจน์แล้วว่าคอมไพล์จะช้ากว่าโซลูชันฐานข้อมูลแบบเดิมมากหรืออาจมีข้อผิดพลาดเกี่ยวกับความสามารถในการปรับขนาด / ความน่าเชื่อถือ ฉันคิดว่าคลัสเตอร์ของเซิร์ฟเวอร์ดังกล่าวที่ผลัก / ดึงที่เก็บของกันและกันควรมีความแข็งแกร่งและเชื่อถือได้พอสมควร

โดยพื้นฐานแล้วบอกฉันว่าโซลูชันนี้ใช้ได้ผลหรือไม่และทำไมจึงทำได้หรือไม่ทำ


คำตอบ:


58

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

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

  • แนวทาง "Blunt": ผู้ใช้ 1 คน = 1 สถานะ = 1 สำเนาที่ใช้งานได้เต็มรูปแบบของที่เก็บที่เซิร์ฟเวอร์เก็บรักษาไว้สำหรับผู้ใช้ แม้ว่าเราจะพูดถึงฐานข้อมูลเอกสารที่ค่อนข้างเล็ก (เช่น 100s MiBs) ที่มีผู้ใช้ ~ 100K แต่การรักษาโคลนที่เก็บข้อมูลแบบเต็มสำหรับพวกเขาทั้งหมดทำให้การใช้งานแผ่นดิสก์ทำงานผ่านหลังคา (เช่นผู้ใช้ 100K คูณ 100MiB ~ 10 TiB) . สิ่งที่แย่ไปกว่านั้นคือการโคลนที่เก็บ 100 MiB ในแต่ละครั้งจะใช้เวลาหลายวินาทีแม้ว่าจะทำในรูปแบบที่มีประสิทธิภาพพอสมควร (กล่าวคือไม่ใช้โดย git และการแกะ - บรรจุหีบห่อใหม่) ซึ่ง IMO ไม่เป็นที่ยอมรับ และที่แย่ไปกว่านั้นคือทุกการแก้ไขที่เราใช้กับโครงสร้างหลักควรถูกดึงไปยังที่เก็บของผู้ใช้ทุกคนซึ่งก็คือ (1) ทรัพยากรหมู (2) อาจนำไปสู่ความขัดแย้งในการแก้ไขที่ไม่ได้รับการแก้ไขในกรณีทั่วไป

    โดยทั่วไปแล้วมันอาจจะแย่พอ ๆ กับ O (จำนวนการแก้ไข×ข้อมูล×จำนวนผู้ใช้) ในแง่ของการใช้งานดิสก์และการใช้ดิสก์ดังกล่าวโดยอัตโนมัติหมายถึงการใช้งาน CPU ที่ค่อนข้างสูง

  • แนวทาง "เฉพาะผู้ใช้ที่ใช้งานอยู่": รักษาสำเนาที่ใช้งานได้สำหรับผู้ใช้ที่ใช้งานอยู่เท่านั้น วิธีนี้โดยทั่วไปคุณจะไม่จัดเก็บแบบเต็ม repo-clone-per-user แต่:

    • เมื่อผู้ใช้เข้าสู่ระบบคุณจะโคลนที่เก็บ ใช้เวลาหลายวินาทีและพื้นที่ดิสก์ ~ 100 MiB ต่อผู้ใช้ที่ใช้งานอยู่
    • ในขณะที่ผู้ใช้ทำงานบนไซต์ต่อไปเขาจะทำงานกับสำเนาที่ใช้งานได้
    • เมื่อผู้ใช้ออกจากระบบโคลนที่เก็บของเขาจะถูกคัดลอกกลับไปยังที่เก็บหลักเป็นสาขาดังนั้นจึงจัดเก็บเฉพาะ "การเปลี่ยนแปลงที่ไม่ได้ใช้" เท่านั้นหากมีซึ่งค่อนข้างประหยัดพื้นที่

    ดังนั้นการใช้ดิสก์ในกรณีนี้จึงมีค่าสูงสุดที่ O (จำนวนการแก้ไข×ข้อมูล×จำนวนผู้ใช้ที่ใช้งานอยู่) ซึ่งโดยปกติจะน้อยกว่าจำนวนผู้ใช้ทั้งหมด ~ 100..1000 เท่า แต่ทำให้การเข้า / ออกมีความซับซ้อนและช้าลง เนื่องจากเกี่ยวข้องกับการโคลนสาขาต่อผู้ใช้ในทุกการเข้าสู่ระบบและดึงการเปลี่ยนแปลงเหล่านี้กลับมาเมื่อออกจากระบบหรือหมดอายุเซสชัน (ซึ่งควรทำธุรกรรม => เพิ่มความซับซ้อนอีกชั้นหนึ่ง) ในจำนวนที่แน่นอนมันลดการใช้ดิสก์ 10 TiB ลงเหลือ 10..100 GiB ในกรณีของฉันซึ่งอาจเป็นที่ยอมรับได้ แต่อีกครั้งตอนนี้เรากำลังพูดถึงฐานข้อมูลที่ค่อนข้างเล็กถึง 100 MiB

  • วิธีการ "ชำระเงินแบบกระจัดกระจาย": การ "ชำระเงินแบบกระจัดกระจาย" แทนการโคลน repo เต็มรูปแบบต่อผู้ใช้ที่ใช้งานอยู่ไม่ได้ช่วยอะไรมากนัก อาจช่วยประหยัดการใช้พื้นที่ดิสก์ได้ถึง 10 เท่า แต่ต้องเสียค่าใช้จ่ายในการโหลด CPU / ดิสก์ที่สูงขึ้นมากในการดำเนินการที่เกี่ยวข้องกับประวัติซึ่งเป็นการทำลายวัตถุประสงค์

  • แนวทาง "กลุ่มคนงาน": แทนที่จะทำโคลนเต็มรูปแบบทุกครั้งสำหรับคนที่กระตือรือร้นเราอาจเก็บโคลน "คนงาน" ไว้จำนวนหนึ่งพร้อมใช้งาน ด้วยวิธีนี้ทุกครั้งที่ผู้ใช้เข้าสู่ระบบเขาจะครอบครอง "คนงาน" หนึ่งคนดึงสาขาของเขาจาก repo หลักไปที่นั่นและเมื่อเขาออกจากระบบเขาก็ปลดปล่อย "คนงาน" ซึ่งจะทำการฮาร์ดรีเซ็ตคอมไพล์อย่างชาญฉลาดให้กลายเป็นอีกครั้ง repo clone หลักพร้อมใช้งานโดยผู้ใช้รายอื่นที่เข้าสู่ระบบไม่ช่วยเรื่องการใช้งานดิสก์มากนัก (ยังค่อนข้างสูง - เฉพาะโคลนเต็มต่อผู้ใช้ที่ใช้งานอยู่) แต่อย่างน้อยก็ทำให้การเข้า / ออกเร็วขึ้นเนื่องจากมีค่าใช้จ่าย ความซับซ้อนมากยิ่งขึ้น

ที่กล่าวว่าโปรดทราบว่าฉันตั้งใจคำนวณจำนวนฐานข้อมูลที่ค่อนข้างเล็กและฐานผู้ใช้: ผู้ใช้ 100K ผู้ใช้ที่ใช้งานอยู่ 1K ฐานข้อมูลทั้งหมด 100 MiBs + ประวัติการแก้ไขสำเนาการทำงาน 10 MiB หากคุณดูโครงการจัดหาฝูงชนที่โดดเด่นกว่านั้นมีจำนวนที่สูงกว่ามากที่นั่น:

│              │ Users │ Active users │ DB+edits │ DB only │
├──────────────┼───────┼──────────────┼──────────┼─────────┤
│ MusicBrainz  │  1.2M │     1K/week  │   30 GiB │  20 GiB │
│ en.wikipedia │ 21.5M │   133K/month │    3 TiB │  44 GiB │
│ OSM          │  1.7M │    21K/month │  726 GiB │ 480 GiB │

เห็นได้ชัดว่าสำหรับข้อมูล / กิจกรรมจำนวนดังกล่าวแนวทางนี้จะไม่สามารถยอมรับได้อย่างสิ้นเชิง

โดยทั่วไปแล้วจะใช้งานได้หากสามารถใช้เว็บเบราว์เซอร์เป็นไคลเอนต์ "แบบหนา" เช่นการออกการดำเนินการคอมไพล์และจัดเก็บเช็คเอาต์แบบเต็มในฝั่งไคลเอ็นต์ไม่ใช่ในฝั่งเซิร์ฟเวอร์

นอกจากนี้ยังมีจุดอื่น ๆ ที่ฉันพลาดไป แต่ก็ไม่ได้แย่ขนาดนั้นเมื่อเทียบกับข้อแรก:

  • รูปแบบของการมีสถานะการแก้ไขของผู้ใช้ที่ "หนา" เป็นที่ถกเถียงกันในแง่ของ ORM ปกติเช่น ActiveRecord, Hibernate, DataMapper, Tower เป็นต้น
  • เท่าที่ฉันค้นหาไม่มี codebase ฟรีที่มีอยู่เป็นศูนย์สำหรับการทำแนวทางนั้นเพื่อคอมไพล์จากเฟรมเวิร์กยอดนิยม
  • มีบริการอย่างน้อยหนึ่งบริการที่สามารถจัดการได้อย่างมีประสิทธิภาพนั่นคือgithub - แต่อนิจจา codebase ของพวกเขาเป็นแบบปิดและฉันสงสัยอย่างยิ่งว่าพวกเขาไม่ได้ใช้เซิร์ฟเวอร์ git ปกติ / เทคนิคการจัดเก็บ repo ภายในกล่าวคือพวกเขาใช้โดยทั่วไป คอมไพล์ "ข้อมูลขนาดใหญ่" ทางเลือก

ดังนั้นบรรทัดล่าง : เป็นไปได้ แต่สำหรับการใช้งานปัจจุบันส่วนใหญ่จะไม่อยู่ใกล้กับโซลูชันที่ดีที่สุด การปรับใช้การแก้ไขเอกสารประวัติเป็น SQL ของคุณเองหรือพยายามใช้ฐานข้อมูลเอกสารที่มีอยู่อาจเป็นทางเลือกที่ดีกว่า


16
อาจจะสายไปหน่อย แต่ฉันมีข้อกำหนดที่คล้ายกันกับสิ่งนี้และไปตามเส้นทาง git-route หลังจากขุดคุ้ยกับ git ภายในแล้วฉันก็พบวิธีที่จะทำให้มันใช้งานได้ แนวคิดคือการทำงานกับที่เก็บเปล่า มีข้อเสียอยู่บ้าง แต่ฉันคิดว่ามันใช้งานได้ ฉันเขียนทุกอย่างในโพสต์ที่คุณอาจต้องการตรวจสอบ (ถ้ามีอะไรเพื่อประโยชน์ของผลประโยชน์): kenneth-truyers.net/2016/10/13/git-nosql-database
Kenneth

อีกเหตุผลหนึ่งที่ฉันไม่ทำเช่นนี้คือความสามารถในการสืบค้น ที่เก็บเอกสารมักจัดทำดัชนีเอกสารทำให้ง่ายต่อการค้นหาภายใน สิ่งนี้จะไม่ตรงไปตรงมากับคอมไพล์
FrankyHollywood

12

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

ถ้าคุณตัดสินใจที่จะใช้ Git แบ็กเอนด์ต่อไปโดยพื้นฐานแล้วมันจะใช้ได้กับความต้องการของคุณหากคุณใช้งานตามที่อธิบายไว้ แต่:

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

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


11

มูลค่า 2 เพนนีของฉัน ค่อนข้างโหยหา แต่ ...... ฉันมีข้อกำหนดที่คล้ายกันในโครงการบ่มเพาะของฉัน คล้ายกับของคุณข้อกำหนดสำคัญของฉันที่ฐานข้อมูลเอกสาร (xml ในกรณีของฉัน) พร้อมการกำหนดเวอร์ชันเอกสาร สำหรับระบบผู้ใช้หลายคนที่มีกรณีการใช้งานร่วมกันจำนวนมาก ความชอบของฉันคือการใช้โซลูชันโอเพนซอร์ซที่มีอยู่ซึ่งรองรับข้อกำหนดหลักส่วนใหญ่

เพื่อลดการไล่ล่าฉันไม่พบผลิตภัณฑ์ใด ๆ ที่ให้ทั้งสองอย่างในแบบที่ปรับขนาดได้เพียงพอ (จำนวนผู้ใช้ปริมาณการใช้งานพื้นที่จัดเก็บข้อมูลและทรัพยากรการประมวลผล) ฉันมีอคติต่อคอมไพล์สำหรับความสามารถทั้งหมดที่มีแนวโน้มและ (เป็นไปได้) วิธีแก้ปัญหาที่เราสามารถสร้างขึ้นมาได้ เมื่อฉันเล่นกับตัวเลือก git มากขึ้นการเปลี่ยนจากมุมมองของผู้ใช้คนเดียวไปสู่มุมมองของผู้ใช้หลาย (มิลลิแอมป์) กลายเป็นความท้าทายที่ชัดเจน น่าเสียดายที่ฉันไม่ได้ทำการวิเคราะห์ประสิทธิภาพที่สำคัญเหมือนที่คุณทำ (.. ขี้เกียจ / เลิกเร็ว .... สำหรับรุ่น 2 มนต์) พลังให้คุณ!. อย่างไรก็ตามความคิดที่เอนเอียงของฉันได้เปลี่ยนไปเป็นทางเลือกถัดไป (ยังคงเอนเอียง): การรวมเครื่องมือที่ดีที่สุดในทรงกลมฐานข้อมูลและการควบคุมเวอร์ชันที่แยกจากกัน

ในขณะที่ยังดำเนินการอยู่ (... และละเลยเล็กน้อย) เวอร์ชันที่ปรับเปลี่ยนเป็นเพียงสิ่งนี้

  • ที่ส่วนหน้า: (userfacing) ใช้ฐานข้อมูลสำหรับหน่วยเก็บข้อมูลระดับที่ 1 (เชื่อมต่อกับแอปพลิเคชันผู้ใช้)
  • บนแบ็กเอนด์ใช้ระบบควบคุมเวอร์ชัน (VCS) (เช่น git) เพื่อทำการกำหนดเวอร์ชันของอ็อบเจ็กต์ข้อมูลในฐานข้อมูล

โดยพื้นฐานแล้วมันจะเป็นการเพิ่มปลั๊กอินควบคุมเวอร์ชันลงในฐานข้อมูลด้วยกาวการรวมบางอย่างซึ่งคุณอาจต้องพัฒนา แต่อาจจะง่ายกว่ามาก

วิธีการทำงาน (ควรจะ) คือการแลกเปลี่ยนข้อมูลอินเทอร์เฟซหลายผู้ใช้หลักผ่านฐานข้อมูล DBMS จะจัดการกับปัญหาที่สนุกและซับซ้อนทั้งหมดเช่นผู้ใช้หลายคน, e พร้อมกัน, การดำเนินการของอะตอมเป็นต้นในแบ็กเอนด์ VCS จะดำเนินการควบคุมเวอร์ชันบนอ็อบเจ็กต์ข้อมูลชุดเดียว (ไม่มีปัญหาการเกิดพร้อมกันหรือผู้ใช้หลายคน) สำหรับแต่ละธุรกรรมที่มีประสิทธิภาพบนฐานข้อมูลการควบคุมเวอร์ชันจะดำเนินการเฉพาะกับเรกคอร์ดข้อมูลที่จะมีการเปลี่ยนแปลงอย่างมีประสิทธิภาพเท่านั้น

สำหรับกาวเชื่อมจะอยู่ในรูปแบบของฟังก์ชันการทำงานร่วมกันระหว่างฐานข้อมูลและ VCS ในแง่ของการออกแบบแนวทางง่ายๆคืออินเทอร์เฟซที่ขับเคลื่อนด้วยเหตุการณ์โดยการอัปเดตข้อมูลจากฐานข้อมูลจะเรียกใช้ขั้นตอนการควบคุมเวอร์ชัน (คำใบ้: สมมติว่า Mysql ใช้ทริกเกอร์และ sys_exec () blah blah ... ) ในแง่ของความซับซ้อนในการใช้งานจะมีตั้งแต่ขั้นตอนที่เรียบง่ายและมีประสิทธิภาพ (เช่นการเขียนสคริปต์) ไปจนถึงความซับซ้อนและยอดเยี่ยม (อินเทอร์เฟซตัวเชื่อมต่อที่ตั้งโปรแกรมไว้ ทั้งหมดขึ้นอยู่กับว่าคุณต้องการไปกับมันบ้าแค่ไหนและคุณยินดีจ่ายเงินทุนเท่าไร ฉันคิดว่าการเขียนสคริปต์อย่างง่ายควรทำเวทมนตร์ และในการเข้าถึงผลลัพธ์สุดท้ายเวอร์ชันข้อมูลต่างๆทางเลือกง่ายๆคือการเติมข้อมูลโคลนของฐานข้อมูล (โคลนของโครงสร้างฐานข้อมูลเพิ่มเติม) ด้วยข้อมูลที่อ้างอิงโดยแท็กเวอร์ชัน / id / แฮชใน VCS อีกครั้งบิตนี้จะเป็นงานแบบสอบถาม / แปล / แผนที่อย่างง่ายของอินเทอร์เฟซ

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

ค็อกเทลด้านบนนี่คือสิ่งที่ฉันกำลังชงอยู่

  • ใช้ Git สำหรับ VCS (ในตอนแรกถือว่า CVS เก่าที่ดีเนื่องจากมีการใช้เฉพาะชุดการเปลี่ยนแปลงหรือเดลต้าระหว่าง 2 เวอร์ชัน)
  • ใช้ mysql (เนื่องจากลักษณะของข้อมูลของฉันมีโครงสร้างสูง xml ที่มีสกีมา xml ที่เข้มงวด)
  • เล่นกับ MongoDB (เพื่อลองใช้ฐานข้อมูล NoSQl ซึ่งตรงกับโครงสร้างฐานข้อมูลดั้งเดิมที่ใช้ในคอมไพล์)

ข้อเท็จจริงที่น่าสนใจบางอย่าง - คอมไพล์ทำสิ่งที่ชัดเจนเพื่อเพิ่มประสิทธิภาพการจัดเก็บข้อมูลเช่นการบีบอัดและการจัดเก็บเฉพาะเดลต้าระหว่างการแก้ไขอ็อบเจ็กต์ - ใช่ git จะจัดเก็บเฉพาะการเปลี่ยนแปลงหรือเดลต้าระหว่างการแก้ไขอ็อบเจ็กต์ข้อมูลเท่านั้นที่สามารถใช้ได้ (รู้ เมื่อไรและอย่างไร) การอ้างอิง: packfiles ลึกเข้าไปในความกล้าของ Git ภายใน - การตรวจสอบการจัดเก็บอ็อบเจ็กต์ของ git (ระบบไฟล์ที่กำหนดแอดเดรสเนื้อหา) แสดงความคล้ายคลึงกัน (จากมุมมองของแนวคิด) ด้วยฐานข้อมูล noSQL เช่น mongoDB อีกครั้งด้วยค่าใช้จ่ายของเงินทุนอาจให้ความเป็นไปได้ที่น่าสนใจยิ่งขึ้นสำหรับการผสานรวม 2 และการปรับแต่งประสิทธิภาพ

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


4

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

เอกสารประกอบไปด้วยแนวคิดบางประการเกี่ยวกับประสิทธิภาพการแลกเปลี่ยน ฯลฯ


2

ดังที่คุณได้กล่าวไว้กรณีของผู้ใช้หลายคนนั้นค่อนข้างยากที่จะจัดการ ทางออกหนึ่งที่เป็นไปได้คือการใช้ไฟล์ดัชนี Git เฉพาะผู้ใช้ซึ่งส่งผลให้เกิด

  • ไม่จำเป็นต้องใช้สำเนาการทำงานแยกกัน (การใช้ดิสก์ถูก จำกัด ไว้ที่ไฟล์ที่เปลี่ยนแปลง)
  • ไม่จำเป็นต้องเตรียมงานที่ใช้เวลานาน (ต่อเซสชันของผู้ใช้)

เคล็ดลับคือการรวมGIT_INDEX_FILEตัวแปรสภาพแวดล้อมของ Git กับเครื่องมือเพื่อสร้างการคอมมิต Git ด้วยตนเอง:

โครงร่างโซลูชันดังต่อไปนี้ (แฮช SHA1 จริงที่ละเว้นจากคำสั่ง):

# Initialize the index
# N.B. Use the commit hash since refs might changed during the session.
$ GIT_INDEX_FILE=user_index_file git reset --hard <starting_commit_hash>

#
# Change data and save it to `changed_file`
#

# Save changed data to the Git object database. Returns a SHA1 hash to the blob.
$ cat changed_file | git hash-object -t blob -w --stdin
da39a3ee5e6b4b0d3255bfef95601890afd80709

# Add the changed file (using the object hash) to the user-specific index
# N.B. When adding new files, --add is required
$ GIT_INDEX_FILE=user_index_file git update-index --cacheinfo 100644 <changed_data_hash> path/to/the/changed_file

# Write the index to the object db. Returns a SHA1 hash to the tree object
$ GIT_INDEX_FILE=user_index_file git write-tree
8ea32f8432d9d4fa9f9b2b602ec7ee6c90aa2d53

# Create a commit from the tree. Returns a SHA1 hash to the commit object
# N.B. Parent commit should the same commit as in the first phase.
$ echo "User X updated their data" | git commit-tree <new_tree_hash> -p <starting_commit_hash>
3f8c225835e64314f5da40e6a568ff894886b952

# Create a ref to the new commit
git update-ref refs/heads/users/user_x_change_y <new_commit_hash>

ขึ้นอยู่กับข้อมูลของคุณคุณสามารถใช้งาน cron เพื่อรวมการอ้างอิงใหม่masterแต่การแก้ไขข้อขัดแย้งเป็นเนื้อหาที่ยากที่สุดที่นี่

ยินดีต้อนรับแนวคิดที่จะทำให้ง่ายขึ้น


โดยทั่วไปแล้วเป็นแนวทางที่นำไปสู่ที่ไหนเลยเว้นแต่คุณต้องการมีแนวคิดเกี่ยวกับธุรกรรมและ UI ที่ครบถ้วนสมบูรณ์สำหรับการแก้ไขข้อขัดแย้งด้วยตนเอง แนวคิดทั่วไปสำหรับความขัดแย้งคือการทำให้ผู้ใช้แก้ไขได้ทันทีเมื่อกระทำ (เช่น "ขออภัยมีคนอื่นแก้ไขเอกสารนั้นที่คุณกำลังแก้ไข -> โปรดดูการแก้ไขของเขาและการแก้ไขของคุณและรวมเข้าด้วยกัน") เมื่อคุณอนุญาตให้ผู้ใช้สองคนดำเนินการสำเร็จแล้วพบใน async cronjob ว่าสิ่งต่าง ๆ ไปทางทิศใต้โดยทั่วไปไม่มีใครสามารถแก้ไขปัญหาได้
GreyCat
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.