التخزين المؤقت في Java: Redis وMemcached والحلول المدمجة: المستوى المتقدم
\n\nالتخزين المؤقت هو أحد الأدوات الرئيسية لتحسين أداء وقابلية التوسع لتطبيقات Java. على المستوى المتقدم، يواجه المطور خيارًا بين الأنظمة الموزعة (Redis, Memcached) وذاكرة التخزين المؤقت المدمجة خفيفة الوزن (Caffeine, Guava). في هذه المقالة، سنقوم بتحليل الاختلافات المعمارية، وسيناريوهات الاستخدام، وسنقدم أمثلة عملية على الكود لكل حل.
\n\n1. التخزين المؤقت المدمج: Caffeine وGuava
\n\nتعمل ذاكرة التخزين المؤقت المدمجة داخل JVM ولا تتطلب خدمات خارجية. إنها مثالية لتخزين البيانات المؤقتة التي لا تحتاج إلى المزامنة بين العقد.
\n\nCaffeine — المعيار الحديث
\nCaffeine هي مكتبة عالية الأداء للتخزين المؤقت في Java، والتي حلت محل Guava Cache. تستخدم خوارزمية Window TinyLFU لإزالة الإدخالات بكفاءة.
\n\n// تبعية Maven
// <dependency>
// <groupId>com.github.ben-manes.caffeine</groupId>
// <artifactId>caffeine</artifactId>
// <version>3.1.8</version>
// </dependency>
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.concurrent.TimeUnit;
public class CaffeineExample {
public static void main(String[] args) {
Cache<String, User> userCache = Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.maximumSize(10_000)
.recordStats()
.build();
// كتابة
userCache.put("user:123", new User("Alice", "alice@example.com"));
// قراءة
User user = userCache.getIfPresent("user:123");
System.out.println("Cached user: " + user);
// قراءة ذرية مع التحميل
User result = userCache.get("user:456", key -> loadUserFromDB(key));
}
private static User loadUserFromDB(String key) {
// محاكاة التحميل من قاعدة البيانات
return new User("Bob", "bob@example.com");
}
static class User {
private final String name;
private final String email;
User(String name, String email) {
this.name = name;
this.email = email;
}
@Override
public String toString() {
return "User{name='" + name + "', email='" + email + "'}";
}
}
}
\n\nGuava Cache — حل موثوق
\nتظل Guava Cache من Google خيارًا شائعًا للمشاريع التي تستخدم بالفعل مكتبة Guava. وهي تدعم استراتيجيات إزالة متنوعة ومستمعين.
\n\nimport com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class GuavaCacheExample {
public static void main(String[] args) throws ExecutionException {
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.expireAfterAccess(5, TimeUnit.MINUTES)
.maximumSize(5000)
.removalListener(notification ->
System.out.println("Removed: " + notification.getKey()))
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) {
return "Computed: " + key.toUpperCase();
}
});
// كتابة
cache.put("key1", "value1");
// قراءة مع التحميل التلقائي
String value = cache.get("key2");
System.out.println(value); // "Computed: KEY2"
}
}
\n\n2. التخزين المؤقت الموزع مع Redis
\n\nRedis هو