2009-10-01 20 views
8

Tôi có một ứng dụng sử dụng JPA, Hibernate và ehcache, cũng như các giao dịch khai báo của Spring. Tải trên DB khá cao nên mọi thứ được lưu trữ để tăng tốc độ, bao gồm cả bộ sưu tập. Bây giờ không phải là bí mật mà các bộ sưu tập được lưu trữ riêng biệt từ các thực thể sở hữu chúng vì vậy nếu tôi xóa một thực thể là một phần tử của bộ sưu tập được lưu trong bộ nhớ cache này, hãy giữ nguyên một phần tử hoặc cập nhật thực thể sao cho nó di chuyển từ bộ sưu tập này sang bộ sưu tập khác, tôi phải thực hiện việc gỡ bỏ bằng tay.Hibernate/Ehcache: gỡ bỏ các bộ sưu tập từ bộ nhớ cache cấp 2 không đồng bộ với DB khác đọc

Vì vậy, tôi sử dụng trình nghe sự kiện ngủ đông theo dõi các thực thể được chèn, xóa hoặc cập nhật và lưu thông tin đó cho đồng bộ hóa giao dịch đã đăng ký với người quản lý giao dịch của Spring. Việc đồng bộ hóa sau đó thực hiện việc hủy bỏ khi giao dịch được thực hiện.

Bây giờ vấn đề là đó khá thường xuyên, một số giao dịch đồng thời khác quản lý để tìm một bộ sưu tập trong bộ nhớ cache vừa bị đuổi ra (những sự kiện này thường phần mười của một giây ngoài theo log) và, một cách tự nhiên , gây ra một EntityNotFoundException xảy ra.

Làm cách nào để đồng bộ hóa nội dung này chính xác?

Tôi đã cố gắng thực hiện lệnh đuổi theo trong 4 phương thức của TransactionSynchronization (trong đó được gọi tại các thời điểm khác nhau liên quan đến hoàn thành giao dịch).

Trả lời

3

Về cơ bản những gì bạn cần làm là ép buộc đọc từ cơ sở dữ liệu trong trường hợp bộ sưu tập đang trong quá trình hoặc đã bị trục xuất. Một cách để làm điều này sẽ là đánh dấu bộ sưu tập là bẩn ngay sau khi yêu cầu gỡ bỏ nó đã được nhận nhưng trước khi vào giao dịch để thay đổi nó. Bất kỳ giao dịch đồng thời nào đi kèm sẽ kiểm tra cờ bẩn và nếu nó được đặt thành true, nó sẽ lấy dữ liệu từ cơ sở dữ liệu nếu không nó có thể đọc từ bộ nhớ cache. Bạn có thể cần phải thay đổi thiết lập giao dịch DB của bạn để các giao dịch đồng thời chặn cho đến khi một cập nhật dữ liệu kết thúc sao cho dữ liệu chính xác được đọc từ DB. Khi giao dịch kết thúc, bạn có thể đặt lại cờ bẩn thành false.

Bạn cũng có thể tạo khóa trên bộ sưu tập được lưu trong bộ nhớ cache khi bản cập nhật, chèn hoặc xóa sẽ đến hạn miễn là thời gian bị đuổi. Điều này sẽ đảm bảo rằng không có giao dịch nào khác có thể đọc/thay đổi bộ sưu tập được lưu trong bộ nhớ cache cho đến khi quá trình trục xuất kết thúc.

+0

Người ta đuổi bên ngoài của một giao dịch, nhân tiện. Và tôi phải tìm API để đánh dấu chúng bẩn, cảm ơn.Ngoài ra, làm thế nào để làm cho Hibernate đồng bộ hóa trên khóa mà bạn đã đề xuất thêm? –

+1

Rõ ràng, cờ bẩn của PersistentCollection sẽ không làm, bởi vì các giao dịch khác nhau có được các phiên bản khác nhau của cùng một bộ sưu tập . Đối với khóa, tôi sẽ xem xét điều đó tiếp theo, và sẽ thực sự đánh giá cao nếu ai đó chỉ cho tôi API thích hợp. EhCache không hỗ trợ khóa theo như tôi biết, nhìn vào điều đó điều đầu tiên. –

0

Tại sao bạn không thể giữ cho bộ sưu tập được cập nhật? tức là khi bạn thêm một đối tượng, hãy thêm đối tượng vào bộ sưu tập mà nó thuộc về. Khi bạn xóa một đối tượng, hãy xóa nó khỏi bộ sưu tập mà nó đang ở. Theo kinh nghiệm của tôi khi sử dụng bộ nhớ đệm với hibernate hoặc jpa, trạng thái của đối tượng (không phải trạng thái của cơ sở dữ liệu) được lưu trữ, do đó bạn cần đảm bảo mô hình đối tượng của mình trong bộ nhớ được đồng bộ với mô hình đối tượng trên cơ sở dữ liệu.

Hoặc tôi có thiếu gì đó không? Tại sao bạn không thể đơn giản giữ cho các bộ sưu tập được tăng cường?

+1

Đó là một ứng dụng đa luồng, truyền cùng một phiên bản cập nhật với một bộ sưu tập cập nhật xung quanh có vẻ khó khăn vì có tất cả các hoạt động đồng thời mất nhiều thời gian khác nhau và tôi có xu hướng sử dụng EntityManager. getById rất nhiều để lấy trạng thái mới nhất của một thực thể. –

Các vấn đề liên quan