Caching-Redis and Caffeine cache
Spring Boot Cache with Redis
Redis Cache
effectively stores the results of database retrieval operations, allowing
subsequent requests to retrieve the data directly from the cache. This
significantly enhances application performance by reducing unnecessary database
calls.
When a
request is made, the service initially looks in the Redis cache for the desired
data. When a cache hit occurs, the data is swiftly retrieved from the cache and
promptly provided back to the service, avoiding the need to interact with the
database.
However, if
the requested data is not found in the cache (cache miss), the service
intelligently falls back to the database to retrieve the required information.
Subsequently, the fetched data is stored in the Redis cache, enabling future
requests for the same data to be served directly from the cache, thereby
eliminating further database queries and speeding up overall response times.
Time To
Live(TTL): time-to-live property, which is an optional setting that allows us
to set the expiration time for cached data. After the specified time has
elapsed, the cached entry is automatically removed from the cache.
Steps for the implementation:
Step 1: Add Redis dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>3.1.2</version>
</dependency>
Step 2:
Configure Redis using application.yml
Step 3: Creating entity and
repository
Set up the
entity and repository to perform CRUD operations like any other Spring Boot
project. Since Redis is an in-memory database, we need to transform our
object into a stream of bytes for storing as well as the other way around for
retrieving data. Therefore, we need to serialize/deserialize
@Entity
public class Product implements Serializable {
@Id
@GeneratedValue(strategy =
GenerationType.IDENTITY)
private long id;
private String name;
private String code;
private int quantity;
private double price;
}
Step 4:
Enable caching in spring boot
Add the
annotation @EnableCaching to the starter class. It will trigger a
post-processor that inspects every Spring bean for the presence of caching
annotations on public methods.
@SpringBootApplication
@EnableCaching
public class RedisDemoApplication {
public static void main(String[] args)
{
SpringApplication.run(RedisDemoApplication.class, args);
}
}
Step 5:
Annotation-based caching on the controller layer
Use caching annotations in the controller layer to enable caching for specific methods:
1. @Cacheable is employed to fetch data from the database, storing it in the cache. Upon future invocations, the method retrieves the cached value directly, eliminating the need to execute the method again.
@GetMapping("/product/{id}")
@Cacheable(value = "product", key =
"#id")
public Product getProductById(@PathVariable long id) {...}
The value attribute
establishes a cache with a specific name, while the key attribute
permits the use of Spring Expression Language to compute the key dynamically.
Consequently, the method result is stored in the ‘product’ cache, where
respective ‘product_id’ serves as the unique key. This approach optimizes
caching by associating each result with a distinct key.
2. @CachePut is used to update data in the
cache when there is any update in the source database.
@PutMapping("/product/{id}")
@CachePut(cacheNames = "product", key = "#id")
public Product editProduct(@PathVariable long id, @RequestBody Product product)
{...}
The cacheNames attribute
is an alias for value, and can be used in a similar manner.
3. @CacheEvict is used for removing stale or
unused data from the cache.
@DeleteMapping("/product/{id}")
@CacheEvict(cacheNames = "product", key = "#id",
beforeInvocation = true)
public String removeProductById(@PathVariable long id) {...}
Caffeine cache vs redis cache:
Caffeine and Redis represent two distinct approaches to caching, each with its
own strengths and use cases.
Caffeine Cache:
- Type:
In-memory,
local cache. Each application instance maintains its own separate cache.
- Performance:
Extremely
fast, as it operates within the application's JVM and avoids network overhead.
- Suitability:
Ideal for
caching frequently accessed data within a single application instance, reducing
database queries and improving response times for local operations.
- Limitations:
Limited by
the memory available to the individual application instance. Data is not
shared across multiple instances, leading to potential data inconsistency in
distributed environments.
- Language Specificity:
Primarily
designed for Java applications.
Redis:
- Type:
In-memory,
distributed data store. Data is stored in a central server accessible by
multiple application instances.
- Performance:
Fast, but
involves network latency due to remote access. Performance can be
optimized through proper configuration and network design.
- Suitability:
Excellent for
distributed caching, where data needs to be shared and consistent across
multiple application instances or services. Provides scalability and
advanced features like persistence, replication, and pub/sub messaging.
- Limitations:
Introduces
network overhead compared to local caches. Memory usage is limited by the
Redis server's resources.
- Language Agnosticism:
Can be
accessed and utilized by applications written in various programming languages.
Key
Differences Summarized:
|
Feature |
Caffeine
Cache (Local) |
Redis
(Distributed) |
|
Scope |
Single
application instance |
Multiple
instances/services |
|
Location |
Within
application JVM |
Separate
server |
|
Data
Sharing |
No (per
instance) |
Yes (shared
across instances) |
|
Performance |
Extremely
fast (no network) |
Fast
(network latency) |
|
Scalability |
Limited by
instance memory |
Highly
scalable |
|
Consistency |
Local
consistency only |
Distributed
consistency |
|
Language |
Primarily
Java |
Language-agnostic |
Comments
Post a Comment