Redis ist der Schweizer Taschenmesser unter den Datenbanken: extrem schnell, vielfältig einsetzbar und nativ auf Performance optimiert. Während relationale Datenbanken auf Festplattenpersistenz und ACID-Transaktionen optimiert sind, glänzt Redis als In-Memory-Datenbank mit Sub-Millisekunden-Latenz. Spring Data Redis macht die Integration in Spring-Boot-Projekte nahtlos.

Redis als Cache

Die häufigste Anwendung von Redis in Java-Projekten ist das Caching. Spring Boot bietet mit @Cacheable eine deklarative Schnittstelle – das Backend tauscht man über die Konfiguration aus.

Abhängigkeiten:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
Code-Sprache: HTML, XML (xml)

Konfiguration für Redis als Cache-Backend:

@Configuration
@EnableCaching
public class CacheConfig {
}
Code-Sprache: PHP (php)
spring.cache.type=redis
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.cache.redis.time-to-live=10m

Cacheable Service:

@Service
public class ProduktService {

    @Cacheable(value = "produkte", key = "#id")
    public Produkt findById(Long id) {
        <em>// Nur beim ersten Aufruf (Cache Miss) – danach aus Redis</em>
        return produktRepository.findById(id)
            .orElseThrow();
    }

    @CacheEvict(value = "produkte", key = "#id")
    public void update(Long id, ProduktUpdate update) {
        <em>// Cache-Eintrag wird nach dem Update gelöscht</em>
        produktRepository.update(id, update);
    }
}
Code-Sprache: PHP (php)

Spring prüft vor dem Methodenaufruf, ob der Schlüssel im Redis-Cache existiert. Wenn ja, wird die Methode übersprungen und der gecachte Wert zurückgegeben. @CacheEvict entfernt den Eintrag nach schreibenden Operationen.

RedisTemplate für direkten Zugriff

Für granulare Operationen bietet Spring Data Redis das RedisTemplate:

@Bean
public RedisTemplate<String, Produkt> redisTemplate(
        RedisConnectionFactory factory) {
    RedisTemplate<String, Produkt> template = new RedisTemplate<>();
    template.setConnectionFactory(factory);
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(
        new Jackson2JsonRedisSerializer<>(Produkt.class));
    return template;
}
Code-Sprache: JavaScript (javascript)

Direkte Nutzung:

<em>// Speichern mit TTL</em>
redisTemplate.opsForValue()
    .set("produkt:42", produkt, Duration.ofMinutes(30));

<em>// TTL prüfen</em>
Long ttl = redisTemplate.getExpire("produkt:42"); <em>// in Sekunden</em>

<em>// Atomar inkrementieren</em>
Long aufrufe = redisTemplate.opsForValue()
    .increment("counter:produkt:42");
Code-Sprache: JavaScript (javascript)

Redis bietet neben einfachen Key-Value-Operationen auch Listen, Sets, Sorted Sets und Hashes als native Datenstrukturen – alle über redisTemplate.opsForList().opsForSet() etc. ansprechbar.

Pub/Sub mit Redis

Redis kann als Message Broker fungieren – für einfache Ereignisbenachrichtigungen ohne den Overhead von Kafka oder RabbitMQ.

Konfiguration:

@Configuration
public class RedisPubSubConfig {

    @Bean
    public RedisMessageListenerContainer container(
            RedisConnectionFactory factory,
            MessageListenerAdapter adapter) {
        RedisMessageListenerContainer container =
            new RedisMessageListenerContainer();
        container.setConnectionFactory(factory);
        container.addMessageListener(adapter,
            new PatternTopic("bestellungen.*"));
        return container;
    }

    @Bean
    public MessageListenerAdapter adapter(
            BestellungSubscriber subscriber) {
        return new MessageListenerAdapter(subscriber, "onMessage");
    }
}
Code-Sprache: PHP (php)

Subscriber:

@Component
public class BestellungSubscriber {

