Kedai Nilai Utama dengan Peta Kronik

1. Gambaran keseluruhan

Dalam tutorial ini, kita akan melihat bagaimana kita dapat menggunakan Peta Kronik untuk menyimpan pasangan nilai-kunci. Kami juga akan membuat contoh pendek untuk menunjukkan tingkah laku dan penggunaannya.

2. Apa itu Peta Kronik?

Setelah dokumentasi, "Peta Chronicle adalah penyimpanan nilai kunci yang sangat cepat, dalam memori, tanpa penyekat, yang dirancang untuk aplikasi latensi rendah, dan / atau multi-proses".

Ringkasnya, ia adalah kedai nilai kunci yang tidak banyak. Peta tidak memerlukan sejumlah besar RAM untuk berfungsi dengan baik. Ia boleh berkembang berdasarkan kapasiti cakera yang ada . Selanjutnya, ia menyokong replikasi data dalam penyediaan pelayan multi-master.

Sekarang mari kita lihat bagaimana kita dapat mengatur dan mengusahakannya.

3. Ketergantungan Maven

Untuk memulakan, kita perlu menambahkan ketergantungan peta kronik ke projek kita:

 net.openhft chronicle-map 3.17.2 

4. Jenis Peta Kronik

Kita dapat membuat peta dengan dua cara: baik sebagai peta dalam memori atau sebagai peta yang masih ada.

Mari lihat kedua-duanya secara terperinci.

4.1. Peta Dalam Memori

Peta Chronicle dalam-memori adalah kedai peta yang dibuat dalam memori fizikal pelayan. Ini bermaksud hanya boleh diakses dalam proses JVM di mana kedai peta dibuat .

Mari lihat contoh ringkas:

ChronicleMap inMemoryCountryMap = ChronicleMap .of(LongValue.class, CharSequence.class) .name("country-map") .entries(50) .averageValue("America") .create();

Demi kesederhanaan, kami membuat peta yang menyimpan 50 id negara dan namanya. Seperti yang dapat kita lihat dalam coretan kod, penciptaannya cukup mudah kecuali konfigurasi rata - rata Nilai () . Ini memberitahu peta untuk mengkonfigurasi jumlah purata bait yang diambil oleh nilai kemasukan peta.

Dengan kata lain, ketika membuat peta, Chronicle Map menentukan jumlah purata bait yang diambil oleh bentuk nilai bersiri. Ia melakukannya dengan membuat siri nilai purata yang diberikan menggunakan marshallers nilai yang dikonfigurasi. Ia kemudian akan memperuntukkan jumlah bait yang ditentukan untuk nilai setiap entri peta.

Satu perkara yang harus kita perhatikan ketika datang ke peta dalam memori adalah bahawa data dapat diakses hanya ketika proses JVM masih hidup. Perpustakaan akan membersihkan data semasa prosesnya berakhir.

4.2. Peta Berterusan

Tidak seperti peta dalam memori, pelaksanaannya akan menyimpan peta yang berterusan ke cakera . Sekarang mari kita lihat bagaimana kita dapat membuat peta yang berterusan:

ChronicleMap persistedCountryMap = ChronicleMap .of(LongValue.class, CharSequence.class) .name("country-map") .entries(50) .averageValue("America") .createPersistedTo(new File(System.getProperty("user.home") + "/country-details.dat"));

Ini akan membuat fail bernama country-details.dat dalam folder yang ditentukan. Sekiranya fail ini sudah tersedia di jalan yang ditentukan, maka pelaksanaan pembangun akan membuka pautan ke penyimpanan data yang ada dari proses JVM ini.

Kita boleh menggunakan peta yang berterusan sekiranya kita menginginkannya:

  • bertahan di luar proses pencipta; sebagai contoh, untuk menyokong penempatan semula aplikasi panas
  • menjadikannya global dalam pelayan; sebagai contoh, untuk menyokong pelbagai akses proses serentak
  • bertindak sebagai simpanan data yang akan kita simpan ke cakera

5. Konfigurasi Saiz

Wajib untuk mengkonfigurasi nilai rata-rata dan kunci rata-rata semasa membuat Peta Kronik, kecuali jika kunci / nilai jenis kami sama ada primitif berkotak atau antara muka nilai. Dalam contoh kami, kami tidak mengkonfigurasi kunci rata-rata kerana jenis kunci LongValue adalah antara muka nilai.

Sekarang, mari kita lihat apakah pilihan untuk mengkonfigurasi jumlah bait kunci / nilai rata-rata:

  • rata-rata Nilai () - Nilai dari mana jumlah purata bait yang akan diperuntukkan untuk nilai entri peta ditentukan
  • averageValueSize () - Bilangan purata bait yang akan diperuntukkan untuk nilai entri peta
  • constantValueSizeBySample () - Bilangan bait yang akan diperuntukkan untuk nilai entri peta apabila ukuran nilai selalu sama
  • purataKey () - Kunci dari mana jumlah purata bait yang akan diperuntukkan untuk kunci entri peta ditentukan
  • purataKeySize () - Bilangan purata bait yang akan diperuntukkan untuk kunci entri peta
  • constantKeySizeBySample () - Bilangan bait yang akan diperuntukkan untuk kunci entri peta apabila ukuran kunci sentiasa sama

