Belajar Spring - Integrasi Redis dengan Spring Boot dan JedisPool - Java Community

Belajar Spring - Integrasi Redis dengan Spring Boot dan JedisPool

Redis, sebagai salah satu solusi in-memory database yang populer, telah menjadi andalan dalam membangun aplikasi dengan kebutuhan akses data cepat dan efisien. Dalam artikel ini, kita akan menjelajahi cara mengintegrasikan Redis dengan Spring Boot, mulai dari konfigurasi dasar, optimasi pooling menggunakan Jedis, hingga implementasi fitur Redis Streams untuk keperluan messaging dan event-driven architecture. Panduan ini ditujukan untuk membantu Anda memahami konsep Redis dengan pendekatan yang praktis dan langsung diimplementasikan.

Dependency

Tambahkan Dependency Redis di Spring: Di file pom.xml, tambahkan dependency Redis Spring Data.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>5.1.3</version>
</dependency>

Properties

Konfigurasi Redis di Aplikasi: Tambahkan konfigurasi Redis di file application.properties atau application.yml

server.port=8080

spring.data.redis.host=localhost
spring.data.redis.port=6379

Configuration

@Component
@ConfigurationProperties(prefix = "spring.data.redis")
@Getter
@Setter
public class RedisProperties {
    private String host;
    private int port;
}
@Configuration
@EnableRedisRepositories
public class RedisConfig {

    @Autowired
    private RedisProperties redisProperties;

    @Bean
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(10);
        poolConfig.setMaxIdle(5);
        poolConfig.setMinIdle(1);
        return poolConfig;
    }

    @Bean
    public JedisConnectionFactory jedisConnectionFactory() {
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
        configuration.setHostName(redisProperties.getHost());
        configuration.setPort(redisProperties.getPort());

        JedisClientConfiguration clientConfig = JedisClientConfiguration.builder()
                .usePooling()
                .poolConfig(jedisPoolConfig())
                .build();

        return new JedisConnectionFactory(configuration, clientConfig);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());

        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());

        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

        template.setEnableTransactionSupport(true);
        template.afterPropertiesSet();

        return template;
    }
}

Penjelasan

Anotasi dan Konfigurasi
  • @Configuration: Menandakan bahwa class ini adalah konfigurasi Spring yang akan menyediakan bean untuk aplikasi.
  • @EnableRedisRepositories: Mengaktifkan repositori Redis di Spring, memungkinkan pengelolaan data Redis menggunakan repositori mirip JPA.

JedisPoolConfig

JedisPoolConfig adalah konfigurasi untuk Jedis Connection Pool, yang digunakan untuk memanage koneksi Redis. Connection pool berguna untuk meningkatkan kinerja dengan meminimalkan waktu yang diperlukan untuk membuka dan menutup koneksi Redis setiap kali digunakan.

  • setMaxTotal(10): Maksimum total koneksi yang diperbolehkan dalam pool.
  • setMaxIdle(5): Maksimum jumlah koneksi idle yang dapat dipertahankan dalam pool.
  • setMinIdle(1): Minimum jumlah koneksi idle yang dipertahankan.

Kelebihan

  • Dengan pooling, efisiensi koneksi meningkat karena mengurangi overhead pembukaan dan penutupan koneksi Redis secara terus-menerus.

Kekurangan

  • Pada aplikasi berskala besar dengan traffic tinggi, konfigurasi pooling ini mungkin perlu dioptimalkan lebih lanjut untuk menghindari connection exhaustion (kehabisan koneksi).

JedisConnectionFactory

JedisConnectionFactory bertanggung jawab untuk menyediakan koneksi ke Redis menggunakan Jedis sebagai klien Redis.

  • RedisStandaloneConfiguration: Konfigurasi Redis dalam mode standalone, di mana Redis berjalan sebagai instance tunggal (bukan cluster atau sentinel).
  • JedisClientConfiguration digunakan untuk mengatur konfigurasi tambahan, seperti menggunakan connection pooling. poolConfig(jedisPoolConfig()) menghubungkan konfigurasi pooling yang sudah dibuat di bean sebelumnya.

RedisTemplate

RedisTemplate adalah kelas template yang menyediakan API tingkat tinggi untuk bekerja dengan Redis. Ini adalah template yang memudahkan operasi seperti menyimpan, mengambil, dan memodifikasi data di Redis.

  • setConnectionFactory(jedisConnectionFactory()): Mengatur koneksi Redis dari JedisConnectionFactory.
  • KeySerializer dan HashKeySerializer menggunakan StringRedisSerializer, yang mengubah kunci menjadi string (umumnya UTF-8) agar lebih mudah terbaca.
  • ValueSerializer dan HashValueSerializer menggunakan GenericJackson2JsonRedisSerializer, yang mengonversi nilai menjadi JSON dengan bantuan Jackson. Ini memungkinkan data kompleks diubah menjadi JSON dan disimpan dalam Redis, serta diambil kembali dalam bentuk asli.
  • setEnableTransactionSupport(true): Mengaktifkan dukungan transaksi pada RedisTemplate. Ini memungkinkan Anda melakukan operasi Redis di dalam transaksi atomic

