2016-05-09 19 views
18

Vorrei utilizzare PHP 7. Tuttavia non sembra esserci alcuna opzione per la memoria nella cache dei valori-chiave.Esiste una cache di memoria compatibile per PHP 7?

APC is discontinued.

XCache will not be available for PHP 7 for some time.

Esiste un'alternativa disponibile per PHP 7?

Oppure esiste un modo per utilizzare Opcache di PHP7 per implementare il caching della memoria con valori-chiave?

+2

provato con memcached? – Thamilan

+0

@Thamizhan Bene, memcached e redis sono un po 'qualcos'altro. Sto chiedendo la cache di memoria PHP, che ha una latenza molto inferiore rispetto all'utilizzo di quei due (anche su localhost). – Frodik

+0

Qual è la differenza di latenza? L'hai controllato? Non sembra una cosa di cui dovresti preoccuparti. –

risposta

23

Suggerisco di utilizzare Memcached, in particolare se si è preoccupati per le prestazioni.

Mentre siete corretto che APC (u) è molto più veloce di Memcache, non stai prendendo in conto che per il momento si sta preoccuparsi di queste metriche, si sarà in esecuzione su più server e APC (u) non può essere condiviso tra i nodi.

È possibile utilizzare una singola istanza o un cluster Memcache per servire tutti i server di applicazioni che si desidera. La scalabilità è una preoccupazione maggiore nello sviluppo di applicazioni moderne rispetto a "quanto rendimento posso spremere da un server?"

Detto questo, la tua alternativa è APCu, che ha tutte le funzionalità a cui sei abituato da APC. È contrassegnato come stabile con PHP7 ma non lo consiglierei a causa del suo carattere single-node & incapacità di funzionare correttamente con fastcgi.

+0

Grazie per la tua risposta. La nostra applicazione è molto specializzata, noi sto già usando memcache e per i motivi che hai citato, tuttavia, come ho detto, abbiamo anche bisogno di localizzare in cache centinaia di dati con valori-chiave per i quali è memcached e allo stesso modo non molto adatto Ma sono d'accordo con te e la risposta sarà essere utile per qualcuno che esegue il sito Web "ordinario". – Frodik

+2

@Frodik In questo caso, APCu è probabilmente il migliore che si otterrà (almeno senza conoscere il proprio utilizzo specifico.) Vale la pena ricordare che Memcache ha un sacco di [set multi ] (http://php.net/manual/en/memcached.setmultibykey.php) e [ottieni multi] (http://php.net/manual/en/memcached.getmultibykey.php) funzioni, che potrebbero esserti utili se tu " reimpostando quelle centinaia tutte in una volta. Ciò ti farà risparmiare il sovraccarico di più richieste. –

12

APCU è letteralmente APC senza il codice cache (hanno preso il codice APC, rimosse la cache byte-code e rilasciati come APCU). È una sostituzione drop-in. Esattamente come la cache utente di APC, mantiene i dati nello stesso processo del runtime di PHP, quindi usare il valore è come recuperare una variabile ordinaria, quindi la velocità.

+0

Beh, sì, ma APC su PHP 5.3 o superiore era tutto ma stabile :-(Quindi anche potrebbe funzionare con PHP 7, sono molto paura di soffrire anche di instabilità – Frodik

+0

Non temere, ma provalo APCu è tutto ciò che potrebbe essere necessario oltre a nativo zend opcache integrato, ed è molto stabile – Spooky

3

Un altro approccio (che non ho provato, ma sembra molto interessante) è quello di sfruttare opcache come cache dei valori chiave. Questo post graphiq contiene più dettagli ma purtroppo nessun codice reale (e si noti i commenti di Kerry Schwab).

Il primo è assicurarsi che l'opcache sia abilitato e abbia abbastanza memoria allocata per i dati che è necessario memorizzare nella cache e quindi qualcosa sulla falsariga di quanto segue (sollevato dall'articolo, verificarlo per esteso) . La scadenza della cache (oltre alla cancellazione manuale) dovrebbe essere gestita anche, ma non sarebbe difficile da aggiungere (ad esempio, avvolgere i dati in un oggetto contenente con una scadenza e controllarli nel tuo cache_get, eliminando e ignorando il record se è scaduto).

function cache_set($key, $val) { 
    $val = var_export($val, true); 
    // HHVM fails at __set_state, so just use object cast for now 
    $val = str_replace('stdClass::__set_state', '(object)', $val); 
    // Write to temp file first to ensure atomicity 
    $tmp = "/tmp/$key." . uniqid('', true) . '.tmp'; 
    file_put_contents($tmp, '<?php $val = ' . $val . ';', LOCK_EX); 
    rename($tmp, "/tmp/$key"); 
} 

function cache_get($key) { 
    @include "/tmp/$key"; 
    return isset($val) ? $val : false; 
} 

causa della opcache questo funzioni come nella memoria cache, ma evita il sovraccarico di serializzazione e deserializzazione. Immagino che il cache_set dovrebbe anche chiamare opcache_invalidate durante la scrittura (e nella funzione cache_delete che non esiste nei loro esempi) ma altrimenti sembra un suono per una cache che non ha bisogno di essere condivisa tra i server.

Modifica: un'implementazione di esempio con scadenza cache (solo precisione su un secondo, potrebbe utilizzare microtime(true) se è richiesta una maggiore precisione) di seguito. I test minimi hanno effettivamente funzionato e ho abbandonato la sostituzione specifica HHVM, quindi YMMV. Suggerimenti per miglioramenti graditi.

class Cache {                 
    private $root;                
    private $compile;               
    private $ttl;                

    public function __construct($options = []) {         
     $this->options = array_merge(           
      array(                
       'root' => sys_get_temp_dir(),         
       'ttl' => false,             
      ),                 
      $options                
     );                  
     $this->root = $this->options['root'];         
     $this->ttl = $this->options['ttl'];          
    }                   

    public function set($key, $val, $ttl = null) {        
     $ttl = $ttl === null ? $this->ttl : $ttl;        
     $file = md5($key);              
     $val = var_export(array(            
      'expiry' => $ttl ? time() + $ttl : false,       
      'data' => $val,              
     ), true);                

     // Write to temp file first to ensure atomicity       
     $tmp = $this->root . '/' . $file . '.' . uniqid('', true) . '.tmp';  
     file_put_contents($tmp, '<?php $val = ' . $val . ';', LOCK_EX);   

     $dest = $this->root . '/' . $file;          
     rename($tmp, $dest);              
     opcache_invalidate($dest);            
    }                   

    public function get($key) {             
     @include $this->root . '/' . md5($key);         

     // Not found                
     if (!isset($val)) return null;           

     // Found and not expired             
     if (!$val['expiry'] || $val['expiry'] > time()) return $val['data'];  

     // Expired, clean up              
     $this->remove($key);              
    }                   

    public function remove($key) {            
     $dest = $this->root . '/' . md5($key);         
     if (@unlink($dest)) {             
      // Invalidate cache if successfully written       
      opcache_invalidate($dest);           
     }                  
    }                   
}