Jangan pernah menulis solusi caching Anda
Cara lain untuk mempercepat pekerjaan dengan database adalah dengan meng-cache objek yang telah kita minta sebelumnya.
Penting! Jangan pernah menulis solusi caching Anda sendiri. Tugas ini memiliki begitu banyak jebakan yang tidak pernah Anda impikan.
Masalah 1 - cache flush . Terkadang kejadian terjadi saat objek perlu dihapus dari cache atau diperbarui di cache. Satu-satunya cara untuk melakukan ini secara kompeten adalah meneruskan semua permintaan ke database melalui mesin cache. Jika tidak, setiap kali Anda harus secara eksplisit memberi tahu cache objek mana di dalamnya yang harus dihapus atau diperbarui.
Masalah 2 - kekurangan memori . Caching sepertinya ide yang bagus sampai Anda menemukan bahwa objek dalam memori menghabiskan banyak ruang. Anda memerlukan tambahan memori puluhan gigabyte agar cache aplikasi server berfungsi secara efektif.
Dan karena selalu ada kekurangan memori, diperlukan strategi yang efektif untuk menghapus objek dari cache. Ini agak mirip dengan pengumpul sampah di Jawa. Dan seperti yang Anda ingat, selama beberapa dekade pemikir terbaik telah menemukan berbagai cara untuk menandai objek dari generasi ke generasi, dll.
Soal 3 - strategi yang berbeda . Seperti yang diperlihatkan oleh praktik, berbagai strategi untuk menyimpan dan memperbarui dalam cache efektif untuk objek yang berbeda. Sistem caching yang efisien tidak dapat melakukan hanya satu strategi untuk semua objek.
Masalah 4 - Penyimpanan file . Anda tidak bisa begitu saja menyimpan objek di cache. Objek terlalu sering berisi referensi ke objek lain, dan seterusnya.Pada tingkat ini, Anda tidak memerlukan pengumpul sampah: tidak ada yang perlu dihapus.
Oleh karena itu, daripada menyimpan objek itu sendiri, terkadang jauh lebih efisien untuk menyimpan nilai bidang primitifnya. Dan sistem untuk membuat objek dengan cepat berdasarkan objek tersebut.
Hasilnya, Anda akan mendapatkan seluruh DBMS virtual dalam memori, yang seharusnya bekerja dengan cepat dan menghabiskan sedikit memori.
Caching basis data
Selain caching langsung di program Java, caching sering diatur langsung di database.
Ada empat pendekatan besar:
Pendekatan pertama adalah untuk denormalize database . Server SQL menyimpan data dalam memori secara berbeda dari cara penyimpanannya dalam tabel.
Ketika data disimpan pada disk dalam tabel, sangat sering pengembang berusaha menghindari duplikasi data sebanyak mungkin - proses ini disebut normalisasi basis data. Jadi, untuk mempercepat pekerjaan dengan data dalam memori, proses sebaliknya dilakukan - denormalisasi basis data. Sekelompok tabel terkait sudah dapat disimpan dalam bentuk gabungan - dalam bentuk tabel besar, dll.
Pendekatan kedua adalah query caching . Dan hasil kueri.
DBMS melihat bahwa sangat sering permintaan yang sama atau serupa datang padanya. Kemudian ia mulai menyimpan permintaan ini dan tanggapannya ke dalam cache. Tetapi pada saat yang sama, Anda perlu memastikan bahwa baris yang telah diubah dalam database dihapus dari cache tepat waktu.
Pendekatan ini bisa sangat efektif dengan manusia yang dapat menganalisis kueri dan membantu DBMS mencari cara terbaik untuk menyimpannya.
Pendekatan ketiga adalah database dalam memori .
Pendekatan lain yang umum digunakan. Basis data lain ditempatkan di antara server dan DBMS, yang menyimpan semua datanya hanya di memori. Ini juga disebut In-Memory-DB. Jika Anda memiliki banyak server berbeda yang mengakses database yang sama, maka dengan menggunakan In-Memory-DB Anda dapat mengatur caching berdasarkan jenis server tertentu.
Contoh:
Pendekatan 4 - cluster database . Beberapa basis hanya-baca.
Solusi lain adalah dengan menggunakan cluster: beberapa DBMS dengan tipe yang sama berisi data yang identik. Pada saat yang sama, Anda dapat membaca data dari semua database, dan menulis hanya ke satu database. Yang kemudian disinkronkan dengan database lainnya.
Ini adalah solusi yang sangat bagus karena mudah dikonfigurasi dan berfungsi dalam praktiknya. Biasanya, untuk satu permintaan ke database untuk mengubah data, 10-100 permintaan untuk membaca data datang.
Jenis caching di Hibernate
Hibernasi mendukung tiga tingkat caching:
- Caching di tingkat sesi (Sesi)
- Caching di tingkat SessionFactory
- Permintaan caching (dan hasilnya)
Anda dapat mencoba merepresentasikan sistem ini dalam bentuk gambar berikut:
Jenis caching paling sederhana (juga disebut cache level pertama ) diimplementasikan pada level sesi Hibernasi. Hibernasi selalu menggunakan cache ini secara default dan tidak dapat dinonaktifkan .
Mari kita langsung perhatikan contoh berikut:
Employee director1 = session.get(Employee.class, 4);
Employee director2 = session.get(Employee.class, 4);
assertTrue(director1 == director2);
Tampaknya dua kueri ke database akan dieksekusi di sini, tetapi tidak demikian. Setelah permintaan pertama ke database, objek Karyawan akan di-cache. Dan jika Anda menanyakan objek lagi di sesi yang sama, Hibernasi akan mengembalikan objek Java yang sama.
Objek yang sama berarti bahkan referensi objek akan identik. Itu benar-benar objek yang sama.
Metode save() , update() , saveOrUpdate() , load() , get() , list() , iterate() , dan scroll() akan selalu menggunakan cache tingkat pertama. Sebenarnya, tidak ada lagi yang perlu ditambahkan.
Caching tingkat kedua
Jika cache tingkat pertama terikat ke objek sesi, maka cache tingkat kedua terikat ke objek sesi.SessionFactory. Artinya visibilitas objek di cache ini jauh lebih luas daripada di cache level pertama.
Contoh:
Session session = factory.openSession();
Employee director1 = session.get(Employee.class, 4);
session.close();
Session session = factory.openSession();
Employee director2 = session.get(Employee.class, 4);
session.close();
assertTrue(director1 != director2);
assertTrue(director1.equals(director2));
Dalam contoh ini, dua kueri akan dibuat ke database. Hibernasi akan mengembalikan objek yang identik, tetapi itu bukan objek yang sama - mereka akan memiliki referensi yang berbeda.
Caching tingkat kedua dinonaktifkan secara default . Oleh karena itu, kami memiliki dua kueri ke database, bukan satu.
Untuk mengaktifkannya, Anda perlu menulis baris berikut di file hibernate.cfg.xml:
<property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletEhCacheProvider"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
Setelah mengaktifkan caching tingkat kedua, perilaku Hibernasi akan sedikit berubah:
Session session = factory.openSession();
Employee director1 = session.get(Employee.class, 4);
session.close();
Session session = factory.openSession();
Employee director2 = session.get(Employee.class, 4);
session.close();
assertTrue(director1 == director2);
Hanya setelah semua manipulasi ini, cache level kedua akan diaktifkan, dan dalam contoh di atas, hanya satu kueri ke database yang akan dieksekusi.