2008-10-20 24 views
5

Một phần của ứng dụng web mới nhất của tôi cần viết để ghi số tiền hợp lý như một phần của quá trình ghi nhật ký. Một vấn đề mà tôi đã nhận thấy là nếu có một vài người dùng đồng thời, ghi có thể ghi đè lên nhau (thay vì phụ thêm vào tệp). Tôi cho rằng điều này là do tệp đích có thể được mở ở một số địa điểm cùng một lúc.Khóa các tệp NFS trong PHP

flock(...) thường là tuyệt vời nhưng dường như không hoạt động trên NFS ... Đó là vấn đề lớn đối với tôi khi máy chủ sản xuất sử dụng mảng NFS.

Điều gần nhất tôi đã nhìn thấy một giải pháp thực tế liên quan đến việc cố gắng tạo một thư mục khóa và chờ cho đến khi nó có thể được tạo. Để nói điều này thiếu sự thanh lịch là understatement của năm, có thể thập kỷ.

Bất kỳ ý tưởng nào tốt hơn?

Chỉnh sửa: Tôi nên thêm rằng tôi không có gốc trên máy chủ và lưu trữ theo cách khác không thực sự khả thi bất kỳ lúc nào, ít nhất là trong thời hạn của tôi.

Trả lời

2

Một lỗi bẩn khác sẽ là flock() tệp "cục bộ" và chỉ mở/ghi vào tệp NFS nếu bạn giữ khóa trên tệp cục bộ.

Chỉnh sửa: từ flock() page:

bầy() sẽ không hoạt động trên NFS và nhiều hệ thống tập tin mạng khác. Kiểm tra tài liệu hệ điều hành của bạn để biết thêm chi tiết.

Chỉnh sửa 2:

Tất nhiên có luôn sử dụng cơ sở dữ liệu để synchonise truy cập (tôi giả sử ứng dụng của bạn sử dụng một db). Đây sẽ là một hit khá hiệu quả nếu bạn đang thực hiện rất nhiều việc đăng nhập.

Nếu chỉ để ghi nhật ký, bạn có thực sự cần tệp nhật ký tập trung không? Bạn có thể đăng nhập cục bộ (và thậm chí kết hợp các bản ghi khi họ xoay vào cuối ngày nếu cần)?

+0

Hiện tại, điều đó sẽ ổn, nhưng một khi điều này không còn phát triển, nó sẽ được trải rộng trên một số máy chủ ảo để cân bằng tải và có thể ném cờ lê [nother] trong công trình. – Oli

3

Một cách tiếp cận có thể là thiết lập một phiên bản Memcache, được chia sẻ giữa mỗi máy chủ ảo của bạn. Bạn có thể ape flock() bằng cách đặt một mục nhập của tên tệp vào bộ nhớ cache khi bạn bắt đầu các thao tác tệp cục bộ và xóa nó khi hoàn tất.

Mỗi máy chủ có thể truy cập hồ bơi này trước khi thao tác với tệp và xem liệu "khóa" này có tồn tại hay không, ví dụ:

// Check for lock, using $filename as key 
$lock = $memcache->get($filename); 

if(!$lock) { 
    // Set lock in memcache for $filename 
    $memcache->set($filename, 1); 

    // Do file operations... 

    // Blow away "lock" 
    $memcache->delete($filename); 
} 

Không phải là giải pháp thanh lịch nhất, nhưng sẽ cho phép bạn kiểm soát khóa từ tất cả các máy chủ trong thiết lập của bạn một cách dễ dàng.

0

Chỉ nên sử dụng memcache thêm và tránh điều kiện đua.

if ($memcache->add($filename, 1, 1)) 
{ 
    $memcache->delete($filename); 
} 
1

Mặc dù bạn không thể đổ() các tập tin trên NFS và I/O có thể asynchroneous, hoạt động thư mục trên NFS nguyên tử. Điều đó có nghĩa là tại bất kỳ thời điểm nào, một thư mục có hoặc không tồn tại.

Để thực hiện tính năng khóa NFS của riêng bạn, hãy kiểm tra hoặc tạo thư mục khi bạn muốn khóa và xóa thư mục khi bạn hoàn tất.

Thật không may, nó có thể không tương thích với bất kỳ ứng dụng nào khác mà bạn không tự viết.

14

hoạt động Directory KHÔNG nguyên tử dưới NFSv2 và NFSv3 (vui lòng tham khảo các cuốn sách 'NFS Illustrated' bởi Brent Callaghan, ISBN 0-201-32570-5; Brent là một NFS-kỳ cựu tại Sun).

NFSv2 có hai hoạt động nguyên tử:

  • liên kết tượng trưng
  • đổi tên

Với NFSv3 create cuộc gọi cũng là nguyên tử.

Biết được điều này, bạn có thể thực hiện spin-ổ khóa cho các tập tin và thư mục (trong vỏ, không PHP):

khóa thư mục hiện hành:

while ! ln -s . lock; do :; done 

khóa một tập tin:

while ! ln -s ${f} ${f}.lock; do :; done 

mở khóa (giả định, quá trình chạy thực sự có được khóa):

unlock dir hiện tại:

mv lock deleteme && rm deleteme 

unlock một tập tin:

mv ${f}.lock ${f}.deleteme && rm ${f}.deleteme 

Remove cũng không phải là nguyên tử, do đó đầu tiên đổi tên (mà là nguyên tử) và sau đó loại bỏ.

Đối với liên kết tượng trưng và đổi tên, cả hai tên tệp phải nằm trên cùng một hệ thống tệp. Đề xuất của tôi: chỉ sử dụng tên tệp đơn giản và đặt tệp và khóa vào cùng một thư mục.

+0

Những nhận xét trên trang hướng dẫn sử dụng đàn có liên quan và tôi thấy chúng khá hữu ích. http://www.php.net/manual/en/function.flock.php#46085 http://www.php.net/manual/en/function.flock.php#68875 http: //www.php.net/manual/en/function.flock.php#82521 – aiham

2

Bạn cũng có thể sử dụng dio_fcntl() để khóa tệp trên ổ đĩa NFS. Nó đòi hỏi gói dio, có thể không phải là một phần của cài đặt php của bạn theo mặc định.

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