<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Objectzilla &#187; java cache memcached</title>
	<atom:link href="http://www.objectzilla.com.br/tag/java-cache-memcached/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.objectzilla.com.br</link>
	<description>por Leonardo Veríssimo</description>
	<lastBuildDate>Sat, 05 Jun 2010 18:58:50 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Já usou Memcached?</title>
		<link>http://www.objectzilla.com.br/2009/05/02/ja-usou-memcached/</link>
		<comments>http://www.objectzilla.com.br/2009/05/02/ja-usou-memcached/#comments</comments>
		<pubDate>Sat, 02 May 2009 20:02:17 +0000</pubDate>
		<dc:creator>Leonardo</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[java cache memcached]]></category>

		<guid isPermaLink="false">http://www.objectzilla.com.br/?p=207</guid>
		<description><![CDATA[Cache não é algo que os programadores desconhem. Quem esteve numa universidade, e teve uma aula séria de Arquitetura de Computadores, sabe que a memória é disposta numa hierarquia de caches. E quem já programou em Java, já ouviu falar de inicialização tardia, muito usado em singletons (apesar de não ser só para isso):

public class [...]]]></description>
			<content:encoded><![CDATA[<p>Cache não é algo que os programadores desconhem. Quem esteve numa universidade, e teve uma aula séria de Arquitetura de Computadores, sabe que a memória é disposta numa hierarquia de caches. E quem já programou em Java, já ouviu falar de inicialização tardia, muito usado em <em>singletons</em> (apesar de não ser só para isso):<span id="more-207"></span></p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> MinhaClasse <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> MinhaClasse instance<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> MinhaClasse getInstance<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    	<span style="color: #000000;  font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>instance == <span style="color: #006600; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    		instance = <span style="color: #000000; font-weight: bold;">new</span> MinhaClasse<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    	<span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">return</span> instance<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// outras coisas</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Esse é um jeito de fazer cache. Apenas deve-se tomar cuidado para que o objeto a ser retornado não seja mutável. Afinal, todos os interessados estão com a mesma instância, e se um dos clientes puderem mudar uma propriedade desse único objeto, todos terão o efeito indesejável de ter um objeto com comportamento diferente sem saber. Detalhe: a implementação de <em>singleton</em> dessa maneira é ingênua, evite-a.</p>
<p>Um outro jeito, comumente usado, de fazer cache é usar <em>session</em>. Pra quem tem uma aplicação web, parece mágico: joga-se uma entidade da persistência na sessão passando uma chave. Ao precisar do mesmo objeto de novo, ao invés de acessar o banco, pega-se o objeto da sessão com a mesma chave usada na escrita. Esse é a estratégia mais comum que eu já vi por aí. Mas existem vários problemas : já vi aplicações com mais código pra cache em sessão do que pro próprio negócio! Além do mais, <em>sessions</em> são únicas para cada usuário no <em>browser</em>, enquanto que a entidade a ser cacheada é, não raro, visível a vários usuários. Significa duas coisas: 1) Não vai ter uma cacheamento efetivo, se 20 usuários se logarem e todos acessarem a mesma entidade duas vezes, haverá vinte cópias do objeto, que será escrita e lida uma vez cada; 2) Ninguém sabe o que um outro usuário pode fazer, se um alterar a entidade, todos os dezenove usuários restantes não terão como saber disso e manterão cópias desatualizadas. <em>Session</em> não foi feita pra cache, e existe até um problema de design: apesar do mapa de sessão pertencer à camada de apresentação, o cache lida com problemas de objetos que surgem na camada de persistência. Dizer que um pode ser usado para implementação do outro resulta em confusões de conceitos.</p>
<p>Uma solução melhor é usar bibliotecas de cache. No Java, um bastante comum é o EHCache &#8212; usado principalmente para o cache de segundo nível de Hibernate &#8212; que fica na mesma JVM da sua aplicação. Não que seja ruim (tem até uns javeiros roxos que acham que esta é a melhor solução do mundo), mas quando se quer usar um cluster de aplicações web, por exemplo, passa-se a ter vários caches para cada instância de servidor, que é não o desejável. Uma das opções de cache, que fica fora da JVM de sua aplicação, é o Memcached.</p>
<p>A seguir, apresentarei as vantagens do Memcached, seu mecanismo básico junto com uma API do Java, e no final, o uso integrado com o Hibernate.</p>
<h2>Características do Memcached</h2>
<p>Memcached permite a chamada <strong>escalabilidade horizontal</strong>, ou seja, é possível usar várias instâncias de memcached em paralelo como se fosse uma única unidade, onde cada processo possui somente parte dos registros. Parece idiota, mas não é. Não é toda infraestrutura que lhe permite isso; bancos de dados tradicionais, sistemas operacionais e máquinas virtuais possuem uma dificuldade tremenda de configurações para que isso seja possível.</p>
<p>Porém, ser fácil de se escalar horizontalmente trouxe certos custos na sua implementação. Exemplo: Não existe replicação de dados automática, se quiser duas instâncias com dados iguais, terá que fazer seu script. Não existe transação e nem lock, pois isso gera contenção. Não existem busca por todos os registros ou por wildcards, pois pode causar demora nos resultados. E não há garantia de durabilidade de objetos armazenados em casos de <em>crash</em>.</p>
<p>E ainda duas características peculiares, uma é que o <strong>tempo de expiração no cache</strong> não é zerado com consultas (como é tradicional nas sessions de containeres web), ou seja, se você definir como tempo de expiração dois minutos, esse será o tempo que ficará armazenado, independente se houve consulta do registro nesse meio-tempo ou não. Portanto, sempre coloque no memcached objetos que já estejam persistidos em outro lugar. A segunda característica é que o tempo de expiração é definido por segundos que devem ser armazenados, ou seja, uma hora é 3600. Mas apenas se o tempo de permanência for menor que trinta dias, se for maior, o Memcached assume que é o tempo UNIX absoluto, ou seja, 1240699927 significa que o registro deve permanecer em cache até em 25 de abril de 2009 às 22h52min07 em UTC.</p>
<h2>Como usar</h2>
<p>Se você estiver usando alguma distribuição Linux, com certeza o Memcached pode ser baixado diretamente de seu repositório. Caso você seja um usuário Windows, existem portes do cache para esse Sistema Operacional <a href="http://www.splinedancer.com/memcached-win32/">aqui</a> e <a href="http://code.jellycan.com/memcached/">aqui</a>. Como só tenho o Fedora, não testei pra ver se funciona, então o <a href="http://www.google.com.br/">Google</a> será melhor pra resolver problemas de instalação no Windows do que eu.</p>
<p>Além disso, é necessário um cliente Memcached, que existem para várias linguagens. No Java, a melhor biblioteca que encontrei é a <a href="http://code.google.com/p/spymemcached/">Spy Memcached</a>, disponível na <a href="http://spymemcached.googlecode.com/files/memcached-2.3.1.jar">versão 2.3.1</a>. Baixe o arquivo e coloque no classpath de sua aplicação.</p>
<p>Incialize o Memcached no seu shell dessa maneira:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">memcached <span style="color: #660033;">-p</span> <span style="color: #000000;">18000</span> <span style="color: #660033;">-vv</span></pre></div></div>

