2010-04-14 34 views
13

Tôi đang sử dụng Cache trong một phương pháp dịch vụ web như thế này:Sử dụng 'HttpContext.Current.Cache' một cách an toàn

var pblDataList = (List<blabla>)HttpContext.Current.Cache.Get("pblDataList"); 

if (pblDataList == null) 
{ 
    var PBLData = dc.ExecuteQuery<blabla>(@"SELECT blabla"); 

    pblDataList = PBLData.ToList(); 

    HttpContext.Current.Cache.Add("pblDataList", pblDataList, null, 
     DateTime.Now.Add(new TimeSpan(0, 0, 15)), 
     Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); 
} 

Nhưng tôi tự hỏi, là mã này thread-an toàn không? Phương thức dịch vụ web được gọi bởi nhiều người yêu cầu. Và sau đó, một người yêu cầu có thể tìm cách lấy dữ liệu và thêm vào số Cache cùng lúc trong khi bộ nhớ cache trống.

Truy vấn mất từ ​​5 đến 8 giây. Sẽ giới thiệu một tuyên bố khóa xung quanh mã này ngăn chặn bất kỳ xung đột có thể có? (Tôi biết rằng nhiều truy vấn có thể chạy đồng thời, nhưng tôi muốn chắc chắn rằng chỉ có một truy vấn đang chạy cùng một lúc.)

Trả lời

22

Đối tượng bộ nhớ cache an toàn chủ đề nhưng HttpContext.Current sẽ không có sẵn trong chủ đề nền. Điều này có thể hoặc không áp dụng cho bạn ở đây, không rõ ràng từ đoạn mã của bạn cho dù bạn có đang sử dụng các chủ đề nền hay không, nhưng trong trường hợp bạn đang có hoặc quyết định vào một thời điểm nào đó trong tương lai, bạn nên ghi nhớ điều này .

Nếu có bất kỳ cơ hội nào bạn cần truy cập bộ nhớ cache từ chuỗi nền, hãy sử dụng HttpRuntime.Cache để thay thế.

Ngoài ra, mặc dù các hoạt động riêng lẻ trên bộ nhớ cache có chủ đề an toàn, hoạt động tra cứu/lưu trữ tuần tự rõ ràng không phải là nguyên tử. Dù bạn có cần chúng là nguyên tử hay không tùy thuộc vào ứng dụng cụ thể của bạn. Nếu nó có thể là một vấn đề nghiêm trọng cho cùng một truy vấn chạy nhiều lần, tức là nếu nó tạo ra nhiều tải hơn cơ sở dữ liệu của bạn có thể xử lý, hoặc nếu nó là vấn đề yêu cầu trả về dữ liệu bị ghi đè ngay lập tức cache, sau đó bạn có thể muốn đặt một khóa xung quanh toàn bộ khối mã.

Tuy nhiên, trong hầu hết các trường hợp, bạn thực sự muốn cấu hình trước và xem liệu đây có thực sự là vấn đề hay không. Hầu hết các ứng dụng/dịch vụ web không quan tâm đến khía cạnh này của bộ nhớ đệm vì chúng là trạng thái không trạng thái và không quan trọng nếu bộ nhớ cache bị ghi đè.

+0

Tôi không sử dụng các chủ đề nền, nó chỉ là các cuộc gọi dịch vụ web. Nhân tiện, cảm ơn. –

2

Bạn là chính xác. Các hoạt động truy xuất và bổ sung không được coi là một giao dịch nguyên tử. Nếu bạn cần ngăn truy vấn chạy nhiều lần, bạn sẽ cần sử dụng khóa.

(Thông thường điều này sẽ không có nhiều của một vấn đề, nhưng trong trường hợp của một truy vấn chạy dài nó có thể hữu ích để giảm căng thẳng cho cơ sở dữ liệu.)

+2

Điều này thực sự phụ thuộc. Trong môi trường thông lượng cao, tải bổ sung trên cơ sở dữ liệu có thể không phải là một thỏa thuận lớn khi yêu cầu-điều chỉnh kết quả từ loại khóa này.Trong hầu hết các trường hợp * tôi muốn nói rằng bạn nói đúng, nhưng mỗi trường hợp phải được đánh giá riêng lẻ. – Aaronaught

+0

Điểm tốt. Tôi hơi lặp lại câu trả lời của tôi vì điều này. – Greg

1

Tôi tin rằng Add nên được thread-safe - tức là nó sẽ không lỗi nếu Add được gọi hai lần với cùng một khóa, nhưng rõ ràng truy vấn có thể thực hiện hai lần.

Một câu hỏi khác, tuy nhiên, là là luồng dữ liệu an toàn. Không có gì đảm bảo rằng mỗi List<blabla> bị cô lập - nó phụ thuộc vào nhà cung cấp bộ nhớ cache. Nhà cung cấp bộ nhớ đệm trong bộ nhớ lưu trữ trực tiếp các đối tượng, do đó có nguy cơ va chạm nếu có bất kỳ chủ đề nào chỉnh sửa dữ liệu (thêm/xóa/hoán đổi các mục trong danh sách hoặc thay đổi các thuộc tính của một trong các mục). Tuy nhiên, với nhà cung cấp serializing, bạn sẽ vẫn ổn. Tất nhiên, điều này sau đó yêu cầu rằng blabla có thể được tuần tự hóa ...

+0

Bạn có thể chia sẻ liên kết để tuần tự hóa đối tượng của bạn cho bộ nhớ cache không? Tôi đã cố gắng để cache một bảng dữ liệu tại nơi làm việc cho một màn hình web để lọc một số dữ liệu. Tôi đã nói với tải máy chủ sẽ được nhiều. Bạn có biết bất kỳ bài viết nào nói về bộ nhớ đệm và tuần tự hóa cũng như tải trên máy chủ không? Tôi không thể tìm thấy bất kỳ điều gì cụ thể trong khi Googling. –

+0

@kcbeard trước tiên, khi được lưu trong bộ nhớ cache: ** không thay đổi ** một 'DataTable'. Bây giờ đó là cách thức: dữ liệu lớn đến mức nào? Khối lượng hàng nào? –

+0

Mọi nơi từ vài trăm hàng đến tối đa 5k. Một tá cột có kiểu dữ liệu ngày tháng, int và var-char. Cảm giác thông thường nói với tôi không sử dụng trạng thái xem và SO đã sao lưu tôi. Tôi đã được một giả định chỉ có một vài người dùng cho mỗi trường hợp ứng dụng sẽ được truy cập vào nó vì vậy lúc đầu tôi sử dụng Current.Session, sau đó nó đã được đưa lên tải máy chủ được nhiều vì vậy tôi nghĩ Current.Cache (ứng dụng rộng). Tôi có nghĩa là có thể một thủ tục lưu trữ đủ linh hoạt để đối phó với tất cả các bộ lọc sẽ là con đường tốt nhất. Nhưng một trong hai cách tôi muốn biết thêm về bộ nhớ đệm bảo mật, thực hành tốt nhất, cạm bẫy vv. –

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