Quand on n’a pas la possibilité d’avoir un serveur memcache à disposition, on peut mettre en place un système de cache en base de données simplement. Voici comment faire.
Il faut commencer par créer la table qui va stocker les données, voici les commandes sql pour mySQL :
CREATE TABLE `cached_items` ( `id` int(11) NOT NULL AUTO_INCREMENT, `cachekey` varchar(255) DEFAULT NULL, `created` datetime DEFAULT NULL, `expires` datetime DEFAULT NULL, `content` longblob, `cachehit` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `cacheditems_cachekey_index` (`cachekey`), KEY `cacheditems_created_index` (`created`), KEY `cacheditems_expires_index` (`expires`) );
Ensuite, il faut créer un modèle appelé CachedItem dans app/models/cached_item.rb c’est grâce à lui qu’on pourra accéder aux données cachées :
require 'digest/sha1' class CachedItem < ActiveRecord::Base def self.check_for(item) key = Digest::MD5.hexdigest(Marshal.dump(item)) logger.info "Cache checking for key #{key}" self.find(:first, :conditions => ["cachekey = ? AND expires > NOW()", key]) end def self.get_cached(item) key = Digest::MD5.hexdigest(Marshal.dump(item)) logger.info "Cache getting by key #{key}" getc = self.find( :first, :conditions => ["cachekey = ?", key] ) hitcount = getc.cachehit + 1 self.update(getc.id, {:cachehit => hitcount}) self.delete_all "expires < NOW()" # Efface les données trop vieilles return Marshal.load(getc.content) end def self.store_data(item, data) key = Digest::MD5.hexdigest(Marshal.dump(item)) logger.info "%%% storing by key #{key}" content = Marshal.dump(data) logger.level = (4) # Empêche d'afficher les données de Marshal dans le log ci = new() ci.cachekey = key ci.created = Time.now() ci.expires = 30.minutes.from_now() # durée de vie de la donnée cachée ci.content = content ci.cachehit = 0 ci.save return data end end
Voila, le plus dur est fait. Faites attention au type de données que vous stockez, Marshal ne supporte pas tous les types. Vous pouvez sans problème stocker une chaîne, par exemple pour du XML vous pouvez faire :
donnees = REXML::Document.new(mes_donnees_xml).root CachedItem.store_data(donnees_id, donnees.to_s)
Pour stoker des donnes xml. Pour les relire :
donnees = REXML::Document.new(CachedItem.get_cached(mes_donnees_xml_id)).root
Les données trop vieilles sont automatiquement effacée lors d’une lecture quelconque (voir get_cached) et la durée de vie d’une donnée est définie lors de l’écriture dans store_data.
Merci à joeldg pour son code qui a servi de base à ce billet.

0 commentaire ↓
Il n'y a aucun commentaire
Laisser un commentaire