<p>A opção -p indica a porta da conexão TCP por onde será &#8220;ouvida&#8221; (não é necessário, se não informar será assumido o padrão 11211), e o -vv é a opção <em>verbose</em>.</p>
<p>Na sua aplicação Java, você abre um cliente Memcached dessa maneira:</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;">MemcachedClient mem = <span style="color: #000000; font-weight: bold;">new</span> MemcachedClient<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399; font-weight: bold;">InetSocketAddress</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;localhost&quot;</span>, <span style="color: #cc66cc;">18000</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Ou seja, passando um endereço de rede ao construtor do MemcachedClient. Caso você queira um cluster de aplicações Memcached, é possível também passar uma lista de endereços de redes, assim:</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;">MemcachedClient mem = <span style="color: #000000; font-weight: bold;">new</span> MemcachedClient<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399; font-weight: bold;">InetSocketAddress</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399; font-weight: bold;">InetSocketAddress</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;localhost&quot;</span>, <span style="color: #cc66cc;">18000</span><span style="color: #009900;">&#41;</span>,
				<span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399; font-weight: bold;">InetSocketAddress</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;localhost&quot;</span>, <span style="color: #cc66cc;">18001</span><span style="color: #009900;">&#41;</span>,
			<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Obviamente, é necessário duas instâncias de Memcached disponíveis nesses endereços.</p>