6. Jenis Kunci dan Nilai

Terdapat piawaian tertentu yang perlu kita ikuti ketika membuat Peta Kronik, terutama ketika menentukan kunci dan nilai. Peta berfungsi paling baik apabila kita membuat kunci dan nilai menggunakan jenis yang disyorkan.

Berikut adalah beberapa jenis yang disyorkan:

  • Antara muka nilai
  • Mana-mana kelas yang melaksanakan antara muka Byteable dari Chronicle Bytes
  • Mana-mana kelas yang melaksanakan antara muka BytesMarshallable dari Chronicle Bytes; kelas pelaksanaan harus mempunyai konstruktor no-arg awam
  • bait [] dan ByteBuffer
  • CharSequence , String , dan StringBuilder
  • Integer , Long , and Double
  • Mana-mana kelas yang melaksanakan java.io.Externalizable ; kelas pelaksanaan harus mempunyai konstruktor no-arg awam
  • Apa-apa jenis yang melaksanakan java.io.Serializable , termasuk jenis primitif berkotak (kecuali yang disenaraikan di atas) dan jenis array
  • Apa-apa jenis lain, jika penyesuai khas disediakan

7. Menanyakan Peta Kronik

Peta Kronik menyokong pertanyaan satu-satu dan juga pertanyaan pelbagai kunci.

7.1. Single-Key Queries

Single-key queries are the operations that deal with a single key. ChronicleMap supports all the operations from the Java Map interface and ConcurrentMap interface:

LongValue qatarKey = Values.newHeapInstance(LongValue.class); qatarKey.setValue(1); inMemoryCountryMap.put(qatarKey, "Qatar"); //... CharSequence country = inMemoryCountryMap.get(key);

In addition to the normal get and put operations, ChronicleMap adds a special operation, getUsing(), that reduces the memory footprint while retrieving and processing an entry. Let's see this in action:

LongValue key = Values.newHeapInstance(LongValue.class); StringBuilder country = new StringBuilder(); key.setValue(1); persistedCountryMap.getUsing(key, country); assertThat(country.toString(), is(equalTo("Romania"))); key.setValue(2); persistedCountryMap.getUsing(key, country); assertThat(country.toString(), is(equalTo("India")));

Here we've used the same StringBuilder object for retrieving values of different keys by passing it to the getUsing() method. It basically reuses the same object for retrieving different entries. In our case, the getUsing() method is equivalent to:

country.setLength(0); country.append(persistedCountryMap.get(key));

7.2. Multi-Key Queries

There may be use cases where we need to deal with multiple keys at the same time. For this, we can use the queryContext() functionality. The queryContext() method will create a context for working with a map entry.

Let's first create a multimap and add some values to it:

Set averageValue = IntStream.of(1, 2).boxed().collect(Collectors.toSet()); ChronicleMap
    
      multiMap = ChronicleMap .of(Integer.class, (Class
     
      ) (Class) Set.class) .name("multi-map") .entries(50) .averageValue(averageValue) .create(); Set set1 = new HashSet(); set1.add(1); set1.add(2); multiMap.put(1, set1); Set set2 = new HashSet(); set2.add(3); multiMap.put(2, set2);
     
    

To work with multiple entries, we have to lock those entries to prevent inconsistency that may occur due to a concurrent update:

try (ExternalMapQueryContext
    
      fistContext = multiMap.queryContext(1)) { try (ExternalMapQueryContext
     
       secondContext = multiMap.queryContext(2)) { fistContext.updateLock().lock(); secondContext.updateLock().lock(); MapEntry
      
        firstEntry = fistContext.entry(); Set firstSet = firstEntry.value().get(); firstSet.remove(2); MapEntry
       
         secondEntry = secondContext.entry(); Set secondSet = secondEntry.value().get(); secondSet.add(4); firstEntry.doReplaceValue(fistContext.wrapValueAsData(firstSet)); secondEntry.doReplaceValue(secondContext.wrapValueAsData(secondSet)); } } finally { assertThat(multiMap.get(1).size(), is(equalTo(1))); assertThat(multiMap.get(2).size(), is(equalTo(2))); }
       
      
     
    

8. Closing the Chronicle Map

Setelah selesai bekerja dengan peta kami, mari kita panggil kaedah tutup () pada objek peta kita untuk melepaskan memori luar timbunan dan sumber yang berkaitan dengannya:

persistedCountryMap.close(); inMemoryCountryMap.close(); multiMap.close();

Satu perkara yang perlu diingat di sini ialah semua operasi peta mesti diselesaikan sebelum menutup peta. Jika tidak, JVM mungkin berlaku secara tidak dijangka.

9. Kesimpulannya

Dalam tutorial ini, kami telah belajar bagaimana menggunakan Peta Kronik untuk menyimpan dan mendapatkan pasangan nilai-kunci. Walaupun versi komuniti tersedia dengan kebanyakan fungsi inti, versi komersial mempunyai beberapa ciri canggih seperti replikasi data di beberapa pelayan dan panggilan jarak jauh.

Semua contoh yang telah kita bincangkan di sini boleh didapati melalui projek Github.