one-light-cache
is a lightweight distributed caching framework built on top of Caffeine and Redisson. It provides a
unified cache management interface and solves common distributed caching challenges like cache consistency, cache
penetration, and cache avalanche.
- Centralized local cache management through
LightCacheManager
- Support for both code-based and configuration-based cache creation
- Redis integration as a remote cache layer
- Support for RocketMQ/Redis Pub/Sub messaging
- Eventual consistency guarantee in distributed environments
- Distributed lock-based cache update strategy
- Cache penetration prevention (distributed locks + two-level cache)
- Cache avalanche prevention (staggered expiration)
- Cache penetration prevention (null value caching)
- Support for YAML configuration and code configuration
- Customizable cache parameters (capacity, expiration time, etc.)
- Support for Aviator expressions for cache loading
<dependency>
<groupId>com.oneinstep.light</groupId>
<artifactId>light-cache-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
@SpringBootApplication
@EnableLightCache
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
light:
cache:
producer-group: my-cache-producer-group
consumer-group: my-cache-consumer-group
rocketmq-name-server: localhost:9876
use-redis-as-cache: true
kafka-bootstrap-servers: localhost:9092
cache-configs:
- cacheName: test-user
initial-capacity: 20
maximum-size: 100
expire-after-write: 5000
load-cache-expression: getUserById(key)
mq-topic: user_data_change
mq-type: REDIS
LightCacheManager.<User>newCacheBuilder()
.cacheName("user-cache")
.initialCapacity(10)
.maximumSize(100)
.expireAfterWrite(5000)
.fetcher(userId -> userService.getUser(userId))
.mqTopic("user_data_change")
.mqType(MQType.REDIS)
.buildAndRegister();
// Using cache
LightCache<User> cache = cacheManager.getCache("user-cache");
User user = cache.get("123");
+----------------+
| Application |
+----------------+
↓
+----------------+ +-----------------+
| Local Cache | → | Redis Cache |
| (Caffeine) | | (Redisson) |
+----------------+ +-----------------+
↓
+-----------------+
| Data Source |
| (DB/RPC) |
+-----------------+
- Local Cache Expiration: Prioritize fetching from Redis, use distributed locks when Redis has no data
- Data Changes: Notify all nodes through message queues to update cache, ensuring eventual consistency
- Penetration Prevention: Use distributed locks to ensure only one node queries the data source
- Null Value Handling: Set short expiration times for null values to prevent cache penetration
-
High Concurrency Read
- Product details
- User information
- Configuration data
-
Distributed Environment
- Multi-node deployment
- Cache consistency requirements
- Cache penetration prevention
// Method 1: Lambda expression
.fetcher(userId -> userService.getUser(userId))
// Method 2: Aviator expression
.loadCacheExpression("getUserById(key)")
// Send cache update message
DataChangeMsg msg = DataChangeMsg.builder()
.dataName("user-cache")
.dataId(userId)
.type(DataChangeType.UPDATE)
.build();
mqProducer.sendMsg("user_topic", JSON.toJSONString(msg));
- Cache hit rate
- Loading time
- Concurrent loading count
-
Cache Consistency
- Framework provides eventual consistency guarantee
- Send cache update message immediately after updating DB
- Critical business should query data source directly
-
Performance Optimization
- Set reasonable cache capacity and expiration time
- Avoid caching large objects
- Regular cleanup of expired data
-
Exception Handling
- Cache loading timeout settings
- Fallback processing
- Log monitoring