Rumah > pembangunan bahagian belakang > Golang > Menskalakan keupayaan Zensearch untuk menanyakan keseluruhan pangkalan data

Menskalakan keupayaan Zensearch untuk menanyakan keseluruhan pangkalan data

Linda Hamilton
Lepaskan: 2024-11-14 12:08:02
asal
390 orang telah melayarinya

Scaling Zensearch

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.

Mencipta Segmen

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;
}

Salin selepas log masuk

Menghuraikan segmen masuk

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?

Pembacaan daripada penampan segmen

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

}

Salin selepas log masuk

Mengendalikan penghantaran semula dan requeuing segmen

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
        }
Salin selepas log masuk

Menambahkan muatan segmen

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
        }
Salin selepas log masuk

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!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan