Sebelum ini saya telah dapat merangkak dan mengindeks halaman web untuk enjin carian saya tanpa masalah, sehingga pangkalan data saya berkembang lebih daripada apa yang mampu disimpan oleh baris gilir mesej RabbitMQ. Jika mesej dalam baris gilir mesej melebihi saiz lalainya, RabbitMQ akan menimbulkan ralat dan panik, saya boleh menukar saiz lalai tetapi itu tidak akan berskala jika pangkalan data saya berkembang, jadi untuk pengguna merangkak halaman web tanpa perlu risau tentang broker mesej terhempas.
Saya telah melaksanakan fungsi untuk mencipta segmen dengan saiz segmen maksimum atau MSS daripada prinsip yang sama daripada TCP semasa mencipta segmen, segmen tersebut mengandungi pengepala 8 bait di mana setiap 4 bait daripada pengepala 8 bait ialah nombor urutan dan jumlah kiraan segmen dan bahagian badan yang lain ialah muatan pangkalan data tersegmen.
// MSS is number in bytes function createSegments( webpages: Array<Webpage>, // webpages queried from database MSS: number, ): Array<ArrayBufferLike> { const text_encoder = new TextEncoder(); const encoded_text = text_encoder.encode(JSON.stringify(webpages)); const data_length = encoded_text.byteLength; let currentIndex = 0; let segmentCount = Math.trunc(data_length / MSS) + 1; // + 1 to store the remainder let segments: Array<ArrayBufferLike> = []; let pointerPosition = MSS; for (let i = 0; i < segmentCount; i++) { let currentDataLength = Math.abs(currentIndex - data_length); let slicedArray = encoded_text.slice(currentIndex, pointerPosition); currentIndex += slicedArray.byteLength; // Add to offset MSS to point to the next segment in the array // manipulate pointerPosition to adjust to lower values using Math.min() // Is current data length enough to fit MSS? // if so add from current position + MSS // else get remaining of the currentDataLength pointerPosition += Math.min(MSS, currentDataLength); const payload = new Uint8Array(slicedArray.length); payload.set(slicedArray); segments.push(newSegment(i, segmentCount, Buffer.from(payload))); } return segments; } function newSegment( sequenceNum: number, segmentCount: number, payload: Buffer, ): ArrayBufferLike { // 4 bytes for sequenceNum 4 bytes for totalSegmentsCount const sequenceNumBuffer = convertIntToBuffer(sequenceNum); const segmentCountBuffer = convertIntToBuffer(segmentCount); const headerBuffer = new ArrayBuffer(8); const header = new Uint8Array(headerBuffer); header.set(Buffer.concat([sequenceNumBuffer, segmentCountBuffer])); return Buffer.concat([header, payload]); } function convertIntToBuffer(int: number): Buffer { const bytes = Buffer.alloc(4); bytes.writeIntLE(int, 0, 4); console.log(bytes); return bytes; }
Kaedah mencipta segmen kecil set data yang besar ini akan membantu menskalakan pertanyaan pangkalan data walaupun pangkalan data berkembang.
Sekarang bagaimanakah enjin carian menghuraikan penimbal dan mengubah setiap segmen menjadi tatasusunan halaman web?
Ekstrak dahulu pengepala segmen, kerana pengepala itu mengandungi 2 sifat iaitu Nombor urutan dan Jumlah Segmen,
func GetSegmentHeader(buf []byte) (*SegmentHeader, error) { byteReader := bytes.NewBuffer(buf) headerOffsets := []int{0, 4} newSegmentHeader := SegmentHeader{} for i := range headerOffsets { buffer := make([]byte, 4) _, err := byteReader.Read(buffer) if err != nil { return &SegmentHeader{}, err } value := binary.LittleEndian.Uint32(buffer) // this feels disgusting but i dont feel like bothering with this if i == 0 { newSegmentHeader.SequenceNum = value continue } newSegmentHeader.TotalSegments = value } return &newSegmentHeader, nil } func GetSegmentPayload(buf []byte) ([]byte, error) { headerOffset := 8 byteReader := bytes.NewBuffer(buf[headerOffset:]) return byteReader.Bytes(), nil }
Nombor jujukan akan digunakan untuk penghantaran semula/pemgantian segmen, jadi jika nombor jujukan yang dijangkakan tidak seperti yang diterima, maka baris gilir semula setiap segmen bermula dari segmen semasa.
// for retransmission/requeuing if segmentHeader.SequenceNum != expectedSequenceNum { ch.Nack(data.DeliveryTag, true, true) log.Printf("Expected Sequence number %d, got %d\n", expectedSequenceNum, segmentHeader.SequenceNum) continue }
Jumlah segmen akan digunakan untuk keluar daripada mendengar pengeluar (perkhidmatan pangkalan data) jika jumlah bilangan segmen yang diterima oleh enjin carian adalah sama dengan panjang jumlah segmen yang akan dihantar oleh perkhidmatan pangkalan data kemudian pecahkan dan huraikan penimbal segmen agregat, jika tidak teruskan mendengar dan tambahkan penimbal muatan segmen pada penimbal halaman web untuk menahan bait daripada semua segmen masuk.
segmentCounter++ fmt.Printf("Total Segments : %d\n", segmentHeader.TotalSegments) fmt.Printf("current segments : %d\n", segmentCounter) expectedSequenceNum++ ch.Ack(data.DeliveryTag, false) webpageBytes = append(webpageBytes, segmentPayload...) fmt.Printf("Byte Length: %d\n", len(webpageBytes)) if segmentCounter == segmentHeader.TotalSegments { log.Printf("Got all segments from Database %d", segmentCounter) break }
Saya menggunakan vim btw
Terima kasih kerana datang ke ceramah ted saya, saya akan melaksanakan lebih banyak ciri dan pembetulan untuk zensearch.
Atas ialah kandungan terperinci Menskalakan keupayaan Zensearch untuk menanyakan keseluruhan pangkalan data. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!