<p>As operações que o Memcached suporta são simples, exemplos:</p>
<h3>set</h3>
<p><img src="/wp-content/pic/memcached/opcao_set.png" alt="Memcached - exemplo do comando SET" /></p>
<p>A operação <strong>set</strong> insere um valor para uma dada chave, independente se esta já possuía um valor anterior ou não:</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;">     <span style="color: #003399; font-weight: bold;">String</span> marca = <span style="color: #0000ff;">&quot;Ford&quot;</span><span style="color: #339933;">;</span>
     <span style="color: #006600; font-weight: bold;">int</span> expira = <span style="color: #009900;">&#40;</span><span style="color: #006600; font-weight: bold;">int</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#40;</span><span style="color: #003399; font-weight: bold;">System</span>.<span style="color: #006633;">currentTimeMillis</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> + <span style="color: #cc66cc;">60</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">60</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">1000</span><span style="color: #009900;">&#41;</span> / <span style="color: #cc66cc;">1000</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// uma hora pra expirar</span>
&nbsp;
     Future<span style="color: #339933;">&lt;</span>Boolean<span style="color: #339933;">&gt;</span> valido = mem.<span style="color: #006633;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;marca&quot;</span>, expira, marca<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Lembre-se também do comportamento dos trinta dias, as duas formas abaixo setam o mesmo período de expiração:</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;">     Future<span style="color: #339933;">&lt;</span>Boolean<span style="color: #339933;">&gt;</span> valido = mem.<span style="color: #006633;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;marca&quot;</span>, <span style="color: #cc66cc;">24</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">60</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">60</span>, marca<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// um dia para expirar</span>
     Future<span style="color: #339933;">&lt;</span>Boolean<span style="color: #339933;">&gt;</span> valido = mem.<span style="color: #006633;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;marca&quot;</span>, <span style="color: #009900;">&#40;</span><span style="color: #006600; font-weight: bold;">int</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#40;</span><span style="color: #003399; font-weight: bold;">System</span>.<span style="color: #006633;">currentTimeMillis</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> + <span style="color: #cc66cc;">24</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">60</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">60</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">1000</span><span style="color: #009900;">&#41;</span> / <span style="color: #cc66cc;">1000</span>, marca<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// também um dia</span></pre></div></div>

<p>É possível <em>setar</em> qualquer coisa, inclusive objetos Java que sejam seriálizáveis. Porém, qualquer coisa diferente de um tipo simples não é identificável para programas em outras linguagens que se conectarem a esse mesmo Memcached.</p>
<h3>add</h3>
<p><img src="/wp-content/pic/memcached/opcao_add.png" alt="Memcached - exemplo do comando ADD" /></p>
<p>A operação <strong>add</strong>, apesar do nome, insere um valor para uma dada chave, deste que esta não esteja com um elemento previamente armazenado:</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;">     Pessoa pessoa1 = <span style="color: #000000; font-weight: bold;">new</span> Pessoa<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     pessoa1.<span style="color: #006633;">setId</span><span style="color: #009900;">&#40;</span>28L<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     pessoa1.<span style="color: #006633;">setName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Leonardo&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
     Future<span style="color: #339933;">&lt;</span>Boolean<span style="color: #339933;">&gt;</span> valido1 = mem.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;pessoa&quot;</span>, <span style="color: #cc66cc;">60</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">60</span>, pessoa1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// valido1 é true</span>
&nbsp;
     Pessoa pessoa2 = <span style="color: #000000; font-weight: bold;">new</span> Pessoa<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     pessoa2.<span style="color: #006633;">setId</span><span style="color: #009900;">&#40;</span>41L<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     pessoa2.<span style="color: #006633;">setName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Vinicius&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
     Future<span style="color: #339933;">&lt;</span>Boolean<span style="color: #339933;">&gt;</span> valido2 = mem.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;pessoa&quot;</span>, <span style="color: #cc66cc;">60</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">60</span>, pessoa2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// valido2 é false</span></pre></div></div>

