Pertama beberapa konteks, solusi di akhir :
Dari perintah SCAN> Jaminan penghentian
Algoritme SCAN dijamin untuk berhenti hanya jika ukuran koleksi yang diulang tetap dibatasi pada ukuran maksimum yang diberikan, jika tidak, mengulangi koleksi yang selalu bertambah dapat mengakibatkan SCAN tidak pernah mengakhiri iterasi penuh.
Ini mudah dilihat secara intuitif:jika koleksi bertambah, ada lebih banyak dan lebih banyak pekerjaan yang harus dilakukan untuk mengunjungi semua elemen yang mungkin, dan kemampuan untuk menghentikan iterasi bergantung pada jumlah panggilan ke SCAN dan nilai opsi COUNT dibandingkan dengan rate di yang koleksinya bertambah.
Tetapi dalam opsi COUNT dikatakan:
Penting:tidak perlu menggunakan nilai COUNT yang sama untuk setiap iterasi. Penelepon bebas mengubah hitungan dari satu iterasi ke iterasi lainnya sesuai kebutuhan, selama kursor yang dilewatkan pada panggilan berikutnya adalah yang diperoleh pada panggilan sebelumnya ke perintah.
Penting untuk diingat, dari jaminan Pindai:
- Elemen tertentu dapat dikembalikan beberapa kali. Terserah aplikasi untuk menangani kasus elemen duplikat, misalnya hanya menggunakan elemen yang dikembalikan untuk melakukan operasi yang aman ketika diterapkan kembali beberapa kali.
- Elemen yang tidak selalu ada dalam koleksi selama iterasi penuh, dapat dikembalikan atau tidak:tidak ditentukan.
Kunci solusi ada di kursor itu sendiri. Lihat Memahami kursor SCAN Redis. Adalah kemungkinan untuk menyimpulkan persentase kemajuan pemindaian Anda karena kursor benar-benar merupakan bit-dibalik indeks ke ukuran tabel.
Menggunakan DBSIZE
atau INFO keyspace
perintah Anda bisa mendapatkan berapa banyak kunci yang Anda miliki setiap saat:
> DBSIZE
(integer) 200032
> info keyspace
# Keyspace
db0:keys=200032,expires=0,avg_ttl=0
Sumber informasi lain adalah DEBUG htstats index
yang tidak berdokumen , hanya untuk merasakan:
> DEBUG htstats 0
[Dictionary HT]
Hash table 0 stats (main hash table):
table size: 262144
number of elements: 200032
different slots: 139805
max chain length: 8
avg chain length (counted): 1.43
avg chain length (computed): 1.43
Chain length distribution:
0: 122339 (46.67%)
1: 93163 (35.54%)
2: 35502 (13.54%)
3: 9071 (3.46%)
4: 1754 (0.67%)
5: 264 (0.10%)
6: 43 (0.02%)
7: 6 (0.00%)
8: 2 (0.00%)
[Expires HT]
No stats available for empty dictionaries
Ukuran tabel adalah pangkat 2 mengikuti jumlah kunci Anda:Kunci:200032 => Ukuran tabel:262144
Solusinya:
Kami akan menghitung COUNT
yang diinginkan argumen untuk setiap pemindaian.
Katakanlah Anda akan memanggil SCAN dengan frekuensi (F
dalam Hz) dari 10 Hz (setiap 100 ms) dan Anda ingin menyelesaikannya dalam 5 detik (T
dalam s). Jadi Anda ingin ini selesai di N = F*T
panggilan, N = 50
dalam contoh ini.
Sebelum pemindaian pertama Anda, Anda tahu kemajuan Anda saat ini adalah 0, jadi persentase yang tersisa adalah RP = 1
(100%).
Sebelum setiap SCAN
panggilan (atau setiap jumlah panggilan yang ingin Anda sesuaikan COUNT Anda jika Anda ingin menghemat Waktu Pulang Pergi (RTT) dari DBSIZE
panggilan), Anda memanggil DBSIZE
untuk mendapatkan jumlah kunci K
.
Anda akan menggunakan COUNT = K*RP/N
Untuk panggilan pertama, ini COUNT = 200032*1/50 = 4000
.
Untuk panggilan lainnya, Anda perlu menghitung RP = 1 - ReversedCursor/NextPowerOfTwo(K)
.
Misalnya, Anda sudah melakukan 20 panggilan, jadi sekarang N = 30
(jumlah panggilan yang tersisa). Anda menelepon DBSIZE
dan dapatkan K = 281569
. Ini berarti NextPowerOfTwo(K) = 524288
, ini adalah 2^19.
Kursor Anda berikutnya adalah 14509 dalam desimal =000011100010101101
dalam biner. Karena ukuran tabel adalah 2^19, kami merepresentasikannya dengan 18 bit.
Anda membalikkan bit dan mendapatkan 101101010001110000
dalam biner =185456 dalam desimal. Ini berarti kita telah membahas 185456 dari 524288. Dan:
RP = 1 - ReversedCursor/NextPowerOfTwo(K) = 1 - 185456 / 524288 = 0.65 or 65%
Jadi Anda harus menyesuaikan:
COUNT = K*RP/N = 281569 * 0.65 / 30 = 6100
Jadi di SCAN
Anda berikutnya panggilan Anda menggunakan 6100
. Masuk akal itu meningkat karena:
- Jumlah kunci telah meningkat dari 200032 menjadi 281569.
- Meskipun kami hanya memiliki 60% dari perkiraan awal panggilan yang tersisa, kemajuannya terlambat karena 65% dari ruang kunci menunggu untuk dipindai.
Semua ini dengan asumsi Anda mendapatkan semua kunci. Jika Anda mencocokkan pola , Anda perlu menggunakan masa lalu untuk memperkirakan jumlah kunci yang tersisa untuk ditemukan. Kami menambahkan sebagai faktor PM
(persen kecocokan) ke COUNT
perhitungan.
COUNT = PM * K*RP/N
PM = keysFound / ( K * ReversedCursor/NextPowerOfTwo(K))
Jika setelah 20 panggilan, Anda hanya menemukan keysFound = 2000
kunci, lalu:
PM = 2000 / ( 281569 * 185456 / 524288) = 0.02
Ini berarti hanya 2% dari kunci yang cocok dengan pola kita sejauh ini, jadi
COUNT = PM * K*RP/N = 0.02 * 6100 = 122
Algoritme ini mungkin dapat ditingkatkan, tetapi Anda mengerti.
Pastikan untuk menjalankan beberapa tolok ukur pada COUNT
nomor yang akan Anda gunakan untuk memulai, untuk mengukur berapa milidetik SCAN
Anda menerima, karena Anda mungkin perlu memoderasi ekspektasi Anda tentang berapa banyak panggilan yang Anda butuhkan (N
) untuk melakukan ini dalam waktu yang wajar tanpa memblokir server, dan sesuaikan F
. Anda dan T
sesuai.