Artikel ini terutama mempelajari konten yang relevan dari cache LRU throughput dan thread-safe tinggi, sebagai berikut.
Beberapa tahun yang lalu, saya menerapkan cache LRU untuk menemukan ID untuk kata kunci. Struktur data sangat menarik karena throughput yang diperlukan cukup besar untuk menghilangkan masalah kinerja yang disebabkan oleh sejumlah besar locks dan kata kunci synchronized . Aplikasi diimplementasikan di Java.
Saya berpikir bahwa serangkaian alokasi referensi atom akan menjaga ketertiban LRU dan LRU di concurrenthashmap. Pada awalnya, saya membungkus nilainya ke dalam entri. Entri ini memiliki simpul dalam rantai LRU dari daftar double-linked. Ekor rantai mempertahankan entri yang baru -baru ini digunakan, dan simpul kepala menyimpan entri yang dapat dibersihkan ketika cache mencapai ukuran tertentu. Setiap node menunjuk ke entri yang digunakan untuk menemukan.
Saat Anda mencari nilai melalui kunci, cache pertama -tama perlu mencari peta untuk melihat apakah nilai ini ada. Jika tidak ada, itu akan tergantung pada loader untuk membaca nilai dari sumber data dengan cara yang dibaca dan menambahkannya di peta di "Tambahkan jika hilang". Tantangan untuk memastikan throughput tinggi adalah untuk secara efektif mempertahankan rantai LRU. Peta hash bersamaan ini tersegmentasi dan level utas berada pada level tertentu (Anda dapat menentukan tingkat konkurensi ketika Anda membangun peta) tidak akan mengalami terlalu banyak kompetisi utas. Tetapi tidak bisakah rantai LRU dibagi dengan cara yang sama? Untuk mengatasi masalah ini, saya memperkenalkan antrian tambahan untuk operasi kliring.
Ada enam metode dasar dalam cache. Untuk hit cache, pencarian mencakup dua operasi dasar: dapatkan dan tawarkan, dan untuk kehilangan kasar, ada empat metode dasar: dapatkan, muat, put, dan tawarkan. Dalam metode put, kita mungkin perlu melacak operasi yang jelas. Ketika cache menghantam, kami secara pasif melakukan beberapa kliring pada rantai LRU yang disebut operasi pemurnian.
Dapatkan: Entri pencarian di peta dengan kunci
Load: Load Nilai dari Sumber Data
Put: Buat entri dan peta ke kunci
Penawaran: Tambahkan simpul di bagian belakang daftar LRU yang mengacu pada entri yang baru diakses
Evict: Hapus node di kepala daftar dan entri terkait dari peta (setelah cache mencapai ukuran tertentu)
Pembersihan: Hapus node yang tidak digunakan dalam daftar LRU - kami menyebut node ini sebagai lubang, dan antrian pembersihan melacaknya
Operasi kliring dan operasi pemurnian keduanya merupakan batch besar data pemrosesan. Mari kita lihat detail dari setiap operasi.
Operasi GET bekerja sebagai berikut:
get (k) -> v Entry pencarian dengan kunci k jika cache hit, kami memiliki entri entri e penawaran e coba bersihkan beberapa lubang lagi nilai beban v untuk kunci k buat entri e < - (k, v) Coba Entri E end Value Return Nilai EV EV
Jika kunci ada, kami menyediakan simpul baru di ekor rantai LRU untuk menunjukkan bahwa ini adalah nilai yang baru digunakan. Eksekusi GET dan Penawaran bukanlah operasi atom (tidak ada kunci di sini), jadi kami tidak dapat mengatakan bahwa poin node yang ditawarkan ini ke entitas yang paling baru digunakan, tetapi jelas entitas yang paling baru digunakan yang diperoleh ketika kami dieksekusi secara bersamaan. Kami tidak memaksa dan menawarkan untuk melaksanakan pesanan antar utas, karena ini dapat membatasi throughput. Setelah menawarkan node, kami mencoba melakukan beberapa operasi untuk menghapus dan mengembalikan nilai. Mari kita lihat operasi penawaran dan pembersihan secara rinci di bawah ini.
Jika kerugian cache terjadi, kami akan memanggil loader untuk memuat nilai untuk kunci ini, membuat entitas baru dan memasukkannya ke dalam peta, dan operasi put adalah sebagai berikut:
put (e) -> e entri yang ada ex < - peta.putifabsent (EK, E) Jika absen menawarkan entri E; Jika ukuran mencapai penggusuran penggusur beberapa entri entri entri entri yang lain, kami memiliki entri entri entri yang ada ex end ex end
Seperti yang Anda lihat, mungkin ada kompetisi ketika dua atau lebih utas memasukkan entitas ke dalam peta, tetapi hanya satu keberhasilan yang diizinkan dan penawaran itu akan dipanggil. Setelah memberikan simpul di ekor rantai LRU, kita perlu memeriksa apakah cache telah mencapai ambang batasnya, yang merupakan pengidentifikasi yang kita gunakan untuk memulai operasi yang jelas batch. Dalam skenario aplikasi khusus ini, pengaturan ambang batas lebih kecil dari kapasitas. Operasi kliring terjadi dalam batch kecil daripada ketika setiap entitas ditambahkan. Beberapa utas dapat berpartisipasi dalam operasi kliring sampai kapasitas cache mencapai kapasitasnya. Penguncian mudah tetapi utas bisa aman. Membersihkan simpul kepala rantai LRU membutuhkan penghapusan, yang membutuhkan operasi atom yang cermat untuk menghindari operasi penghapusan multi-utara di peta.
Operasi penawaran ini sangat menarik. Itu selalu mencoba untuk membuat node tetapi tidak mencoba menghapus dan menghapus node yang tidak lagi digunakan di LRU segera.
Penawaran (e) Jika simpul ekor tidak mengacu pada entri e Tetapkan simpul saat ini C <-en membuat simpul baru n (e), node baru referer ke entri e jika atom perbandingan dan set node en, harapkan c, tetapkan n tambahkan simpul n ke ekor daftar lru jika node c tidak null set ce ke null, c sekarang memiliki hole add node ke cleanup quue
Pertama, ia akan memeriksa bahwa simpul di ekor rantai tidak menunjuk ke entitas yang telah diakses, yang tidak berbeda kecuali semua utas sering mengakses pasangan nilai kunci yang sama. Ini akan membuat simpul baru di ekor rantai. Ketika entitas ini berbeda, sebelum memberikan simpul baru, ia mencoba membuat perbandingan dan mengatur operasi untuk entitas, yang akan mencegah beberapa utas melakukan hal yang sama.
Utas yang berhasil mengalokasikan node menyediakan node baru di ujung rantai LRU. Operasi ini sama dengan temuan di concurrentlinkedqueue. Algoritma ketergantungan dijelaskan dalam artikel berikut. Algoritma antrian bersamaan yang sederhana, cepat, dan praktis memblokir dan memblokir. Utas kemudian akan memeriksa apakah entitas terkait dengan node lain sebelumnya. Jika demikian, simpul lama tidak akan segera dihapus, tetapi akan ditandai sebagai lubang (referensi ke entitasnya akan diatur untuk kosong)
Di atas adalah semua penjelasan terperinci dari artikel ini tentang cache LRU throughput tinggi dan yang aman, dan saya harap ini akan membantu semua orang. Teman yang tertarik dapat terus merujuk ke topik terkait lainnya di situs ini. Jika ada kekurangan, silakan tinggalkan pesan untuk menunjukkannya. Terima kasih teman atas dukungan Anda untuk situs ini!