<h3>replace</h3>
<p><img src="/wp-content/pic/memcached/opcao_replace.png" alt="Memcached - exemplo do comando REPLACE" /></p>
<p>A operação <strong>replace</strong>, ao contrário do <em>add</em>, insere um valor para uma dada chave apenas se esta já estiver anteriormente armazenado:</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;">     <span style="color: #006600; font-weight: bold;">int</span> anoLancamento = <span style="color: #cc66cc;">2010</span><span style="color: #339933;">;</span>
     Future<span style="color: #339933;">&lt;</span>Boolean<span style="color: #339933;">&gt;</span> valido1 = mem.<span style="color: #006633;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;anoLancamento&quot;</span>, <span style="color: #cc66cc;">60</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">60</span>, anoLancamento<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// valido1 é false</span>
&nbsp;
     Future<span style="color: #339933;">&lt;</span>Boolean<span style="color: #339933;">&gt;</span> ok = mem.<span style="color: #006633;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;anoLancamento&quot;</span>, <span style="color: #cc66cc;">60</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">60</span>, anoLancamento<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// set armazena de qualquer jeito</span>
     ok.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// bloqueia até a conclusão</span>
&nbsp;
     <span style="color: #006600; font-weight: bold;">int</span> novoAnoLancamento = <span style="color: #cc66cc;">2011</span><span style="color: #339933;">;</span>
     Future<span style="color: #339933;">&lt;</span>Boolean<span style="color: #339933;">&gt;</span> valido2 = mem.<span style="color: #006633;">replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;anoLancamento&quot;</span>, <span style="color: #cc66cc;">60</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">60</span>, novoAnoLancamento<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// valido2 é true</span></pre></div></div>

<h3>get</h3>
<p><img src="/wp-content/pic/memcached/opcao_get.png" alt="Memcached - exemplo do comando GET" /></p>
<p>A operação <strong>get</strong> busca um registro armazenado anteriormete, dada uma chave:</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;">     <span style="color: #003399; font-weight: bold;">String</span> marca = <span style="color: #009900;">&#40;</span><span style="color: #003399; font-weight: bold;">String</span><span style="color: #009900;">&#41;</span> mem.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;marca&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// &quot;Ford&quot;, ou null se demorou demais ou expirou</span></pre></div></div>

<h3>delete</h3>
<p><img src="/wp-content/pic/memcached/opcao_delete.png" alt="Memcached - exemplo do comando DELETE" /></p>
<p>A operação <strong>delete</strong> apaga um valor no Memcached dada a chave. O valor armazenado não é retornado:</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;">     Future<span style="color: #339933;">&lt;</span>Boolean<span style="color: #339933;">&gt;</span> valido1 = mem.<span style="color: #006633;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;anoLancamento&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// true</span>
&nbsp;
     Future<span style="color: #339933;">&lt;</span>Boolean<span style="color: #339933;">&gt;</span> valido2 = mem.<span style="color: #006633;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;anoLancamento&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// false</span></pre></div></div>

<h3>incr</h3>
<p>A operação <strong>incr</strong> incrementa um valor previamente armazenado. Válido somente para números:</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;">     <span style="color: #006600; font-weight: bold;">long</span> valor1 = mem.<span style="color: #006633;">incr</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;contador&quot;</span>, <span style="color: #cc66cc;">9</span>, <span style="color: #cc66cc;">5</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">/* o segundo parâmetro é valor a ser incrementado */</span>
                                               <span style="color: #666666; font-style: italic;">/* o terceiro parâmetro (opcional) é o valor inicial caso não haja nenhum par armazenado */</span>
                                               <span style="color: #666666; font-style: italic;">/* valor1 = 5 */</span>
