مقدمة: لماذا نحتاج إلى التخزين المؤقت في Java؟
\nفي التطوير الحديث عالي التحميل، سرعة الوصول إلى البيانات هي عامل حاسم. كل طلب إلى قاعدة البيانات أو API خارجي يزيد من وقت الاستجابة والتحميل على البنية التحتية. التخزين المؤقت في Java يسمح بتخزين البيانات المطلوبة بشكل متكرر في ذاكرة سريعة (RAM)، مما يقلل وقت الاستجابة من عشرات الميلي ثانية إلى ميكروثانية.
\nفي هذه المقالة، سنستعرض ثلاث طرق رئيسية للتخزين المؤقت: الحلول المضمنة (HashMap، Caffeine، Ehcache)، Redis وMemcached. ستتعلم كيفية اختيار الأداة المناسبة، وسترى أمثلة عملية على الكود.
\n\n1. الحلول المضمنة للتخزين المؤقت في Java
\nللمشاريع الصغيرة أو التطبيقات أحادية الخيط، غالبًا ما تكون المجموعات المضمنة كافية. ومع ذلك، لبيئة الإنتاج، من الأفضل استخدام مكتبات متخصصة.
\n\n1.1. تخزين مؤقت بسيط باستخدام HashMap
\nأبسط طريقة هي استخدام ConcurrentHashMap مع إدارة يدوية لعمر البيانات. مناسب للنماذج الأولية، لكنه لا يحتوي على آليات للإزالة (eviction).
import java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.TimeUnit;\n\npublic class SimpleCache {\n private final ConcurrentHashMap<String, CacheEntry> cache = new ConcurrentHashMap<>();\n\n public void put(String key, Object value, long ttlMs) {\n cache.put(key, new CacheEntry(value, System.currentTimeMillis() + ttlMs));\n }\n\n public Object get(String key) {\n CacheEntry entry = cache.get(key);\n if (entry == null || System.currentTimeMillis() > entry.expiry) {\n cache.remove(key);\n return null;\n }\n return entry.value;\n }\n\n private record CacheEntry(Object value, long expiry) {}\n}\n\n1.2. Caffeine — تخزين مؤقت عالي الأداء لـ Java
\nCaffeine هي مكتبة حديثة، تُستخدم في Spring Cache. تدعم الإزالة التلقائية بناءً على الوقت والحجم وتكرار الاستخدام.
\nimport com.github.benmanes.caffeine.cache.Cache;\nimport com.github.benmanes.caffeine.cache.Caffeine;\nimport java.util.concurrent.TimeUnit;\n\npublic class CaffeineExample {\n public static void main(String[] args) {\n Cache<String, String> cache = Caffeine.newBuilder()\n .expireAfterWrite(10, TimeUnit.MINUTES)\n .maximumSize(1000)\n .build();\n\n cache.put("user_1", "أليكسي");\n String user = cache.getIfPresent("user_1");\n System.out.println(user); // أليكسي\n }\n}\n\n1.3. Ehcache — المعيار المؤسسي
\nEhcache هو حل ناضج يدعم التجميع (clustering) والتخزين الدائم على القرص. يُستخدم غالبًا مع Hibernate.
\nimport org.ehcache.Cache;\nimport org.ehcache.CacheManager;\nimport org.ehcache.config.builders.CacheConfigurationBuilder;\nimport org.ehcache.config.builders.CacheManagerBuilder;\nimport org.ehcache.config.builders.ResourcePoolsBuilder;\n\npublic class EhcacheExample {\n public static void main(String[] args) {\n CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()\n .withCache("users",\n CacheConfigurationBuilder.newCacheConfigurationBuilder(\n String.class, String.class,\n ResourcePoolsBuilder.heap(100))\n ).build();\n cacheManager.init();\n\n Cache<String, String> cache = cacheManager.getCache("users", String.class, String.class);\n cache.put("user_2", "ماريا");\n System.out.println(cache.get("user_2")); // ماريا\n\n cacheManager.close();\n }\n}\n\n2. Redis — التخزين المؤقت الموزع لـ Java
\nRedis هو مخزن بيانات في الذاكرة (in-memory) يعمل كخادم منفصل