    public void onMessage(String nachricht) {
        log.info("Neue Bestellung: {}", nachricht);
        <em>// Lager aktualisieren, E-Mail versenden ...</em>
    }
}
Code-Sprache: JavaScript (javascript)

Publisher:

redisTemplate.convertAndSend(
    "bestellungen.neu", bestellungJson);
Code-Sprache: CSS (css)

Pub/Sub eignet sich für Szenarien wie Cache-Invalidation über Service-Grenzen hinweg oder Echtzeit-Benachrichtigungen. Für garantierte Zustellung (At-Least-Once) sollte man jedoch auf Kafka oder Redis Streams ausweichen.

Redis Streams

Redis Streams (seit Redis 5.0) bieten eine persistente Nachrichtenstruktur mit Consumer Groups – ideal für Event-Driven-Architekturen, bei denen Nachrichten nicht verloren gehen dürfen:

<em>// Nachricht schreiben</em>
Map<String, String> body = Map.of(
    "produktId", "42", "menge", "3");
redisTemplate.opsForStream()
    .add(StreamRecords.string(body)
        .withStreamKey("bestellungen"));

<em>// Consumer Group erstellen (einmalig)</em>
redisTemplate.opsForStream().createGroup(
    "bestellungen", "lager-service");

<em>// Nachrichten lesen</em>
List<MapRecord<String, String, String>> records =
    redisTemplate.opsForStream().read(
        Consumer.from("lager-service", "instanz-1"),
        StreamReadOptions.empty().count(10),
        StreamOffset.create("bestellungen",
            ReadOffset.lastConsumed()));
Code-Sprache: JavaScript (javascript)

Im Gegensatz zu Pub/Sub bleiben Nachrichten in Streams erhalten und können von mehreren Consumer Groups unabhängig konsumiert werden. Spring Data Redis unterstützt Streams nativ über opsForStream().

Spring Session mit Redis

Session-Management mit Redis verteilt HTTP-Sessions über mehrere Server-Instanzen, ohne dass der Client an eine bestimmte Instanz gebunden wird (Sticky Sessions):

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>
Code-Sprache: HTML, XML (xml)

Konfiguration:

spring.session.store-type=redis
spring.session.redis.flush-mode=on_save
spring.session.timeout=30m

Danach ist jede HTTP-Session automatisch in Redis gespeichert – alle Server-Instanzen teilen sich die Sessions. Ein Load Balancer kann Requests frei verteilen, ohne dass der Benutzer seinen Login verliert. Aufräumen übernimmt Redis über den TTL-Mechanismus.

Performance-Vergleich

OperationRedis (lokal)PostgreSQLFaktor
Einfaches GET~0,1 ms~2 ms20×
Query mit Index~0,5 ms~5 ms10×
Schreiben (single)~0,3 ms~8 ms25×

Die Zahlen variieren je nach Hardware und Netzwerk, aber die Größenordnung macht klar: Redis ist für Hot-Paths und Caching ideal.

Fazit

Redis ergänzt klassische relationale Datenbanken ideal. Als Caching-Layer reduziert es die Last auf PostgreSQL/MySQL, als Pub/Sub-Broker ermöglicht es ereignisgesteuerte Architekturen, und als Session-Store entkoppelt es den Anwendungszustand vom Server. Spring Data Redis abstrahiert die Redis-Kommunikation hinter gewohnten Spring-Idiomen wie @CacheableRedisTemplate und MessageListenerAdapter. Die nahtlose Integration macht Redis zur ersten Wahl für performante Java-Anwendungen.

Hinweis zur Lizenz: Seit Version 7.4 (März 2024) ist Redis nicht mehr unter der BSD-Lizenz verfügbar, sondern dual lizenziert unter RSALv2 und SSPLv1. Für die meisten Entwickler ändert sich dadurch nichts – interne und persönliche Nutzung bleibt frei. Wer eine echte Open-Source-Alternative sucht, findet mit Valkey (Linux Foundation) einen kompatiblen Fork unter BSD-Lizenz.