Cache leeren für Backend User

Damit einem Redakteur das Löschen des Caches ermöglicht werden kann, müssen folgende zwei Zeilen in das Usergroup/User-Setup eingefügt werden:

options.clearCache.pages = 1 
options.clearCache.all = 1

Caching kurzlebiger Inhalte (z.B. News)

Ein typischer Fall, in dem Kunden und Entwickler das Caching von TYPO3 bisher verfluchten, war die Nutzung eines Plugins wie tt_news, bei dem sich die anzuzeigenden Datensätze zwar geändert hatten, die Aktualisierung des Caches aber erst nach Ablauf dessen Gültigkeitszeitraums  erfolgte. (Die Möglichkeit, generell den Cache zu deaktivieren, ist böse und wir daher nicht näher betrachtet). Über die Einstellung TCEMAIN.clearCacheCmd auf der Seite, die die Datensätze enthält, ließ sich zwar der Cache einzelner (oder aller) Seiten bei Änderungen invalidieren, jedoch ist dies nicht wirklich sinnvoll und praktikabel:

  • Man muss entweder die Liste der Seiten-IDs pflegen oder mittels „all“ den Cache aller Seiten lsöchen, unahängig davon, ob das Plugin dort überhaupt eingesetzt ist.
  • Man löscht stets den Cache der gesamten Seite, obwohl sich ja nur ein Inhaltselement aktualisieren soll.

Ende Februar hatte Fabrizio in seinem Blog eine Idee vorgestellt, wie auf Contentelement-Ebene ein individuelleres Caching ermöglicht werden könnte. Diese stieß auf viel Interesse und schaffte es schnell in den TYPO3-Core (4.7), auch ein Backport in 4.5 und 4.6 ist vorgesehen.

Weiterlesen»

Caching Framework nutzen

Für umfangreichere Datenkonstrukte, die häufig verwendet werden oder aber aufwändig zu erzeugen sind, ist ein Cache nützlich. Ein typischer Fall sind Dateilisten, die sich auf Verzeichnissen generieren (z.B. für eine einfache Bildergalerie). Die Inhalte der Verzeichnisse ändern sich meist nur extrem selten – wozu also immer wieder aufs Neue via Dateisystem auslesen, welche Dateien existieren? Hier ist es doch naheliegender, die Liste zu cachen und nur selten oder gar nur via gezielter Anforderung zu aktalisieren.
Einen von vielen Fällen, wo das Caching Framework in einer eigenen Extension zum Einsatz kommen kann…

Weiterlesen»

Caching Framework in Extensions

Extensions sollten um horizontal zu skalieren, Caches nicht in eigens gebauten $_SESSION Arrays oder Temporaeren SQL Tabellen halten, sondern das ab TYPO3 4.3.0 eingebaute und ab 4.3.1 vollstaendig umgesetzte Caching Framework (ein Backport aus der FLOW3 Entwicklung) verwenden.

Ein guter Artikel ist:

Bei der Entwicklung der Extensions ist natuerlich darauf zu achten, dass diese in der Form auch erst ab 4.3.1 korrekt arbeiten, und auf aelteren Installationen nicht funktionieren werden.

In kurzen Auszuegen:
In die ext_localconf.php folgendes hinzufuegen, wenn Memcached verwendet werden soll:

// If cache is not already defined, define it
if (!is_array($TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['my_extension'])) {
   $TYPO3_CONF_VARS['SYS']['caching'] ['cacheConfigurations']['my_extension'] = array(
      'backend' => 't3lib_cache_backend_MemcachedBackend', 'options' => array( 'servers' => array('localhost:11211'), ))
   );
}

In der Extension muss das cache Object erzeugt und initialisiert werden:

if (TYPO3_UseCachingFramework) {
   // Create the cache
   try {
      $GLOBALS['typo3CacheFactory']->create(
         'my_extension',
         't3lib_cache_frontend_VariableFrontend',
         $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['my_extension']['backend'],
         $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['my_extension']['options']
      );
   } catch(t3lib_cache_exception_DuplicateIdentifier $e) {
      // do nothing, the cache already exists
   }
   // Initialize the cache
   try {
      $this->cache = $GLOBALS['typo3CacheManager']->getCache(
         'my_extension'
      );
   } catch(t3lib_cache_exception_NoSuchCache $e) {
      // Unable to load
   }
}

Um jetzt mit dem Cache arbeiten zu koennen sind folgende Methoden vorhanden:

$this->cache->has($id);
$this->cache->get($id);
$this->cache->set($id, $content, $tags, $lifetime);

Um id, content, tags und lifetime muss man sich selber kuemmern…

