cuốn sách gpt4 ai đã làm

[Nói chuyện linh tinh] Một số vấn đề và suy nghĩ phải gặp khi chuyển từ khóa câu lạc quan của JPA sang khóa bi quan

In lại Tác giả: Sahara Thời gian cập nhật: 2024-07-31 17:11:56 58 4
mua khóa gpt4 Nike

lý lịch

Đảm bảo nhận được một dự án bên ngoài sử dụng JPA làm ORM.

Có nhiều dự án thực tế với các trường @version.

OptimisticLocingFailureException thường được báo cáo khi tính toán ở mức cao.

Nguyên thức kiến ​​thức

@version của JPA thực hiện khóa câu lạc bộ bằng cách thao tác các câu lệnh SQL.

FILE NHẬP tên_bảng BỘ cột_cập nhật = new_value, phiên bản = phiên bản mới Ở ĐÂU NHẬN DẠNG = thực thể_id  phiên bản = old version

Thao tác "So sánh và cài đặt" này phải được đặt trong cơ sở dữ liệu lớp. Tính toán nguyên tử của "So sánh và cài đặt" (Tính chất nguyên tử của bản cập nhật lệnh).

Nếu thao tác "So sánh và đặt" này được đặt ở lớp ứng dụng, thì nguyên tử tính toán không thể được đảm bảo, nghĩa là việc so sánh phiên bản có thể thành công, nhưng vào thời điểm cập nhật thực tế đã xảy ra, cơ sở dữ liệu ở phiên bản đã được sửa đổi.

Tại thời điểm này, những sửa đổi không chính xác sẽ xảy ra.

nhu cầu

Giải thích các lỗi đó để giao dịch có thể được hoàn thành bình thường.

Quá trình - Thử lại

Vì lỗi khóa liên lạc được báo cáo, điều đó có nghĩa là có xung đột chỉnh sửa, vì vậy chỉ cần tự động thử lại.

Trường hợp mã.

Trước khi sửa đổi.

