Không bao giờ viết giải pháp bộ nhớ đệm của bạn
Một cách khác để tăng tốc công việc với cơ sở dữ liệu là lưu trữ các đối tượng mà chúng tôi đã yêu cầu trước đó.
Quan trọng! Không bao giờ viết giải pháp bộ nhớ đệm của riêng bạn. Nhiệm vụ này có rất nhiều cạm bẫy mà bạn chưa bao giờ mơ tới.
Sự cố 1 - xóa bộ nhớ cache . Đôi khi các sự kiện xảy ra khi một đối tượng cần được xóa khỏi bộ nhớ cache hoặc cập nhật trong bộ nhớ cache. Cách duy nhất để làm điều này một cách thành thạo là chuyển tất cả các yêu cầu tới cơ sở dữ liệu thông qua công cụ bộ đệm. Mặt khác, mỗi lần bạn sẽ phải thông báo rõ ràng cho bộ nhớ cache biết những đối tượng nào trong đó sẽ bị xóa hoặc cập nhật.
Vấn đề 2 - thiếu bộ nhớ . Bộ nhớ đệm có vẻ là một ý tưởng tuyệt vời cho đến khi bạn thấy rằng các đối tượng trong bộ nhớ chiếm rất nhiều dung lượng. Bạn cần thêm hàng chục gigabyte bộ nhớ để bộ đệm ứng dụng máy chủ hoạt động hiệu quả.
Và vì luôn thiếu bộ nhớ, nên cần có một chiến lược hiệu quả để xóa các đối tượng khỏi bộ đệm. Điều này hơi giống với trình thu gom rác trong Java. Và như bạn còn nhớ, trong nhiều thập kỷ, những bộ óc giỏi nhất đã phát minh ra nhiều cách khác nhau để đánh dấu đồ vật theo thế hệ, v.v.
Vấn đề 3 - các chiến lược khác nhau . Như thực tế cho thấy, các chiến lược khác nhau để lưu trữ và cập nhật trong bộ đệm có hiệu quả đối với các đối tượng khác nhau. Một hệ thống lưu trữ hiệu quả không thể chỉ thực hiện một chiến lược cho tất cả các đối tượng.
Vấn đề 4 - Lưu trữ hiệu quả các tệp . Bạn không thể chỉ lưu trữ các đối tượng trong bộ đệm. Các đối tượng thường chứa các tham chiếu đến các đối tượng khác, v.v... Với tốc độ này, bạn sẽ không cần bộ thu gom rác: đơn giản là nó sẽ không có bất cứ thứ gì để loại bỏ.
Do đó, thay vì lưu trữ chính các đối tượng, đôi khi sẽ hiệu quả hơn nhiều khi lưu trữ các giá trị của các trường nguyên thủy của chúng. Và các hệ thống để nhanh chóng xây dựng các đối tượng dựa trên chúng.
Kết quả là bạn sẽ nhận được toàn bộ DBMS ảo trong bộ nhớ, hệ thống này sẽ hoạt động nhanh chóng và tiêu tốn ít bộ nhớ.
Bộ nhớ đệm cơ sở dữ liệu
Ngoài việc tạo bộ nhớ đệm trực tiếp trong chương trình Java, bộ nhớ đệm thường được tổ chức trực tiếp trong cơ sở dữ liệu.
Có bốn cách tiếp cận lớn:
Cách tiếp cận đầu tiên là phi chuẩn hóa cơ sở dữ liệu . Máy chủ SQL lưu trữ dữ liệu trong bộ nhớ khác với cách dữ liệu được lưu trữ trong bảng.
Khi dữ liệu được lưu trữ trên đĩa trong các bảng, các nhà phát triển thường cố gắng tránh sao chép dữ liệu càng nhiều càng tốt - quá trình này được gọi là chuẩn hóa cơ sở dữ liệu. Vì vậy, để tăng tốc độ làm việc với dữ liệu trong bộ nhớ, quá trình ngược lại được thực hiện - chuẩn hóa cơ sở dữ liệu. Một loạt các bảng có liên quan đã có thể được lưu trữ ở dạng kết hợp - ở dạng bảng lớn, v.v.
Cách tiếp cận thứ hai là bộ nhớ đệm truy vấn . Và kết quả truy vấn.
Hệ quản trị cơ sở dữ liệu nhận thấy rằng các yêu cầu tương tự hoặc giống nhau thường đến với nó. Sau đó, nó chỉ đơn giản là bắt đầu lưu trữ các yêu cầu này và phản hồi của chúng. Nhưng đồng thời, bạn cần đảm bảo rằng các hàng đã thay đổi trong cơ sở dữ liệu sẽ được xóa khỏi bộ đệm một cách kịp thời.
Cách tiếp cận này có thể rất hiệu quả với một con người có thể phân tích các truy vấn và giúp DBMS tìm ra cách tốt nhất để lưu chúng vào bộ đệm.
Cách tiếp cận thứ ba là một cơ sở dữ liệu trong bộ nhớ .
Một cách tiếp cận thường được sử dụng khác. Một cơ sở dữ liệu khác được đặt giữa máy chủ và DBMS, nơi chỉ lưu trữ tất cả dữ liệu của nó trong bộ nhớ. Nó còn được gọi là Trong bộ nhớ-DB. Nếu bạn có nhiều máy chủ khác nhau truy cập cùng một cơ sở dữ liệu, thì khi sử dụng In-Memory-DB, bạn có thể tổ chức bộ nhớ đệm dựa trên loại máy chủ cụ thể.
Ví dụ:
![](https://cdn.codegym.cc/images/article/a2a92dd6-07b2-46e4-880c-7f2673af154b/1024.jpeg)
Cách tiếp cận 4 - cụm cơ sở dữ liệu . Một số cơ sở chỉ đọc.
Một giải pháp khác là sử dụng một cụm: một số DBMS cùng loại chứa dữ liệu giống hệt nhau. Đồng thời, bạn có thể đọc dữ liệu từ tất cả các cơ sở dữ liệu và chỉ ghi vào một cơ sở dữ liệu. Sau đó được đồng bộ hóa với phần còn lại của cơ sở dữ liệu.
Đây là một giải pháp rất tốt vì nó dễ cấu hình và hoạt động trong thực tế. Thông thường, đối với một yêu cầu cơ sở dữ liệu để thay đổi dữ liệu, 10-100 yêu cầu đọc dữ liệu sẽ đến với nó.
Các loại bộ nhớ đệm trong Hibernate
Hibernate hỗ trợ ba cấp bộ nhớ đệm:
- Bộ nhớ đệm ở cấp phiên (Session)
- Bộ nhớ đệm ở cấp độ SessionFactory
- Yêu cầu bộ nhớ đệm (và kết quả của chúng)
Bạn có thể thử biểu diễn hệ thống này dưới dạng một hình như vậy:
![](https://cdn.codegym.cc/images/article/938d3cbc-b006-4c2d-9bdc-b2311e5de4a5/1024.jpeg)
Loại bộ đệm đơn giản nhất (còn được gọi là bộ đệm cấp đầu tiên ) được triển khai ở cấp phiên Hibernate. Chế độ ngủ đông luôn sử dụng bộ đệm này theo mặc định và không thể tắt được .
Hãy xem xét ngay ví dụ sau:
Employee director1 = session.get(Employee.class, 4);
Employee director2 = session.get(Employee.class, 4);
assertTrue(director1 == director2);
Có vẻ như hai truy vấn cơ sở dữ liệu sẽ được thực hiện ở đây, nhưng thực tế không phải vậy. Sau yêu cầu đầu tiên tới cơ sở dữ liệu, đối tượng Nhân viên sẽ được lưu vào bộ đệm. Và nếu bạn truy vấn lại đối tượng trong cùng một phiên, Hibernate sẽ trả về cùng một đối tượng Java.
Đối tượng giống nhau có nghĩa là ngay cả các tham chiếu đối tượng cũng sẽ giống hệt nhau. Nó thực sự là cùng một đối tượng.
Các phương thức save() , update() , saveOrUpdate() , load() , get() , list() , iterate() và scroll() sẽ luôn sử dụng bộ đệm cấp một. Trên thực tế, không có gì hơn để thêm.
Bộ nhớ đệm cấp hai
Nếu bộ đệm cấp một được liên kết với đối tượng phiên, thì bộ đệm cấp hai được liên kết với đối tượng phiên.PhiênFactory. Điều đó có nghĩa là khả năng hiển thị của các đối tượng trong bộ đệm này rộng hơn nhiều so với trong bộ đệm cấp một.
Ví dụ:
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));
Trong ví dụ này, hai truy vấn sẽ được thực hiện đối với cơ sở dữ liệu. Hibernate sẽ trả về các đối tượng giống hệt nhau, nhưng nó sẽ không phải là cùng một đối tượng - chúng sẽ có các tham chiếu khác nhau.
Bộ nhớ đệm cấp hai bị tắt theo mặc định . Do đó, chúng tôi có hai truy vấn cơ sở dữ liệu thay vì một.
Để kích hoạt nó, bạn cần viết những dòng sau vào tệp 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"/>
Sau khi kích hoạt bộ nhớ đệm cấp hai, hành vi Hibernate sẽ thay đổi một chút:
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);
Chỉ sau tất cả các thao tác này, bộ nhớ đệm cấp hai mới được kích hoạt và trong ví dụ trên, chỉ một truy vấn tới cơ sở dữ liệu sẽ được thực hiện.