Kelebihan

  • Efisiensi Koneksi: Penggunaan connection pool (JedisPoolConfig) memungkinkan aplikasi menangani banyak koneksi Redis dengan efisien.
  • Kemudahan Serialization: Menggunakan JSON untuk serialisasi memudahkan penyimpanan dan pengambilan data kompleks di Redis.
  • Dukungan Transaksi: Mengaktifkan dukungan transaksi memberi kemampuan untuk melakukan operasi Redis dalam satu unit transaksi.
  • Scalability: Karena Redis digunakan dalam mode standalone, konfigurasi ini cocok untuk aplikasi yang sedang berkembang dan memungkinkan scaling dengan mode cluster jika dibutuhkan di masa depan.

Kekurangan

  • Stand-alone Redis: Redis dikonfigurasi dalam mode standalone. Untuk lingkungan produksi dengan skala besar, mungkin Anda ingin mempertimbangkan mode Redis Cluster atau Redis Sentinel untuk ketersediaan yang lebih tinggi dan skalabilitas.
  • Complexity with JSON Serialization: Menggunakan JSON sebagai serializer mungkin menambah sedikit overhead dalam hal konversi data, meskipun biasanya tidak signifikan kecuali untuk dataset besar.

DTO

Pertama, kita buat class Produk yang akan kita simpan di Redis. Gunakan anotasi @Data dari Lombok agar kita tidak perlu menuliskan getter dan setter secara manual.

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@RedisHash("Produk")
public class Produk implements Serializable {
    private String id;
    private String kode;
    private String nama;
}

Repository

Buat repository untuk mengelola produk menggunakan RedisTemplate.

public interface ProdukRepository {
    void save(Produk produk);
    Produk findById(String id);
    List<Produk> findAll();
    void delete(String id);
}
@Repository
public class ProdukRepositoryImpl implements ProdukRepository {
    public static final String HASH_KEY = "Produk";

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void save(Produk produk) {
        redisTemplate.opsForHash().put(HASH_KEY, produk.getId(), produk);
    }

    @Override
    public Produk findById(String id) {
        return (Produk) redisTemplate.opsForHash().get(HASH_KEY, id);
    }

    @Override
    public List<Produk> findAll() {
        return (List<Produk>) redisTemplate.opsForHash().values(HASH_KEY);
    }

    @Override
    public void delete(String id) {
        redisTemplate.opsForHash().delete(HASH_KEY, id);
    }
}

Rest API

Buat controller untuk memfasilitasi permintaan HTTP seperti POST, GET, PUT, dan DELETE.

@RestController
@RequestMapping("/api/produk")
public class ProdukAPI {

    @Autowired
    private ProdukRepository produkRepository;

    @GetMapping("/list")
    public ResponseEntity<List<Produk>> findAll() {
        List<Produk> produkList = produkRepository.findAll();
        if(produkList.isEmpty()) {
            return ResponseEntity.noContent().build();
        }
        return ResponseEntity.ok(produkList);
    }

    @GetMapping("/search")
    public ResponseEntity<Produk> findById(@RequestParam(value = "id") String id) {
        Produk produk = produkRepository.findById(id);
        if(produk == null) {
            return ResponseEntity.noContent().build();
        }
        return ResponseEntity.ok(produk);
    }

    @PostMapping("/create")
    public ResponseEntity<Produk> save(@RequestBody Produk produk) {
        produk.setId(UUID.randomUUID().toString());
        produkRepository.save(produk);
        return ResponseEntity.ok(produk);
    }

    @DeleteMapping("/delete")
    public ResponseEntity<Produk> delete(@RequestParam(value = "id") String id) {
        Produk produk = produkRepository.findById(id);
        if(produk == null) {
            return ResponseEntity.noContent().build();
        }
        produkRepository.delete(id);
        return ResponseEntity.ok(produk);
    }
}

Dengan memanfaatkan integrasi Redis di Spring Boot, Anda dapat meningkatkan kinerja aplikasi dengan memanfaatkan caching yang efisien, transaksi Redis, dan arsitektur pesan berbasis event melalui Redis Streams. Konfigurasi yang tepat, seperti menggunakan pooling pada JedisConnectionFactory, dapat memberikan optimasi lebih lanjut untuk aplikasi yang menangani ratusan atau bahkan ribuan permintaan per detik. Semoga tutorial ini membantu Anda dalam memahami dan mengimplementasikan Redis secara efektif dalam aplikasi Spring Boot Anda.

Subscribe to receive free email updates:

0 Response to "Belajar Spring - Integrasi Redis dengan Spring Boot dan JedisPool"

Posting Komentar