由於緩存通常應用在不頻繁異動的資料上,所以不應該每次都向第三方緩存服務取得資料,而是透過 MQ Service 廣播和訂閱訊息功能,發布註銷的事件,將對應的資料清除,大幅提高系統效能,降低龐大架構的維護成本
SpringBootApplication
@EnablePolarBearCache
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
CacheConfig
public class CacheConfig {
@Bean
@Primary
public PolarBearCacheManager polarBearCacheManager() {
return new BasicCacheManager();
}
}
The architecture of multiple services needs to send evict events to other services through EventService.
SpringBootApplication
@EnablePolarBearCache
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
CacheEventServiceImpl
Redis example.
public class CacheEventServiceImpl extends PolarBearCacheEventService implements InitializingBean {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisMessageListenerContainer redisMessageListenerContainer;
@Autowired
private DefaultClientResources defaultClientResources;
private final String topic = "cache";
@Override
public void afterPropertiesSet() throws Exception {
defaultClientResources.eventBus().get().subscribe((event) -> {
if (event instanceof ConnectedEvent) {
publishConnectedEvent();
}
});
}
@Override
public void send(String body) {
stringRedisTemplate.convertAndSend(topic, body);
}
@Override
public void addListener(Consumer<String> listener) {
redisMessageListenerContainer.addMessageListener((message, pattern) -> {
log.info("pattern:{},message:{}", new String(pattern), message);
listener.accept(new String(message.getBody()));
}, new PatternTopic(topic));
}
}
CacheConfig
public class CacheConfig {
@Bean
public PolarBearCacheEventService polarBearCacheEventService() {
return new CacheEventServiceImpl();
}
@Bean
@Primary
public PolarBearCacheManager polarBearCacheManager() {
return new BasicCacheManager();
}
}
Reference Spring Cacheable
@Cacheable
一般
public class UserService {
@Cacheable(
cacheNames = "User"
, key = "#id"
, condition = "#id != null"
, unless = "#result==null"
)
public User find(Integer id) {
// TODO
}
}
時效性
import pers.clare.polarbearcache.annotation.CacheAlive;
public class UserService {
@CacheAlive("PT30S")
@Cacheable(
cacheNames = "User"
, key = "#id"
, condition = "#id != null"
, unless = "#result==null"
)
public User find(Integer id) {
// TODO
}
}
@CacheEvict
如果有配置 Event Service 時,會將 Evict Event 廣播給其他使用相同配置的服務
一般
public class UserService {
@CacheEvict(
cacheNames = "User"
, key = "#user.id"
, condition = "#user.id != null"
)
public void update(User user) {
//TODO
}
}
BeeCacheDependencies
It also clears itself when dependency cache triggers the evict event.
public class TestService implements InitializingBean {
@Autowired
private PolarBearCacheDependencies cacheDependencies;
@Override
public void afterPropertiesSet() {
// Test cache depends on user cache
cacheDependencies.depend("Test", (key) -> {
// Convert key
return key;
}, "User");
}
}
註冊 Evict 的事件處理
當本地有該緩存資源時,則會觸發 handler 取得最新資料,直接更新緩存,避免同時請求造成多次查詢或者鎖的等待。
public class UserService implements InitializingBean {
@Autowired
private PolarBearCacheManager cacheManager;
@Override
public void afterPropertiesSet() {
cacheManager.<User>onEvict(UserCacheKey, (key, data) -> find(data.getId()));
}
}