التخزين المؤقت في Kotlin: Redis وMemcached والحلول المضمنة — من الألف إلى الياء
التخزين المؤقت هو أحد الأدوات الرئيسية لتحسين أداء التطبيقات. في نظام Kotlin البيئي، الذي يعمل فوق JVM وAndroid، تتوفر للمطور العديد من الحلول: من الأنظمة الموزعة (Redis، Memcached) إلى ذاكرات التخزين المؤقت المحلية المضمنة (Caffeine، Guava Cache، Ehcache). في هذه المقالة، سنشرح كيفية دمج كل منها في مشروع Kotlin، وسنقدم أمثلة على الكود وتوصيات للاختيار.
1. التخزين المؤقت المضمن على JVM: Caffeine وGuava Cache
للتخزين المؤقت المحلي في Kotlin، فإن أفضل خيار هو Caffeine — مكتبة عالية الأداء مكتوبة بلغة Java ومتوافقة تمامًا مع Kotlin. وهي تدعم الإزالة التلقائية بناءً على الوقت والحجم والأوزان. البديل هو Guava Cache من Google، لكن Caffeine أسرع (غالبًا بمقدار 2-3 مرات).
مثال: Caffeine + Kotlin
أضف التبعية في build.gradle.kts:
implementation("com.github.ben-manes.caffeine:caffeine:3.1.8")نقوم بإنشاء ذاكرة تخزين مؤقت بسعة 1000 عنصر مع مدة صلاحية (TTL) تبلغ 10 دقائق:
import com.github.benmanes.caffeine.cache.Caffeineimport java.util.concurrent.TimeUnit
val cache = Caffeine.newBuilder() .maximumSize(1000) .expireAfterWrite(10, TimeUnit.MINUTES) .build<String, String>()
// الاستخدامcache.put("user:42", "{\\"name\\":\\"Alice\\"}")val user = cache.getIfPresent("user:42")println(user) // {"name":"Alice"}مثال: Guava Cache + Kotlin
implementation("com.google.guava:guava:33.0.0-jre")import com.google.common.cache.CacheBuilderimport java.util.concurrent.TimeUnit
val guavaCache = CacheBuilder.newBuilder() .maximumSize(500) .expireAfterWrite(5, TimeUnit.MINUTES) .build<String, String>()
guavaCache.put("session:abc", "active")println(guavaCache.getIfPresent("session:abc")) // activeمتى تستخدم: لتخزين البيانات المؤقتة لمثيل واحد من التطبيق (مثل نتائج الحسابات المعقدة، الرموز المميزة، الإعدادات). غير مناسب للخدمات المصغرة ذات المثيلات المتعددة — حيث لا تتم مزامنة البيانات.
2. Redis — التخزين المؤقت الموزع للخدمات المصغرة
Redis هو مخزن من نوع "مفتاح-قيمة" في الذاكرة، يُستخدم كذاكرة تخزين مؤقت موزعة، ووسيط رسائل، وقاعدة بيانات. أفضل عميل لـ Kotlin هو Lettuce (غير متزامن، تفاعلي، آمن للخيوط).
التثبيت والاتصال
implementation("io.lettuce:lettuce-core:6.3.2.RELEASE")مثال: الاتصال والعمليات الأساسية
import io.lettuce.core.RedisClientimport io.lettuce.core.api.sync.RedisCommands
val client = RedisClient.create("redis://localhost:6379")val connection = client.connect()val commands: RedisCommands<String, String> = connection.sync()
// تعيين مفتاح مع مدة صلاحية (TTL) 60 ثانيةcommands.setex("user:123", 60, "{\\"name\\":\\"Bob\\"}")
// القراءةval data = commands.get("user:123")println(data) // {"name":"Bob"}
connection.close()client.shutdown()مثال: العميل التفاعلي (Kotlin Coroutines)
import io.lettuce.core.RedisClientimport io.lettuce.core.api.reactive.RedisReactiveCommandsimport kotlinx.coroutines.reactive.awaitFirstOrNull
suspend fun getFromRedis(key: String): String? { val client = RedisClient.create("redis://localhost:6379") val connection = client.connect() val reactive: RedisReactiveCommands<String, String> = connection.reactive()
val result = reactive.get(key).awaitFirstOrNull() connection.close() client.shutdown() return result}متى تستخدم: الأنظمة الموزعة، الخدمات المصغرة، الجلسات المشتركة، تحديد المعدل (rate limiting)، pu