2013-08-13 19 views
5

Tôi đã gặp phải vấn đề trong Grails mà tôi nghĩ có thể là một vấn đề tiềm ẩn với cách xử lý đồng thời; và tôi không chắc chắn cách xử lý tốt nhất điều này (hoặc nếu có giải pháp/thực hành đã có sẵn, tôi có thể điều chỉnh).Xử lý các sửa đổi đồng thời trong Grails (GORM) trong khi tránh các ngoại lệ đối tượng cũ

nền


Grails My ứng dụng được phục vụ như là một API REST, và có một phương pháp Enciphering cho dữ liệu mà dựa vào một truy cập biến như một cơ chế muối cho mật mã.

truy cập này biến phải được duy trì, và không thể thấp hơn như các dữ liệu đang diễn ra với một thẻ SIM nơi quầy không thể được sửa đổi sau khi phát hành, do đó điều quan trọng là tôi duy trì truy cập này một cách chính xác. Ngoài ra, nếu bộ đếm không đúng, tin nhắn sẽ bị SIM từ chối.

Khi một cuộc gọi của người dùng, ví dụ: http://example.tld/service/controller/action?id=1 máy chủ sẽ làm như sau:

  • get đối tượng controller với định danh 1
  • Sửa đổi counter viên/hàng của đối tượng
  • save sự đối tượng

Điều này đã tốt cho đến nay 20.000 yêu cầu. Tuy nhiên, hai lần, tôi đã có một StaleObjectException mà tôi đã xác định xảy ra do đối tượng được truy cập vào cùng một thời điểm chính xác. Tôi đã xác định rằng điều này đang xảy ra như API wrapper tôi đã cung cấp sử dụng mười chủ đề, và tình cờ cả hai chủ đề đã được gọi là action cùng một lúc.

Tôi đã đọc và lưu ý rằng tôi có thể:

  • Tắt Khóa lạc (này có vẻ giống như một xấu ý tưởng)
  • Bật nâng cấp động (Tôi không nghĩ điều này sẽ giúp tôi, vì tôi vẫn đang cập nhật cùng một hàng cùng một lúc)
  • lock đối tượng - nhưng tôi nghĩ điều này sẽ vẫn làm tăng Ngoại lệ do đối tượng bị khóa thứ hai thời gian nó được truy cập?
  • Sử dụng executeUpdate mà tôi nghĩ là tương tự như bật Cập nhật động? Có lẽ không hữu ích trong trường hợp sử dụng của tôi.

Câu hỏi


tôi tự hỏi nếu có lẽ một số cơ chế giao dịch tôi có thể sử dụng không? I E. một phương pháp để kiểm tra xem một đối tượng có bị khóa hay không và nếu có, hãy ngủ cho t để cho phép giao dịch hoàn tất trong cơ sở dữ liệu.

Cuối cùng, mục tiêu cuối cùng của tôi là không phải từ chối bất kỳ yêu cầu nào, do đó nếu cơ chế giao dịch ở trên tồn tại (mà tôi giả định là loại khóa bi quan) và cơ chế giao dịch đã từ chối yêu cầu khi đối tượng bị khóa, Tôi muốn một số giải pháp khác như tôi muốn tránh ở tất cả các chi phí từ chối yêu cầu dịch vụ vì nó phức tạp trước khi giao hàng cho khách hàng.

Các giải pháp hiện tại tôi đang nghĩ đến việc là chỉ cần:

try { 
    Foo.save() 
catch (RespectiveException ex) { 
    Thread.sleep(1000) 
    if(depth < 3) { 
     recursiveCallToThisMethod(depth++) 
    } else { 
     render(letTheUserKnowWhyItFailed) 
    } 
} 

Nhưng yeah ... Khá xấu xí.

+0

Thông thường, ngoại lệ sửa đổi đồng thời được dự kiến ​​sẽ được khách hàng xử lý, sau đó phải thử lại thao tác. –

+0

câu hỏi này có thể giúp: http://stackoverflow.com/questions/129329/optimistic-vs-pessimistic-locking –

+0

Bạn đã tìm ra giải pháp nào cho điều này? Tôi có cùng một vấn đề. Điều duy nhất tôi có thể nghĩ là cố gắng có một concurrenthashmap của các đối tượng khóa khối được đồng bộ hóa được tham chiếu bằng khóa duy nhất từ ​​chính đối tượng miền và được tổ chức bởi dịch vụ đơn. Khi phương thức dịch vụ được gọi là đầu tiên, hãy kiểm tra bản đồ để xem liệu có một đối tượng khóa đã có cho giá trị khóa của đối tượng miền hay không và sử dụng nó trong khối được đồng bộ hóa. Nếu đối tượng khóa không có, nó tạo ra một và lưu nó vào bản đồ. Các đối tượng phải được loại bỏ khỏi bản đồ trong một khối cuối cùng khi bạn thực hiện –

Trả lời

0

Thử khóa bi quan. Sẽ không có ngoại lệ đối với yêu cầu thứ hai, nó sẽ chỉ chặn cho đến khi lần đầu tiên kết thúc.

def controller = Controller.lock(params.id) 
controller.counter += 1 
controller.save() 
Các vấn đề liên quan