Part 03 · Spring Framework & Spring Boot · 3.1.09

Async, events, scheduling và cache

Các abstraction này làm code ngắn hơn nhưng không xóa thread, queue, transaction, delivery hay consistency semantics. Production design phải chỉ rõ ownership và failure behavior.


@Async và executor

AsyncAnnotationBeanPostProcessor tạo proxy submit method vào TaskExecutor; self-invocation không async. Return Future hoặc CompletableFuture để caller quan sát lỗi; void method cần AsyncUncaughtExceptionHandler.

Executor concernYêu cầu production
CapacityBounded threads và queue dựa trên workload.
OverloadRejection policy, backpressure hoặc load shedding rõ.
ObservabilityTên thread, active/queued/rejected metrics và task duration.
ShutdownDừng nhận task, drain có timeout rồi hủy có kiểm soát.
ContextSecurity, MDC, locale và transaction không tự truyền đầy đủ; propagate và cleanup có chủ đích.

Application events

ApplicationEventPublisher mặc định gọi listeners đồng bộ trên caller thread, nên listener exception có thể ảnh hưởng publisher. Async listener đổi thread và transaction semantics. @TransactionalEventListener bind với phase như AFTER_COMMIT, nhưng không bảo đảm durable delivery; process crash vẫn có thể làm mất event.

Integration event: event nội bộ của ApplicationContext không thay message broker hoặc Outbox. Nếu consumer ngoài process phải nhận, cần durable record, retry và idempotency.

Scheduling trong một instance và cluster

@Scheduled dùng TaskScheduler: fixed rate đo giữa thời điểm start, fixed delay đo sau completion, cron phụ thuộc clock và timezone. Trong cluster, mỗi instance đều chạy job nếu không có leader election, distributed scheduler hoặc lock.

Cache abstraction

@Cacheable tạo key, lookup, gọi target khi miss rồi put; @CachePut luôn gọi target và cập nhật cache; @CacheEvict invalidates entries. Đây cũng là proxy advice nên self-invocation có cùng giới hạn.

Spring cache abstraction không định nghĩa TTL, serialization, eviction capacity, stampede hay distributed consistency; provider và configuration quyết định các behavior này.

Key và invalidation

Key phải gồm tenant, version và arguments ổn định; không dùng mutable object hoặc toString() không ổn định. Việc cache null và errors phải có chủ đích. Update DB rồi evict cache có race; transaction-aware cache hoặc event invalidation vẫn cần thiết kế khi event/eviction fail.

Cache stampede: nhiều request cùng miss có thể đồng thời gọi dependency. Cân nhắc per-key synchronization, request coalescing, jittered TTL, stale-while-revalidate hoặc rate limiting tùy provider và freshness requirement.

Retry và advice ordering

Spring Framework core không tự làm mọi async/cache operation resilient. Khi dùng retry library, xác định exception retryable, attempts, exponential backoff, jitter, deadline và idempotency. Không retry validation, authentication hoặc permanent failure.

Ordering với transaction thay semantics: retry ngoài transaction có thể tạo transaction mới mỗi attempt; retry trong transaction có thể tiếp tục trên rollback-only state. Test call chain và side effects thay vì chỉ kiểm số lần gọi.

Nguồn tham khảo