التخزين المؤقت في Kotlin: Redis والحلول الأخرى
التخزين المؤقت هو أحد الآليات الرئيسية لتحسين الأداء في التطبيقات الحديثة. في نظام Kotlin البيئي، وبفضل التوافق الكامل مع Java ومكتبات JVM الغنية، تتوفر جميع الأدوات الأساسية للعمل مع التخزين المؤقت. في هذه المقالة، سننظر في كيفية تنظيم التخزين المؤقت في Kotlin باستخدام Redis وCaffeine وEhcache، وسنحلل متى نختار أي أداة.
لماذا نحتاج إلى التخزين المؤقت؟
يسمح التخزين المؤقت بتقليل وقت استجابة التطبيق عن طريق تخزين البيانات المطلوبة بشكل متكرر في ذاكرة سريعة الوصول. هذا مهم بشكل خاص لـ:
- واجهات REST API عالية التحميل؛
- العمل مع واجهات API الخارجية وقواعد البيانات؛
- العمليات الحسابية كثيفة الموارد؛
- بيانات جلسات المستخدمين.
الاستراتيجيات الأساسية للتخزين المؤقت
قبل اختيار المكتبة، من المهم فهم الاستراتيجيات الأساسية:
- Cache-Aside — يدير التطبيق التخزين المؤقت بنفسه: يتحقق أولاً من التخزين المؤقت، وفي حالة عدم وجود البيانات، يقوم بتحميلها من قاعدة البيانات ويضعها في التخزين المؤقت.
- Read-Through — يقوم التخزين المؤقت تلقائياً بتحميل البيانات من المصدر في حالة عدم وجودها.
- Write-Through / Write-Behind — كتابة البيانات في وقت واحد (أو بشكل غير متزامن) في التخزين المؤقت وفي التخزين الرئيسي.
1. Redis من Kotlin
Redis هو مخزن key-value في الذاكرة، يُستخدم غالباً كتخزين مؤقت موزع. للعمل مع Redis في Kotlin، يُستخدم العميل Lettuce (غير متزامن، تفاعلي) أو Jedis (متزامن).
ربط Lettuce
// build.gradle.ktsimplementation("io.lettuce:lettuce-core:6.3.2.RELEASE")مثال على العمل مع Redis عبر Lettuce (Kotlin)
import io.lettuce.core.RedisClientimport io.lettuce.core.api.coroutines
suspend fun main() { val client = RedisClient.create("redis://localhost:6379") val connection = client.connect() val commands = connection.coroutines() // واجهة برمجة تطبيقات coroutines
// كتابة commands.setex("user:123:profile", 3600, "{\\"name\\":\\"Alice\\"}") // قراءة val cached = commands.get("user:123:profile") println("من التخزين المؤقت: $cached") connection.close() client.shutdown()}متى نستخدم Redis؟
- عند الحاجة إلى تخزين مؤقت موزع بين عدة نسخ من التطبيق.
- عند الحاجة إلى درجة عالية من تحمل الأخطاء والنسخ المتماثل.
- عند الحاجة إلى أن تكون البيانات متاحة بعد إعادة تشغيل التطبيق (استمرارية Redis).
- عند الحاجة إلى دعم الهياكل المعقدة (القوائم، المجموعات، قوائم الانتظار).
2. Caffeine — تخزين مؤقت محلي عالي الأداء
Caffeine هي مكتبة للتخزين المؤقت في الذاكرة على JVM، مكتوبة بلغة Java. غالباً ما تُستخدم مع Spring Boot، ولكنها تعمل بشكل ممتاز أيضاً مع Kotlin النقي. توفر Caffeine زمن وصول شبه معدوم عند القراءة.
ربط Caffeine
// build.gradle.ktsimplementation("com.github.ben-manes.caffeine:caffeine:3.1.8")مثال على استخدام Caffeine في Kotlin
import com.github.benmanes.caffeine.cache.Caffeineimport java.util.concurrent.TimeUnit
data class User(val id: Int, val name: String)
fun createCache(): Caffeine<Int, User>.() -> Unit = { maximumSize(10_000) expireAfterWrite(10, TimeUnit.MINUTES) recordStats()}
val userCache = Caffeine.newBuilder() .maximumSize(10_000) .expireAfterWrite(10, TimeUnit.MINUTES) .build<Int, User>()
fun getUserFromCache(id: Int): User? { return userCache.getIfPresent(id)}
fun putUser(id: Int, user: User) { userCache.put(id, user)}
// مثال مع التحميل التلقائي (LoadingCache)val loadingCache = Caffeine.newBuilder() .maximumSize(5_000) .build<Int, User>