Bei MemcacheBackend gilt zu beachten: Idealerweise keine $id laenger als 255 Byte und idealerweise keinen $content mit mehr als 1MByte … das TYPO3 Caching Framework bricht diese Grenzwerte zwar auf, allerdings ist die Performance dann so im Keller, dass man den Zwischenspeicher auch gleich auf Pergament schreiben kann.

Server mit memcached, php-memcache und aktiviertem TYPO3 (>4.3.0) Caching Framework

memcached ist perfekt zum cachen eigener Inhalte. Damit der Server damit ausgeruestet ist:

apt-get install memcached

Ist ein Server mit mehr als 2 Kernen ausgestattet, sollte das threaded Paket installiert.

Der memcached sollte den freien RAM vollstaendig ausnutzen (nicht ueberbuchen, damit’s nicht ins SWAP geht).
Die Speichermenge kann in

/etc/memcached.conf

eingestellt werden.

PHP kann eine API anbieten (die Applikationen muessen sich aber schon selbstaendig um die Verwendung und Organisation des Caches kuemmern: z.B. TYPO3 Extensions koennen vom TYPO3 Core Caching Framework via memcache profitieren )

Um die PHP Erweiterung zu installieren:

apt-get install php5-dev
pecl install memcache-3.0.6

Ideale PHP Werte in

/etc/php5/conf.d/memcache.ini

sind

[memcache]
memcache.dbpath="/var/lib/memcache"
memcache.maxreclevel=0
memcache.maxfiles=0
memcache.archivememlim=0
memcache.maxfilesize=0
memcache.maxratio=0
memcache.protocol=ascii

… ergaenzend fuer TYPO3, ausgelagert in

/etc/php5/conf.d/t3memcache.ini

ist folgendes von Vorteil

memcache.allow_failover=1
memcache.chunk_size=32768
memcache.default_port=11211
memcache.hash_function=fnv
memcache.hash_strategy=consistent
memcache.max_failover_attempts=20

Das „binary“ Protokoll wird von PHP nicht vollstaendig unterstuetzt, daher muss „ascii“ als sehr parser-intensives und langsameres Protokoll verwendet werden.

Damit TYPO3 vom memcache profitiert, folgende Einstellungen in der localconf.php vornehmen:

// ----- Caching with MemCache 4.3 only ----
$TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations'] = array (
    'cache_hash' => array(
	'frontend' => 't3lib_cache_frontend_VariableFrontend',
	'backend' => 't3lib_cache_backend_MemcachedBackend',
	'options' => array(
	    'servers' => array('tcp://localhost:11211'),
	)
    ),
    'cache_pages' => array(
	'frontend' => 't3lib_cache_frontend_VariableFrontend',
	'backend' => 't3lib_cache_backend_MemcachedBackend',
	'options' => array(
	    'servers' => array('tcp://localhost:11211'),
	)
    ),
    'cache_pagesection' => array(
	'frontend' => 't3lib_cache_frontend_VariableFrontend',
	'backend' => 't3lib_cache_backend_MemcachedBackend',
	'options' => array(
	    'servers' => array('tcp://localhost:11211'),
	)
    ),
);
$TYPO3_CONF_VARS['SYS']['useCachingFramework'] = '1';
// ----- /Caching with MemCache 4.3 only----

hier eine aktualisierte Version, die nicht das komplette cacheConfigurations Array ueberschreibt (danke fuer den Hinweis, Steffen).

 
// ----- Caching with MemCache - doesn't overwrite cacheConfigurations array completely -----
$TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['cache_hash'] = array(
	'frontend' => 't3lib_cache_frontend_VariableFrontend',
	'backend' => 't3lib_cache_backend_MemcachedBackend',
	'options' => array(
		'servers' => array('tcp://localhost:11211')
	)
);
$TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['cache_pages'] = array(
	'frontend' => 't3lib_cache_frontend_VariableFrontend',
	'backend' => 't3lib_cache_backend_MemcachedBackend',
	'options' => array(
		'servers' => array('tcp://localhost:11211')
	)
);
$TYPO3_CONF_VARS['SYS']['caching']['cacheConfigurations']['cache_pagesection'] = array(
	'frontend' => 't3lib_cache_frontend_VariableFrontend',
	'backend' => 't3lib_cache_backend_MemcachedBackend',
	'options' => array(
		'servers' => array('tcp://localhost:11211')
	)
);
$TYPO3_CONF_VARS['SYS']['useCachingFramework'] = '1';
// ----- /Caching with MemCache - doesn't overwrite cacheConfigurations array completely -----

Steht ein weiterer, dezidierter memcache Server bereit, sollte der in die ’servers‘ Arrays mit aufgenommen werden. Um split-brain in den Caches zu vermeiden und die Last besser zu koordinieren, ist es aber besser fuer jedes Segment einen eigenen, einzelnen Server zu verwenden (wenn man 3 Server uebrig hat…)