&nbsp;
     <span style="color: #006600; font-weight: bold;">long</span> valor2 = mem.<span style="color: #006633;">incr</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;contador&quot;</span>, <span style="color: #cc66cc;">7</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">/* se não informasse o valor inicial e esta fosse a primeira chamada, o retorno seria -1 */</span>
                                            <span style="color: #666666; font-style: italic;">/* valor2 = 12 */</span></pre></div></div>

<h3>decr</h3>
<p>A operação <strong>decr</strong> decrementa um valor previamente armazenado. Válido somente para números:</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;">     <span style="color: #006600; font-weight: bold;">long</span> valor1 = mem.<span style="color: #006633;">decr</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;contador&quot;</span>, <span style="color: #cc66cc;">12</span>, <span style="color: #cc66cc;">20</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">/* valor1 = 20 */</span>
     <span style="color: #006600; font-weight: bold;">long</span> valor2 = mem.<span style="color: #006633;">decr</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;contador&quot;</span>, <span style="color: #cc66cc;">9</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>      <span style="color: #666666; font-style: italic;">/* valor2 = 11 */</span></pre></div></div>

<p>Lembre-se: os números são só positivos. Se o valor armazenado é 4 e você decrementar 6, o valor final é 0 (zero).</p>
<h2>Exemplo de cache para banco de dados</h2>
<p>Vamos a uma situação prática. Imagine um banco de consulta de preços de um supermercado. Alguns preços são consultados com bastante frequência e seus preços são raramente alterados. Idealmente, seria interessante cachear esses valores retornados para aliviar a carga do banco. Meu objeto de domínio é um só:</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ProductDescription <span style="color: #000000; font-weight: bold;">implements</span> <span style="color: #003399; font-weight: bold;">Serializable</span> <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #006600; font-weight: bold;">long</span> barCode<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399; font-weight: bold;">String</span> description<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399; font-weight: bold;">BigDecimal</span> price<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399; font-weight: bold;">String</span> type<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// getters e setters omitidos</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Meu acesso aos dados obedece a essa interface:</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">br.com.objectzilla.testeDaoMemcached</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">interface</span> ProductDescriptionRepository <span style="color: #009900;">&#123;</span>
&nbsp;
	ProductDescription getByBarCode<span style="color: #009900;">&#40;</span><span style="color: #006600; font-weight: bold;">long</span> barCode<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #006600; font-weight: bold;">void</span> refreshProductInformation<span style="color: #009900;">&#40;</span>ProductDescription product<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Ou seja, existe um método para retornar um pedido por código de barras (<em>getByBarCode()</em>) e outro que atualiza ou insere um produto (<em>refreshProductInformation()</em>).Também tenho uma classe, implementando essa interface, que executa comandos SQL no banco via JDBC (ProductDescriptionDAO, não mostrado).</p>
<p>O pulo do gato é uma classe, que fica como um Decorator, que realiza o cache, veja:</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">br.com.objectzilla.testeDaoMemcached</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">net.spy.memcached.MemcachedClient</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ProductDescriptionCacheDecorator <span style="color: #000000; font-weight: bold;">implements</span> ProductDescriptionRepository <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> MemcachedClient memcachedClient<span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #006600; font-weight: bold;">int</span> expiration<span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">private</span> ProductDescriptionRepository other<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> ProductDescription getByBarCode<span style="color: #009900;">&#40;</span><span style="color: #006600; font-weight: bold;">long</span> barCode<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
		ProductDescription product = <span style="color: #009900;">&#40;</span>ProductDescription<span style="color: #009900;">&#41;</span> memcachedClient.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;product_descr/&quot;</span> + barCode<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000000;  font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>product == <span style="color: #006600; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			product = other.<span style="color: #006633;">getByBarCode</span><span style="color: #009900;">&#40;</span>barCode<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
			memcachedClient.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;product_descr/&quot;</span> + barCode, expiration, product<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #000000; font-weight: bold;">return</span> product<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #006600; font-weight: bold;">void</span> refreshProductInformation<span style="color: #009900;">&#40;</span>ProductDescription product<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		other.<span style="color: #006633;">refreshProductInformation</span><span style="color: #009900;">&#40;</span>product<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		memcachedClient.<span style="color: #006633;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;product_descr/&quot;</span> + product.<span style="color: #006633;">getBarCode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #006600; font-weight: bold;">void</span> setMemcachedClient<span style="color: #009900;">&#40;</span>MemcachedClient memcachedClient<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">memcachedClient</span> = memcachedClient<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #006600; font-weight: bold;">void</span> setExpiration<span style="color: #009900;">&#40;</span><span style="color: #006600; font-weight: bold;">int</span> expiration<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">expiration</span> = expiration<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #006600; font-weight: bold;">void</span> setOther<span style="color: #009900;">&#40;</span>ProductDescriptionRepository other<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">other</span> = other<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Primeiro, a variável other refere-se a uma outra classe que implementa também ProductDescriptionRepository, como a classe acima é um decorator, natural que essa referência seja de um objeto que realmente faz acesso ao banco. Tem-se também a instância de um MemcachedClient e a instância de um período de expiração, para ser usado para a manipulação de dados do Memcached.</p>