@service
công cộng lớp học Dịch vụ sản phẩm { @Autowired
     Riêng tư ProductRepository ProductRepository @Transactional;
     công cộng trống rỗng updateProductPrice(Long ProductId, Double newPrice) { Sản phẩm sản phẩm = ProductRepository.findById(productId).orElseThrow(()->mới RuntimeException("Không tìm thấy sản phẩm") sản phẩm.setPrice(newPrice); sản phẩmRepository.save(sản phẩm);

Sau khi sửa đổi.

Thêm phương thức withRetry. như thao tác của người dùng trên giao diện người dùng trang).

@service
công cộng lớp học Dịch vụ sản phẩm { @Autowired
     Riêng tư Sản phẩmKho lưu trữ sản phẩmKho lưu trữ;

     công cộng trống rỗng updateProductPriceWithRetry(Dài sản phẩmId, Gấp đôi giá mới) {
         boolean đã cập nhật = SAI;
          //Tiếp tục thử lại cho đến khi thành công
          mạnhkhi(!đã cập nhật) {
               thử { updateProductPrice(productId, newPrice đã cập nhật); = ĐÚNG VẬY; lấy được (OpimisticLockingFailureException e) { System.out.println("lỗi khóa updateProductprice, đang thử lại...") } } } @Transactional
     công cộng trống rỗng updateProductPrice(Long ProductId, Double newPrice) { Sản phẩm sản phẩm = ProductRepository.findById(productId).orElseThrow(()->mới RuntimeException("Không tìm thấy sản phẩm") sản phẩm.setPrice(newPrice); sản phẩmRepository.save(sản phẩm); 

Các vấn đề dựa vào khóa lạc quan - tính đồng thời cao mang lại xung đột

Nhưng it làm tăng mức nặng nề cho cơ sở dữ liệu.

Ngoài ra, khóa lạc quan cũng có những vấn đề riêng:

Lớp nghiệp vụ gửi các sửa đổi giao dịch trực tiếp tới cơ sở dữ liệu, cho phép cơ chế khóa an toàn bảo vệ dữ liệu tối ưu.

Lúc này, tốc độ càng cao thì càng có nhiều xung đột trong sửa đổi, số lần gửi không hợp lệ càng nhiều và áp lực up the base data càng lớn.

Cao xung đột đáp ứng - đưa ra bi quan

Cách giải quyết xung đột cao là đưa ra khóa bi quan trong lớp nghiệp vụ.

Trước khi hoạt động kinh doanh, có thể bị khóa.

Một mặt, nó làm giảm số lượng giao dịch được gửi tới cơ sở dữ liệu và các mặt khác, nó cũng làm giảm chi phí CPU của lớp nghiệp vụ (mã nghiệp vụ chỉ được thực thi sau khi có khóa).

@service
công cộng lớp học Dịch vụ sản phẩm { @Autowired
     Riêng tư Sản phẩmKho lưu trữ sản phẩmKho lưu trữ;

     
     công cộng trống rỗng someComplicateOperationWithLock(Thông số đối tượng) {
          
          //Yêu cầu một số đối tượng sửa đổi liên kết đến hoạt động kinh doanh này phải được khóa đối số icon.
          //key=tiền tố lớp+id object
          Danh sách các phím  = Mảng.asList(....);
          
          //Sử dụng RedisLock
          //Bắt đầu thực thi mã nhiệm vụ sau khi có khóa, sau đó miễn phí sau khi hoàn thành công việc thực hiện nhiệm vụ.
          RedisLockUtil.runWithLock(keys, retryTime, retryLockTimeout, ()->someComplicateOperation(params)}): } @Transactional
     công cộng trống rỗng someComplicateOperation(Thông số đối tượng) {...... } }    

Cái hố phải.

Thông thường, sau khi đã khóa, bạn cần tải lại dữ liệu mới nhất để không xảy ra xung đột khi chỉnh sửa. (Người mua khóa trước đó có thể đã sửa đổi dữ liệu).

Tuy nhiên, JPA có cảnh báo ổn định và một lớp đệm bộ nhớ. đã được khóa, dữ liệu trong bộ đệm sẽ được lấy thay vì dữ liệu mới nhất trong cơ sở dữ liệu sau khi lấy được khóa.

Trong trường hợp này, ngay cả khi sử dụng khóa bi quan, xung đột vẫn sẽ xảy ra khi giao dịch được thực hiện.

Trường hợp:

@service
công cộng lớp học Dịch vụ sản phẩm { @Autowired
     Riêng tư Sản phẩmKho lưu trữ sản phẩmKho lưu trữ;

     
     công cộng trống rỗng someComplicateOperationWithLock(Thông số đối tượng) {
// Được truy vấn một lần trước khi lấy khóa. sản phẩm chuỗi dài dài.
= xxxx Sản phẩm sản phẩm = ProductRepository.findById(productId).orElseThrow(()->ném mới RuntimeException("Không tìm thấy sản phẩm")); //Yêu cầu một số đối tượng sửa đổi liên kết đến hoạt động kinh doanh này phải được khóa đối số icon. //key=tiền tố lớp+id object Danh sách các phím = Mảng.asList(....); //RedisLockSử dụng //Bắt đầu thực thi mã nhiệm vụ sau khi có khóa, sau đó miễn phí sau khi hoàn thành công việc thực hiện nhiệm vụ. RedisLockUtil.runWithLock(keys, retryTime, retryLockTimeout, ()->someComplicateOperation(params)}): } @Transactional công cộng trống rỗng someComplicateOperation(Thông số đối tượng) {..... //Lấy dữ liệu cũ từ bộ đệm Sản phẩm sản phẩm = ProductRepository.findById(productId).orElseThrow(()->ném mới RuntimeException("Không tìm thấy sản phẩm")); .... } }

Phương pháp đối thoại——làm mới.

Trong phạm vi khóa bi quan, khi tải dữ liệu thực tế lần đầu tiên, hãy sử dụng phương pháp làm mới để buộc lấy dữ liệu dữ liệu mới nhất từ ​​​​DB.

@service
công cộng lớp học Dịch vụ sản phẩm { @Autowired
     Riêng tư Sản phẩmKho lưu trữ sản phẩmKho lưu trữ;

     
     công cộng trống rỗng someComplicateOperationWithLock(Thông số đối tượng) {
          //Một truy vấn đã được thực hiện trước khi lấy khóa. giữ lâu dài.
          Id sản phẩm chuỗi = xxxx Sản phẩm sản phẩm = ProductRepository.findById(productId).orElseThrow(()->ném mới RuntimeException("Không tìm thấy sản phẩm"));
          
          //Yêu cầu một số đối tượng sửa đổi liên kết đến hoạt động kinh doanh này phải được khóa đối số icon.
          //key=tiền tố lớp+id object
          Danh sách các phím  = Mảng.asList(....);
          
          //RedisLockSử dụng
          //Bắt đầu thực thi mã nhiệm vụ sau khi có khóa, sau đó miễn phí sau khi hoàn thành công việc thực hiện nhiệm vụ.
          RedisLockUtil.runWithLock(keys, retryTime, retryLockTimeout, ()->someComplicateOperation(params)}): } @Transactional
     công cộng trống rỗng someComplicateOperation(Thông số đối tượng) {.....
         //Lấy dữ liệu cũ từ bộ đệm
         Sản phẩm sản phẩm = ProductRepository.findById(productId).orElseThrow(()->ném mới RuntimeException("Không tìm thấy sản phẩm"));
        //Sử dụng phương pháp mới để buộc truy xuất dữ liệu mới nhất từ ​​​​cơ sở dữ liệu và cập nhật vào bối cảnh cảnh lưu giữ lâu dài.
        Trình quản lý thực thi EntityManager = SpringUtil.getBean(EntityManager.lớp học) sản phẩm = thực thểManager.refresh(sản phẩm); .... } }    

Tóm tắt

Dự án này sử dụng cách tiếp cận kết hợp giữa khóa câu lạc quan và khóa bi quan, sử dụng khóa bi quan để hạn chế sửa đổi đổi đồng thời và khóa lạc quan để bảo vệ tính cơ bản nhất.

Về bảo vệ tính nhất quán.

Đối với một số ứng dụng đơn giản có khả năng ghi đồng thời không cao, giao dịch + khóa câu lạc bộ là đủ.

  • Thêm trường @version vào thực thi
  • Phương thức kinh doanh cộng với @Transactional

Mã này đơn giản nhất.

Chỉ khi tỷ lệ ghi đồng thời cao hoặc khi hoạt động ghi đồng thời cao có thể xảy ra dựa trên suy luận kinh doanh, bạn mới nên Cân nhắc áp dụng bi quan cơ chế .

(Mã càng phức tạp thì càng dễ gây ra sự cố và càng khó bảo trì).

Cuối cùng, bài viết về [Thảo luận linh tinh] Một số vấn đề và suy nghĩ phải khi thay đổi khóa lạc quan của JPA thành khóa bi quan sẽ kết thúc tại đây. suy nghĩ, vui lòng tìm kiếm các bài viết của CFSDN hoặc tiếp tục duyệt các bài viết viết liên quan. Tôi hy vọng bạn sẽ ủng hộ blog của tôi trong tương lai .

58 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress