O que é memcache?
Solução de cache no ambiente de cluster de memcache
O Memcache é um sistema de cache de objeto de memória distribuído de alto desempenho. Ao manter uma tabela de hash unificada e enorme na memória, ela pode ser usada para armazenar dados em vários formatos, incluindo imagens, vídeos, arquivos e resultados de recuperação de banco de dados. Simplificando, é para chamar os dados na memória e, em seguida, lê -los da memória, melhorando bastante a velocidade de leitura.
Memcache é um projeto em Danga. Foi servido pela primeira vez pelo LiveJournal. Foi originalmente desenvolvido para acelerar a velocidade de acesso do LiveJournal. Mais tarde, foi adotado por muitos sites grandes.
O Memcached é executado em um ou mais servidores no modo Daemon e recebe conexões e operações do cliente a qualquer momento.
Por que existem dois nomes Memcache e Memcached?
De fato, o Memcache é o nome deste projeto, e o Memcached é o nome principal do arquivo do programa no lado do servidor. Você sabe o que eu quero dizer. Um é o nome do projeto e o outro é o nome principal do arquivo do programa. Eu vi online que muitas pessoas não entendem, então eu misturei.
O Memcached é um sistema de cache de objetos de memória distribuído e alto desempenho usado para reduzir a carga do banco de dados e melhorar a velocidade de acesso em aplicativos dinâmicos. O Memcached é desenvolvido pela Danga Interactive para melhorar o acesso ao LiveJournal.com. LJ tem milhares de visitas dinâmicas de página por segundo e 7 milhões de usuários. O Memcached reduz bastante a carga do banco de dados, aloca melhor recursos e acesso mais rápido.
Este artigo abordará o seguinte:
Memcache
O Memcache é um armazenamento de valores-chave na memória para pequenos pedaços de dados arbitrários (strings, objetos) a partir dos resultados de dados do banco de dados, chamadas de API ou renderização de páginas.
Ou seja, o banco de dados de cache na memória, que é um banco de dados de pares de valor-chave. O banco de dados existe para armazenar temporariamente os dados obtidos de outros serviços na memória e pode ser retornado diretamente do cache de hit quando acessos repetidos. Isso não apenas acelera as taxas de acesso, mas também reduz a carga em outros serviços. Aqui, uma versão do Memcache será implementada e suporta conexões simultâneas entre vários clientes.
O cliente estabelecerá uma conexão Telnet com o servidor e, em seguida, interagirá com o cache do servidor de acordo com o protocolo Memcache. As instruções implementadas aqui são Get, Set e Del. Vamos dar uma olhada no formato de cada instrução
definir
Conjunto é uma instrução de armazenamento. Ao armazenar as características da instrução, insira informações básicas na primeira linha e insira seu valor correspondente na segunda linha.
Set <Key> <lands> <Extime> <sichetes> [noreply]/r/n
<Value>/r/n
Se o armazenamento for bem -sucedido, armazenado será retornado e se a diretiva contiver o atributo Noreply, o servidor não retornará as informações.
O conteúdo de cada domínio nesta diretiva são os seguintes:
Se a instrução não atender aos critérios, o servidor retornará o erro.
pegar
get é um comando get, e as características deste comando são as seguintes:
Obtenha <Key>*/r/n
Ele suporta valores de passagem de várias teclas. Se o cache acertar uma ou mais chaves, os dados correspondentes serão retornados e termina com a extremidade. Se nenhum acerto for feito, a mensagem retornada não contém o valor correspondente à chave. O formato é o seguinte:
Valor <Key> <lags> <ytes>/r/n <Data Block>/r/nvalue <Key> <lags> <bytes>/r/n <bloco de dados>/r/nenddel
Exclua o comando, o formato do comando é o seguinte:
del <Key> [noreply]/r/n
Se a exclusão for bem -sucedida, ele retornará excluído/r/n, caso contrário, retornará não_found. Se houver um parâmetro noreply, o servidor não retornará uma resposta.
Soquete java
Todo o soquete Java precisa saber é o protocolo TCP, soquetes e fluxos de IO. Não vou entrar em detalhes aqui. Você pode se referir à minha série de artigos. Também é recomendável ler a programação da rede Java. Um livro.
Implementação de código
Há algo errado com a função do mapa aqui. Você pode ir ao meu endereço de projeto no final do artigo para visualizar o diagrama de classe.
Aqui, o modo de instrução e o modo de fábrica são usados para implementar a dissociação da criação e execução de instruções. A fábrica de comando receberá a linha de comando e retornará uma instância de comando. Cada comando possui um método de execução para executar suas próprias operações exclusivas. Somente a implementação especial da instrução Del é publicada aqui.
/** * Várias diretivas * atualmente suportam GET, SET, DELETE * * e Erro personalizado *, END */Public Interface Command {/** * Execute Command * @param leitor * @param writer */void Execute (leitor leitor, escritor escritor); / *** Obtenha o tipo do comando* @return*/ commandType getType ();} /*** Instância única da diretiva Factory*/public class CommandFactory {private Static CommandFactory CommandFactory; cache estático privado <tem> memcache; private commandfactory () {} public static commandfactory getInstance (cache <tem> cache) {if (commandFactory == null) {commandFactory = new commandFactory (); memcache = cache; } retornar commandFactory; } / ** * Obtenha comando de acordo com o tipo da diretiva * @param commandLine * @return * / public comando getCommand (string commandLine) {if (commandLine.matches ("^set. } else if (commandLine.matches ("^get.*$")) {return new getCommand (commandLine, memcache); } else if (commandLine.matches ("^del. } else if (commandLine.matches ("^end $")) {return New EndCommand (CommandLine); } else {return new ErrorCommand (CommandLine, errorCommand.erRortype.error); }}} /*** Excluir Diretiva de cache*/public Class DeleteCommand implementa comando {private final String Command; cache final privado <tem> cache; chave de string privada; privado booleano noreply; public DeLeteCommand (comando final da string, cache final <tem> cache) {this.Command = Command; this.cache = cache; initCommand (); } private void initCommand () {if (this.Command.Contains ("noreply")) {noreply = true; } String [] info = command.split (""); chave = info [1]; } @Override public void Execute (leitor leitor, escritor escritor) {bufferwriter bfw = (bufferwriter) writer; Item item = cache.delete (chave); if (! noreply) {tente {if (item == null) {bfw.write ("não_found/r/n"); } else {bfw.write ("excluído/r/n"); } bfw.flush (); } catch (ioexception e) {try {bfw.write ("error/r/n"); bfw.flush (); } catch (ioexception e1) {e1.printStackTrace (); } E.PrintStackTrace (); }}} @Override public CommandType getType () {return CommandType.search; }}Em seguida, implemente o servidor de memória. Para suportar a primeira função da primeira saída, o LinkedTreeMap é usado como a implementação subjacente e o método mais removido é reescrito. Ao mesmo tempo, o tópico de fundo do Cachemanager também é usado para limpar as entradas de cache expiradas no tempo.
classe pública memcache implementa cache <tem> {private logger logger = logger.getLogger (memcache.class.getName ()); // Use o LinkedHashMap para implementar a LRU private static linkedhashmap <string, item> cache; private final int maxsize; // fator de carga FLOAT FINAL PRIVADO DEFAULT_LOAD_FACTOR = 0,75F; public memcache (final int maxSize) {this.maxsize = maxSize; // Verifique se o cache não se expande automaticamente após o maxSize for atingido Int Capacidade = (int) math.ceil (maxsize /default_load_factor) + 1; this.cache = new LinkedHashmap <string, item> (capacidade, default_load_factor, true) {@Override Boolean protegido removelDestEntry (map.entry <string, item> mais alto) {if (size ()> maxsize) {logger.info ("o número do cache". } return size ()> maxSize; }}; // implementar coleções de acesso sincronizado.synchronizedMap (cache); } public sincronizado boolean isfull () {return cache.size ()> = maxsize; } @Override Public item get (string key) {item item = cache.get (key); if (item == null) {logger.info ("tecla no cache:" + key + "não existe"); retornar nulo; } else if (item! = null && Item.isexPired ()) {// Se o cache expirar, exclua e retorne nulo logger.info ("Leia a chave do cache:" + key + "valor:" + item.getValue () + "expirou"); cache.remove (chave); retornar nulo; } logger.info ("Leia a tecla do cache:" + key + "valor:" + item.getValue () + "tempo válido restante" + item.remaintime ()); item de retorno; } @Override public void Set (tecla String, Valor do Item) {Logger.info ("Chave de escreva para cache:" + key + "valor:" + valor); cache.put (chave, valor); } @Override Public Item Delete (chave da string) {Logger.info ("Chave de exclusão do cache:" + key); retornar cache.remove (chave); } @Override public int size () {return cache.size (); } @Override public int capacidade () {return maxSize; } @Override public iterator <pap.entry <string, item >> iterator () {return cache.entryset (). Iterator (); }} /*** Cache Manager* Tópico de fundo* Exclua o cache expirado no cache*/public class Cachemanager implementa Runnable {private logger logger = logger.getLogger (Cachemanager.class.getName ()); // cache de cache de cache <tem> cache; public Cachemanager (cache <tem> cache) {this.cache = cache; } @Override public void run () {while (true) {iterator <pap.entry <string, item >> itemiterator = cache.iterator (); while (Itemiterator.hasNext ()) {map.entry <string, item> entradas = itemiterator.Next (); Item item = entrada.getValue (); if (item.isexired ()) {logger.info ("key:" + entradas.getKey () + "value" + item.getValue () + "expirado, excluído do banco de dados"); Itemiterator.remove (); }} tente {// Execute o programa de segundo plano a cada 5 segundos timeUnit.Seconds.sleep (5); } catch (interruptedException e) {e.printStackTrace (); }}}}Por fim, implemente um servidor de soquete multithread, onde o ServerSocket está vinculado a uma interface e entregue o soquete aceito a um encadeamento adicional para processamento.
/*** servidor*/classe pública ioserver implementa o servidor {parada booleana privada; // Porta número private final Int Port; // servidor Thread ServerSocket ServerSocket; Logger final privado Logger = Logger.getLogger (ioserver.class.getName ()); // pool de threads, capacidade de thread é maxConnection private final ExecorService ExecorService; cache final privado <tem> cache; public ioserver (porta int, int maxConnection, cache <tem> cache) {if (maxConnection <= 0) lançar novo ilegalArgumentException ("o número máximo de conexões suportadas deve ser um número inteiro positivo"); this.port = porta; executorService = executores.newfixedthreadpool (maxConnection); this.cache = cache; } @Override public void start () {try {serverSocket = new ServerSocket (porta); Logger.info ("O servidor inicia na porta"+porta+"); while (true) {tente {soquete soket = serversocket.accept (); logger.info (" recebeu uma conexão de "+soket.getLocalAddress ()+" "); executService.SubMit (New SocketHandler (SwortdRex) (Socket) () () () () () () (") ("(" ("RetwerSocketSocking.EgetLocalAddRest ()+"); E.PrintStackTrace (); ! Serversocket.isclosed (); /*** Lidar com as conexões de cada cliente* Feche a conexão após obter a instrução final s*/classe pública Sockethandler implementa Runnable {private static logger logger = logger.getLogger (sockethandler.class.getName ()); soquete final privado; cache final privado <tem> cache; acabamento booleano privado; Public Sockethandler (Socket S, cache <tem> cache) {this.socket = s; this.cache = cache; } @Override public void run () {try {// Obtenha o fluxo de entrada do soquete Final BufferReader Reader = new BufferredReader (new InputStreamReader (Socket.getInputStream ())); // Obtenha o fluxo de saída do soquete Final BufferWriter Writer = new BufferWriter (novo outputStreamWriter (Socket.getOutputStream ())); CommandFactory commandFactory = commandFactory.getInstance (cache); while (! Finish) {final String CommandLine = reader.readline (); Logger.info ("IP:" + Socket.getLocalAddress () + "Diretiva:" + CommandLine); if (commandLine == null || commandLine.trim (). isEmpty ()) {continuação; } // Use a fábrica de comando para obter a instância de comando Final Command = CommandFactory.getCommand (CommandLine); command.execute (leitor, escritor); if (command.getType () == commandType.end) {Logger.info ("Solicitação para fechar a conexão"); acabamento = true; }}} catch (ioexception e) {e.printStackTrace (); Logger.info ("Feche a conexão de" + soket.getLocalAddress () + ""); } finalmente {tente {if (soket! = null) {socket.close (); }} catch (ioexception e) {e.printStackTrace (); }}}}Clique aqui para o endereço do projeto. Se você acha que é muito bom, espero que você possa me dar uma estrela.
Referências
Site oficial de Memcached
Protocolo Memcache
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.