<p>Veja, primeiro, o método <strong>getByBarCode</strong>, a primeira coisa que se faz é buscar um registro no memcached usando uma chave formada do nome abreviado do objeto seguido do código de barras do produto (o id). Havendo esse registro, retorna-o, e aí a consulta ao banco não é realizada e fim de papo. Se esse registro não estiver no Memcached, aí este é buscado no banco (através de <em>other</em>) e, em sequência, realizada a inserção do objeto no cache, para que as próximas chamadas desse método não façam busca no banco de novo. Lembre-se que o cache expira, e não é apropriado assumir que o objeto está sempre no cache, portanto é sempre necessário ter essa verificação de registro vazio em todas as suas consultas.</p>
<p>Ao inserir ou alterar um registro, o dado no cache fica desatualizado. Por isso, existe uma chamada para remover o ítem após a inserção bem sucedida no método <strong>refreshProductInformation()</strong>. Poderia haver uma inserção no memcache nesse ponto, mas preferi não fazer, porque de qualquer forma, isso será feito no método de busca.</p>
<p>A aplicação que exercita esse cache está disponível nesse <a href="/wp-content/zip/testeDaoMemcached.zip">zip</a>, caso queiram estudá-lo com mais detalhes.</p>
<h2>Usando como cache de segundo nível do Hibernate</h2>
<p>O <a href="https://www.hibernate.org/">Hibernate</a> possui suporte a cache de segundo nível, e a implementação mais comum é o <a href="http://ehcache.sourceforge.net/">EHCache</a>, que vem junto com o framework de persistência. Por ter um cache quase automático (pois você precisa habilitá-lo para cada entidade mapeada), é meio desvantajoso fazer cacheamento manualmente como fiz anteriormente. Incrivelmente, na minha busca por Memcached no Google, me deparei com o plugin <a href="http://code.google.com/p/hibernate-memcached/">hibernate-memcached</a> que usa o Memcached como cache de segundo nível.</p>
<p>Se a opção for essa, as coisas facilitam bastante. Primeiro, anotaremos a entidade ProductDescription, assim:</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;">@<span style="color: #003399; font-weight: bold;">Entity</span>
@Table<span style="color: #009900;">&#40;</span>name=<span style="color: #0000ff;">&quot;product_description&quot;</span><span style="color: #009900;">&#41;</span>
@Cache<span style="color: #009900;">&#40;</span>usage=CacheConcurrencyStrategy.<span style="color: #006633;">NONSTRICT_READ_WRITE</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ProductDescription <span style="color: #000000; font-weight: bold;">implements</span> <span style="color: #003399; font-weight: bold;">Serializable</span> <span style="color: #009900;">&#123;</span>
&nbsp;
	@Id
	@Column<span style="color: #009900;">&#40;</span>name=<span style="color: #0000ff;">&quot;bar_code&quot;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #006600; font-weight: bold;">long</span> barCode<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399; font-weight: bold;">String</span> description<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399; font-weight: bold;">BigDecimal</span> price<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399; font-weight: bold;">String</span> type<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// getters e setters</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Existem as anotações triviais do JPA, como @Entity, @Table, @Id e @Column. Mas existe também a anotação específica do Hibernate, que é o @Cache. Na estratégia de concorrência, estou dizendo que é possível haver escrita e leitura, mas que a escrita não bloqueia leituras. Sem esta anotação, o cache não funciona pra essa entidade. (Por isso, se você um dia colocou o cache de segundo nível que você queria nas configurações, mas nunca colocou a anotação @Cache nas entidades, é a mesma coisa que não ter cache de segundo nível.)</p>
