2013-08-02 29 views
7

trong máy chủ của tôi/server.jsMeteor: Điều kiện chủng tộc có thể xảy ra với Meteor.collections ở phía máy chủ không?

Meteor.methods({ 
    saveOnServer: function() { 
     var totalCount = Collections.find({ 
      "some": "condition" 
     }).count(); 
     if (totalCount) { 
      var customerId = Collections.update('someId', { 
       "$addToSet": { 
        objects: object 
       } 
      }, function(err) { 
       if (err) { 
        throw err; 
       } else { 
        return true; 
       } 
      }); 
     } else {} 
    } 
}); 

Tôi sợ rằng khi saveOnServer() được gọi bởi 2 khách hàng cùng một lúc, nó sẽ trả lại TOTALCOUNT tương tự cho từng khách hàng và về cơ bản kết thúc chèn cùng số nguyên vào id đối tượng. Mục tiêu cuối cùng là chèn hàng ở phía máy chủ với một hoạt động nguyên tử chỉ hoàn thành khi totalCount được trả về thành công và tài liệu được chèn vào để đảm bảo rằng không có id trùng lặp nào tồn tại? Tôi đang cố gắng không sử dụng mongodb _id nhưng có cột số nguyên incrementing id của riêng tôi.

Tôi tự hỏi làm cách nào để đảm bảo rằng trường được tự động tăng cho mỗi thao tác chèn? Tôi hiện đang dựa vào việc nhận tổng số tài liệu. Là một điều kiện chủng tộc có thể ở đây? Nếu vậy, cách sao băng đối phó với điều này là gì?

+0

về nguyên tắc, mã sao băng quá xa dữ liệu để đảm bảo điều này. bạn nên sử dụng các công cụ dbms để xác thực như vậy. – dandavis

+1

ở phía máy chủ tất cả mọi thứ là đồng bộ ngay để tránh địa ngục gọi lại bằng cách sử dụng nút-sợi? Nhưng meteor.collection quản lý mongodb, là có một cách để đảm bảo một đối tượng meteor.collection sẽ được nguyên tử hoặc chủng tộc điều kiện miễn phí? – KJW

+1

Cùng một câu hỏi ở đây và trả lời http://stackoverflow.com/questions/15886833/how-can-i-create-an-auto-increment-field-on-meteor. Mã của bạn không phải là vấn đề trừ khi bạn đang chạy trên nhiều máy chủ. – user728291

Trả lời

9

Trong mô hình đồng thời của Meteor, bạn có thể tưởng tượng toàn bộ phương thức như một khối liên tục của những thứ xảy ra. Để Meteor chuyển từ chạy một phương thức ở giữa để nói, bắt đầu một phương thức khác, bạn cần "hiệu suất" - phương thức cần phải báo hiệu "Tôi có thể bị gián đoạn".

Phương pháp sinh lợi bất cứ khi nào chúng làm điều gì đó không đồng bộ, trong thực tế có nghĩa là bất cứ khi nào bạn cập nhật cơ sở dữ liệu hoặc gọi phương thức có gọi lại trong Meteor 0.6.5 trở lên. Vì bạn gọi cho số update gọi lại, Meteor sẽ luôn luôn cố gắng thực hiện điều gì đó giữa cuộc gọi đến update và cuộc gọi lại của update. Tuy nhiên, trong Meteor 0.6.4.2 và trước đó, các cập nhật cơ sở dữ liệu không bị gián đoạn bất kể việc sử dụng callbacks.

Tuy nhiên, nhiều cuộc gọi đến saveOnServer sẽ diễn ra theo thứ tự và không gây ra tình trạng chạy đua. Bạn có thể gọi this.unblock() để cho phép nhiều cuộc gọi đến saveOnServer xảy ra "đồng thời" — tức là., Không chia sẻ cùng một hàng đợi, được gắn nhãn saveOnServer queue, của các khối nội dung không gián đoạn.

Với mã bạn có, phương pháp khác sửa đổi Collections có thể thay đổi giá trị count() giữa cuộc gọi và cập nhật.

Bạn có thể ngăn một phương pháp từ làm cho giữa chừng không hợp lệ khác bằng cách thực hiện các mô hình dữ liệu sau:

saveOnServer : function() { 
// ... 
    Collections.update({_id:someId, initialized:true, collectionCount: {$gt: 0}}, 
    {$addToSet: {objects: object}}); 
///... 
} 

Khi thêm đối tượng để Collections:

insertObject: function() { 
//... 
    var count = Collections.find({some: condition}).count(); 
    Collections.insert({_id:someId, initialized:false, collectionCount: count}); 
    Collections.update({initialized:false}, 
    {$set:{initialized:true}, $inc: {collectionCount: 1}}); 
} 

Lưu ý, trong khi điều này có vẻ không hiệu quả, nó phản ánh chi phí chính xác của việc cập nhật và chèn vào các phương thức khác nhau theo cách bạn dự định. Trong saveOnServer bạn không thể chèn.

Ngược lại, nếu bạn đã xóa cuộc gọi lại khỏi Collections.update, nó sẽ xảy ra đồng bộ và sẽ không có điều kiện chủng tộc Meteor 0.6.5 trở lên.

+3

Nó sẽ chỉ xảy ra theo thứ tự nếu bạn chỉ sử dụng 1 máy chủ. Nếu bạn 2+ máy chủ tôi nghĩ rằng bạn sẽ có điều kiện chủng tộc trên mongodb viết. – gabrielhpugliese

+0

Kiểm tra ghi chú của tôi để làm rõ khi tôi hiểu mã Meteor tốt hơn. – DoctorPangloss

+0

Đã thêm ghi chú mới. Ý kiến ​​của tôi về việc gọi lại để 'cập nhật 'không chính xác cho đến khi 0.6.5 – DoctorPangloss

1

Bạn có thể làm cho bộ sưu tập này có một chìa khóa duy nhất trên một lĩnh vực chỉ mục, và sau đó tiếp tục nó được cập nhật như sau:

1) Bất cứ khi nào bạn chèn vào bộ sưu tập, lần đầu tiên làm một truy vấn để có được chỉ số tối đa và chèn tài liệu có chỉ mục + 1.

2) Để tìm hiểu số tài liệu chỉ cần thực hiện truy vấn để nhận được tối đa chỉ mục.

Chèn bây giờ là một cặp truy vấn, đọc và viết, để nó có thể thất bại. (DB ops luôn luôn có thể thất bại, mặc dù.) Tuy nhiên, nó có thể không bao giờ để cơ sở dữ liệu ở trạng thái không nhất quán - chỉ số Mongo sẽ đảm bảo điều đó.

Cú pháp để xây dựng một chỉ số trong Meteor là thế này:

MyCollection._ensureIndex('index', {unique: 1}); 
1

Một cách khác để làm điều này là từ một hibernate cơ chế/JPA sau - và đó là để thiết lập một lĩnh vực va chạm. Hầu hết thời gian, đây có thể là dấu thời gian cập nhật được đặt trên mỗi bản cập nhật. Ngay trước khi thực hiện bất kỳ cập nhật nào, hãy truy vấn dấu thời gian cập nhật. Sau đó, bạn có thể chỉ định cập nhật nơi dấu thời gian cập nhật là những gì bạn vừa tìm nạp. Nếu nó đã thay đổi trong thời gian tạm thời, bản cập nhật sẽ không xảy ra - và bạn kiểm tra mã trả về/đếm rằng hàng đã được cập nhật hay chưa. JPA thực hiện điều này tự động cho bạn khi bạn thêm chú thích cho trường va chạm này - nhưng về cơ bản những gì nó làm ở hậu trường

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