{"id":15192094,"url":"https://github.com/margato/redis-spring-tutorial","last_synced_at":"2026-01-28T07:33:02.692Z","repository":{"id":79046634,"uuid":"500197466","full_name":"margato/redis-spring-tutorial","owner":"margato","description":"Tutorial de como integrar Redis com aplicação Spring Boot","archived":false,"fork":false,"pushed_at":"2022-06-13T23:01:05.000Z","size":89,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-11T02:18:12.733Z","etag":null,"topics":["cache","docker","dockercompose","guide","redis","spring","sprintboot","tutorial"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/margato.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-05T19:52:50.000Z","updated_at":"2024-11-17T10:22:02.000Z","dependencies_parsed_at":"2023-02-27T17:15:46.410Z","dependency_job_id":null,"html_url":"https://github.com/margato/redis-spring-tutorial","commit_stats":{"total_commits":3,"total_committers":1,"mean_commits":3.0,"dds":0.0,"last_synced_commit":"95042b102b280d4d3396d18d3f60985eb22f2ae8"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/margato%2Fredis-spring-tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/margato%2Fredis-spring-tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/margato%2Fredis-spring-tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/margato%2Fredis-spring-tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/margato","download_url":"https://codeload.github.com/margato/redis-spring-tutorial/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241110792,"owners_count":19911397,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","docker","dockercompose","guide","redis","spring","sprintboot","tutorial"],"created_at":"2024-09-27T21:04:55.325Z","updated_at":"2026-01-28T07:33:02.651Z","avatar_url":"https://github.com/margato.png","language":"Java","readme":"# Redis com Spring Boot\n\n- [Redis com Spring Boot](#redis-com-spring-boot)\n- [Requisitos](#requisitos)\n    * [O que é Redis?](#o-que---redis-)\n- [Redis na prática](#redis-na-pr-tica)\n    * [Criando as classes do projeto](#criando-as-classes-do-projeto)\n        + [News](#news)\n        + [NewsController](#newscontroller)\n        + [NewsRepository](#newsrepository)\n    * [Como integrar o Redis com Spring](#como-integrar-o-redis-com-spring)\n        + [Iniciar instância Redis local](#iniciar-inst-ncia-redis-local)\n        + [Parâmetros de acesso](#par-metros-de-acesso)\n        + [Configuração na aplicação](#configura--o-na-aplica--o)\n        + [Ativar cache em método](#ativar-cache-em-m-todo)\n    * [Rodando o tutorial](#rodando-o-tutorial)\n\n# Requisitos\n- Conhecimento básico em Spring Boot e Java\n- Docker instalado na máquina (Veja como fazer o download: https://docs.docker.com/get-docker/)\n\n## O que é Redis?\n\nRedis é um armazenamento de estrutura de dados que pode ser utilizado como banco de dados, cache, broker de mensageria e\nmotor de streaming.\n\nRedis provê escrita e leitura atômica de estruturas de dados como listas, conjuntos, maps, strings e outras. Além disso, possui replicação nativa,\nexecução de script em Lua, políticas de limpeza de cache, transações, persistência e alta disponibilidade com Redis\nSentinel e particionamento automático com Redis Cluster.\n\n# Redis na prática\nPara praticar o Redis, vamos criar uma aplicação Spring Boot, utilizando [Spring Initializr](https://start.spring.io/),\nconforme a imagem abaixo:\n![Spring Initializr](./imgs/spring_initializr.jpeg)\n\n\n## Criando as classes do projeto\nPara esse tutorial, iremos exemplificar com um método de listagem de notícias para uma página principal em que o conteúdo é estático e deve ser reconstruído a cada 2 minutos.\nComo o conteúdo é estático, não precisamos obter as mesmas notícias para casa usuário. Se fizéssemos isso, poderíamos onerar o banco de dados desnecessariamente, uma vez que podemos salvar esses dados em cache.\n\nNossa estrutura de classes ficará:\n```\n├── controller\n│   └── NewsController.java\n├── entities\n│   └── News.java\n├── repository\n│   └── NewsRepository.java\n├── RedisTutorialApplication.java\n```\n\n- A classe `News` é uma classe modelo de como uma notícia é estruturada.\n- A classe `NewsRepository` é a classe que faz a obtenção dos dados das notícias na fonte lenta.\n- A classe `NewsController` ficará responsável por expor os dados por HTTP.\n- A classe `RedisTutorialApplication` é a classe principal que executará o framework.\n\n### News\n```java\n@Getter\n@Builder\n@Jacksonized\npublic class News {\n    private final String title;\n    private final String content;\n    private final String author;\n}\n```\n\n### NewsController\n```java\n@RestController\n@RequestMapping(\"/news\")\n@RequiredArgsConstructor\npublic class NewsController {\n\n    private final NewsRepository newsRepository;\n\n    @GetMapping\n    public List\u003cNews\u003e findAll() {\n        return newsRepository.findAll();\n    }\n\n}\n```\n### NewsRepository\nPara simular uma consulta lenta, teremos um `Thread.sleep()` de 4 segundos no método `findAll()`.\n\nAdicionaremos um banco de dados fake apenas para simular a obtenção de dados, com a biblioteca Faker.\n\n```java\n@Component\npublic class NewsRepository {\nprivate final Faker FAKER = new Faker();\nprivate final List\u003cNews\u003e DATABASE = new ArrayList\u003c\u003e();\nprivate static final int NEWS_DB_SIZE = 100;\n\n    @PostConstruct\n    public void setup() {\n        for (int index = 0; index \u003c NEWS_DB_SIZE; index++) {\n            DATABASE.add(News.builder()\n                    .author(FAKER.name().fullName())\n                    .title(FAKER.lorem().characters(10, 20))\n                    .content(FAKER.lorem().characters(1000, 10_000))\n                    .build());\n        }\n    }\n\n    public List\u003cNews\u003e findAll() {\n        try {\n            Thread.sleep(4000);\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n        return DATABASE;\n    }\n}\n```\n## Como integrar o Redis com Spring\nNo arquivo `pom.xml`, é possível integrar com o Redis através de bibliotecas criadas para o ecossistema Spring Boot:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n    \u003cartifactId\u003espring-boot-starter-data-redis\u003c/artifactId\u003e\n    \u003cversion\u003e2.7.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nCom essa biblioteca, poderemos conectar com a instância Redis. Para tanto, precisamos iniciar a instância e configurar os parâmetros de acesso, serialização e cache eviction.\n\n### Iniciar instância Redis local\nPara iniciar o Redis na máquina local, utilizaremos Docker.\n\nFaça download da imagem do Redis:\n```bash\n$ docker pull redis:7.0.0\n```\n\nInicie um container:\n```bash\n$ docker run -d -p 6379:6379 --name redis-tutorial-local redis:7.0.0\n```\n\nPodemos testar a conectividade através do comando `telnet`\n```bash\n$ telnet localhost 6379\n```\n\n### Parâmetros de acesso\nPara definir o hostname e porta, adicionaremos as seguintes linhas no arquivo `application.properties`:\n```properties\nspring.redis.host=localhost\nspring.redis.port=6379\n```\n\n### Configuração na aplicação\nPara configurar a serialização e limpeza de cache, criaremos um pacote `config` e a classe `RedisConfiguration.java`:\n\n```java\n@Slf4j\n@Configuration\n@EnableCaching\n@EnableScheduling\npublic class RedisConfiguration {\n    public static final String NEWS_KEY = \"news\";\n\n    @CacheEvict(allEntries = true, value = NEWS_KEY)\n    @Scheduled(fixedDelayString = \"${cache.ttl.ms}\")\n    public void evictCache() {\n        log.info(\"Cache cleared\");\n    }\n\n    @Bean\n    public RedisCacheConfiguration cacheConfiguration() {\n        return RedisCacheConfiguration.defaultCacheConfig()\n                .disableCachingNullValues()\n                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));\n    }\n}\n```\n\nNote que a classe contém um *Bean* de configuração para desabilitar cache de valores nulos e para serializar objetos Java em JSON utilizando uma classe utilitária.\n\nAlém disso, é utilizado a anotação `@EnableCaching` na declaração da classe para habilitar o uso de cache na aplicação Spring.\n\nCom o uso da anotação `@EnableScheduling`, é possível limpar o cache num intervalo de tempo definido no `application.properties`:\n```properties\ncache.ttl.ms=120000\n```\nCom essa configuração, o cache será limpo a cada 2 minutos.\n\n### Ativar cache em método\nComo visto anteriormente, na classe NewsRepository, simulamos uma lentidão de busca no banco de dados com `Thread.sleep(4000)` que faz com que o endpoint responda no mínimo com 4 segundos de tempo de resposta.\n\n```java\npublic class NewsRepository {\n    private final List\u003cNews\u003e DATABASE = ArrayList\u003c\u003e;\n    \n    public List\u003cNews\u003e findAll() {\n        try {\n            Thread.sleep(4000);\n        } catch (InterruptedException ignored) {\n        }\n        \n        return DATABASE;\n    }\n}\n```\n\nSe testarmos uma chamada na API que busca esses dados, temos o seguinte resultado:\n```bash\n$ curl -o /dev/null -s -w 'Total: %{time_total}s\\n' localhost:8080/news\nTotal: 4.136567s\n```\n\nSe adicionarmos a anotação `@Cacheable(value = NEWS_KEY)` na assinatura do método\n````java\n@Cacheable(value = NEWS_KEY)\npublic List\u003cNews\u003e findAll() { ... }\n````\n\nTemos o seguinte resultado:\n```bash\n$ curl -o /dev/null -s -w 'Total: %{time_total}s\\n' localhost:8080/news\nTotal: 4.159841s\n\n$ curl -o /dev/null -s -w 'Total: %{time_total}s\\n' localhost:8080/news\nTotal: 0.110986s\n\n$ curl -o /dev/null -s -w 'Total: %{time_total}s\\n' localhost:8080/news\nTotal: 0.093111s\n```\nPerceba que na primeira execução, não existia o valor em memória cache, então a aplicação precisou obter o valor da fonte original, que em nosso caso é lenta.\nNas próximas execuções, já obteve o valor da memória Redis, reduzindo drasticamente o tempo de resposta.\nConseguimos reduzir de 4150 ms para 110ms, redução de aproximadamente 38 vezes do tempo de resposta.\n\nO que de fato está acontecendo, é que a aplicação está validando se o dado existe no Redis, e se existir, retorna imediatamente. Caso não exista, ele obterá da fonte original lenta e salvará no Redis para processamentos futuros.\n\n\n\n\n## Rodando o tutorial\n\nRode a aplicação e a instância Redis com o comando e teste em sua máquina o que foi comentado nesse tutorial:\n\n```bash\n$ docker-compose up -d\n```\n\nAcesse pela rota http://localhost:8080/news\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmargato%2Fredis-spring-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmargato%2Fredis-spring-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmargato%2Fredis-spring-tutorial/lists"}