<p>O Dao faz acessos ao Hibernate normalmente (estou usando o template do Spring):</p>

<div class="wp_syntax"><div class="code"><pre class="java5" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">br.com.objectzilla.hibernateMemcached</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.hibernate.SessionFactory</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.orm.hibernate3.HibernateTemplate</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.transaction.annotation.Transactional</span><span style="color: #339933;">;</span>
&nbsp;
@Transactional
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ProductDescriptionDAO <span style="color: #000000; font-weight: bold;">implements</span> ProductDescriptionRepository <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> HibernateTemplate hibernateTemplate<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> ProductDescription getByBarCode<span style="color: #009900;">&#40;</span><span style="color: #006600; font-weight: bold;">long</span> barCode<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">return</span> <span style="color: #009900;">&#40;</span>ProductDescription<span style="color: #009900;">&#41;</span> hibernateTemplate.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>ProductDescription.<span style="color: #000000; font-weight: bold;">class</span>, barCode<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #006600; font-weight: bold;">void</span> refreshProductInformation<span style="color: #009900;">&#40;</span>ProductDescription product<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		product = <span style="color: #009900;">&#40;</span>ProductDescription<span style="color: #009900;">&#41;</span> hibernateTemplate.<span style="color: #006633;">merge</span><span style="color: #009900;">&#40;</span>product<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		hibernateTemplate.<span style="color: #006633;">saveOrUpdate</span><span style="color: #009900;">&#40;</span>product<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #006600; font-weight: bold;">void</span> setSessionFactory<span style="color: #009900;">&#40;</span>SessionFactory sessionFactory<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		hibernateTemplate = <span style="color: #000000; font-weight: bold;">new</span> HibernateTemplate<span style="color: #009900;">&#40;</span>sessionFactory<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>E pra configurar, basta adicionar essas propriedades no hibernate.cfg.xml:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;hibernate.cache.provider_class&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>com.googlecode.hibernate.memcached.MemcachedCacheProvider<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;hibernate.cache.use_query_cache&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;hibernate.memcached.servers&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>localhost:14001<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Onde eu indico o provedor do cache, a opção de se fazer cache de queries, e o servidor do Memcached. Não são as únicas opções, mas as outras possuem opção <em>default</em>, que você encontra <a href="http://code.google.com/p/hibernate-memcached/wiki/Configuration">aqui</a>.</p>
<p>É só isso, agora é só adiconar o hibernate-memcached e o spy-memcached no seu classpath e rodar a aplicação. Também disponibilizei um <a href="/wp-content/zip/hibernateMemcached.zip">zip</a> para esse exemplo, caso vocês queiram dar uma olhada.</p>
<h2>Conclusão</h2>
<p>Usar cache, seja o Memcached ou qualquer outro, é uma boa opção para evitar acesso a recursos custosos, como o banco de dados. Mas, numa aplicação dividida em camadas não é sempre necessário que a responsabilidade de cachear fique no lado cliente (camada de apresentação). Se deixar que o lado servidor (camada de persistência) tenha essa responsabilidade, você pode deixar que os clientes acessem a camada de persistência na hora e do jeito que bem entenderem e, ainda assim, de maneira transparente, estará sendo feito acesso eficiente de recursos.</p>
<p>Eu havia feito uma medição bem informal de quanto o Memcached economizaria o tempo de busca. Levei à conclusão de que por causa de warm-up e tudo mais, eu não sei fazer benchmarks. <img src='http://www.objectzilla.com.br/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  O mais importante do cache não costuma nem ser o tempo de acesso mais rápido, mas o fato de não deixar &#8220;engargalar&#8221; o banco com muitos acessos.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.objectzilla.com.br/2009/05/02/ja-usou-memcached/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
