PHP karşılıklı dışlama (mutex)

6 Cevap php

Read some texts about locking in PHP.
They all, mainly, direct to http://php.net/manual/en/function.flock.php .

Bu sayfa sabit diskteki bir dosyayı açarken bahsediyor!

Gerçekten öyle mi? Yani, bu gerçekten pahalı kilitleme yapar - bu) Ben sabit diske erişmek gerekecek ben kilitlemek istediğiniz her zaman gelir =

Artık keyifli bir haber beni teselli edebilir?

Edit:

Due to some replies I've got here, I want to ask this;
My script will run only by one thread, or several? Because if it's by one then I obviously don't need a mutex. Is there a concise answer?

What exactly I'm trying to do

Asked by ircmaxell.
This is the story:

I have two ftp servers. I want to be able to show at my website how many online users are online.
So, I thought that these ftp servers will "POST" their stats to a certain PHP script page. Let's assume that the URL of this page is "http://mydomain.com/update.php".

Web sitesinin ana sayfasında ("http://mydomain.com/index.php") ben kümülatif istatistikleri (çevrimiçi kullanıcılar) gösterecektir.

İşte bu.

My problem is that I'm not sure if, when one ftp server updates his stats while another does it too, the info will get mixed.
Like when multi-threading; Two threads increase some "int" variable at the same time. It will not happen as expected unless you sync between them.
So, will I have a problem? Yes, no, maybe?

Possible solution

Thinking hard about it all day long, I have an idea here and I want you to give your opinion.
As said these ftp servers will post their stats, once every 60sec.
I'm thinking about having this file "stats.php".
It will be included at the updating script that the ftp servers go to ("update.php") and at the "index.php" page where visitors see how many users are online.
Now, when an ftp server updates, the script at "update.php" will modify "stats.php" with the new cumulative statistics.
First it will read the stats included at "stats.php", then accumulate, and then rewrite that file.

Yanılmıyorsam eğer PHP dosyası ("stats.php") değiştirilir algılamak ve yeni bir yük olacaktır. Düzeltin?

6 Cevap

Eh, PHP (çoğu birkaç diş uygulamaları vardır) farklı bir işlem alanında çalışır. Kolay bir akın ediyor. Bu, tüm platformlar üzerinde çalışmak için garantisi yoktur.

Eğer destek derleme Ancak, bu tür Semaphore uzantısı gibi birkaç başka şeyler kullanabilirsiniz. (Ile Derleme PHP - enable-sysvsem). Sonra (engellemelisiniz not, sem_acquire () Ama nedense, bu yanlış dönecektir edemez.), Gibi bir şey yapabilirsiniz:

$sem = sem_get(1234, 1);
if (sem_acquire($sem)) {
    //successful lock, go ahead
    sem_release($sem);
} else {
    //Something went wrong...
}

Eğer varsa diğer seçenekler, MySQL user level locks GET_LOCK('name', 'timeout'), ya da APC veya XCache (Not gibi bir şey kullanarak kendi oluştururken, bu, gerçek bir kilit olmaz çünkü yarış koşulları olabilir başkası) check ve kilit kabulü arasında bir kilit alır nerede oluşturulur.

Edit: To answer your edited question:

Bu, tüm sunucu yapılandırmasına bağlıdır. PHP (her isteğini farklı bir iş parçacığı tarafından sunulmaktadır) multi-threaded çalışabilir miyim, ya da çoklu-işlem (her isteği farklı bir işlem tarafından sunulmaktadır) çalıştırmak olabilir. Bu, tüm sunucu yapılandırmasına bağlıdır ...

PHP tüm istekleri hizmet veren tek bir süreç (ve bir iş parçacığı) ile, seri, tüm isteklere hizmet edeceğini çok nadirdir. CGI kullanıyorsanız, o zaman varsayılan olarak multi-süreç. Eğer FastCGI kullanıyorsanız, bu çoklu-işlem ve multi-thread olasıdır. Apache ile mod_php kullanıyorsanız, o zaman işçi türüne bağlıdır:

  1. mpm_worker ServerLimit değişkeni tarafından dikte süreçlerin sayısı ile, çoklu-işlem ve multi-thread hem de olacaktır.
  2. prefork çok işlem olacak
  3. perchild yanı sıra çoklu süreç olacaktır

Edit: To answer your second edited question:

Bu oldukça kolay. Bir dosyada saklayın:

function readStatus() {
    $f = fopen('/path/to/myfile', 'r');
    if (!$f) return false;
    if (flock($f, LOCK_SH)) {
        $ret = fread($f, 8192);
        flock($f, LOCK_UN);
        fclose($f);
        return $ret;
    }
    fclose($f);
    return false;
}

function updateStatus($new) {
    $f = fopen('/path/to/myfile', 'w');
    if (!$f) return false;
    if (flock($f, LOCK_EX)) {
        ftruncate($f, 0);
        fwrite($f, $new);
        flock($f, LOCK_UN);
        fclose($f);
        return true;
    }
    fclose($f);
    return false;
}

function incrementStatus() {
    $f = fopen('/path/to/myfile', 'rw');
    if (!$f) return false;
    if (flock($f, LOCK_EX)) {
        $current = fread($f, 8192);
        $current++;
        ftruncate($f, 0);
        fwrite($f, $current);
        flock($f, LOCK_UN);
        fclose($f);
        return true;
    }
    fclose($f);
    return false;
}

Eğer parçacığı ihtiyacınız varsa, ciddi, yanlış dil kullanarak ediyoruz.

PHP çoklu desteklemiyor, her isteği (ve dolayısıyla her PHP script) (PHP çalışacak şekilde bağlı hatta süreci) sadece tek bir iş parçacığı içinde idam edilecek.

Soru: Eğer FTP sunucuları update.php dosyasına POST ile bastırıyorlar istatistikler nerede saklayacak? Bu ikinci yazı ircmaxell daha yerel bir dosya, eğer seni yanıtladı. Siz de bir Muteksleri ile yapabilirsiniz - semafor işlevleri. Başka bir çözüm istatistikleri depolamak ve update info_table set value = value + 1 gibi bir şey kullanmak için MySQL MyISAM tablo kullanmaktır. Bu tabloyu kilitlemek ve isteklerinizi serialize ve hiçbir sorun olmalıdır ve olacaktır.

Evet PHP, Apache tarafından işletilen gibi bu, doğru, ve (çeşitli işçi modeli bakınız) iyi gördüğü gibi Apache yürütme konuları organize edebilirsiniz. Bir seferde bir kaynak bir erişmek istiyorsanız, (örneğin cron işleri ile ilgili ise iyi olduğu) bir dosyaya, kilit, ya sen, veritabanı işlem mekanizması, ASİT özellikleri ve veritabanı kaynakları kilitleme güveniyor veri ile ilgili ise.

Neden sadece gelen ftp sunucusu ipadresi dayalı bir dosya için güncelleme dosyası yazmak zorunda değilsiniz. Ve istatistikler php dosya sadece okumak ve birlikte hem bu dosyaların sayısal içeriğini ekleyin.