प्रौद्योगिकी साझेदारी

जावा स्थानीयसञ्चयम् (उच्चप्रदर्शनसेटिंग्) २.

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

जावा-जगति अनुप्रयोग-प्रदर्शनस्य उन्नयनार्थं कैशिंग्-प्रौद्योगिक्याः व्यापकरूपेण उपयोगः भवति, मुख्यतया दूरस्थ-कैशिंग्-स्थानीय-कैशिंग् इति द्वयोः वर्गयोः विभक्तम् अस्ति दूरस्थं संग्रहणं, उत्तमप्रदर्शनेन, लचीलतायाः च सह, प्रायः Redis, Memcached इत्यादीनां लोकप्रियसमाधानानाम् माध्यमेन कार्यान्वितं भवति । स्थानीय-सञ्चयस्य, लघु-द्रुत-प्रवेश-लक्षणैः सह, HashMap, Guava Cache, Caffeine, Ehcache इत्यादिभिः प्रौद्योगिकीभिः प्रतिनिधित्वं भवति ।

वयं भविष्येषु ब्लॉग्-पोष्ट्-मध्ये दूरस्थ-सञ्चयस्य रहस्यं गहनतया गमिष्यामः, परन्तु अद्य, स्थानीय-सञ्चय-विषये ध्यानं दद्मः । अयं लेखः प्रथमं भवन्तं व्यापकं अवलोकनं प्रदातुं स्थानीय-सञ्चय-प्रौद्योगिक्याः माध्यमेन नेष्यति । तदनन्तरं वयं प्रदर्शनस्य राजा इति प्रसिद्धे कैशिंग्-प्रौद्योगिक्यां गहनतया गमिष्यामः, तस्य पृष्ठतः सिद्धान्तान् कार्यान्वयनविधिश्च अन्वेषयिष्यामः । अन्ते व्यावहारिकप्रकरणानाम् एकस्याः श्रृङ्खलायाः माध्यमेन वयं प्रदर्शयिष्यामः यत् भवतः विकासदक्षतां अनुप्रयोगप्रदर्शनं च सुधारयितुम् एतासां उच्चप्रदर्शनस्थानीयकैशिंगप्रौद्योगिकीनां दैनिककार्यं कथं प्रभावीरूपेण कर्तुं शक्यते।

1. जावा स्थानीय संग्रहणम्

१.१ हैशमैप्

Map इत्यस्य अन्तर्निहितस्य कार्यान्वयनस्य उपयोगेन वयं प्रत्यक्षतया स्मृतौ संग्रहणीयानि वस्तूनि संग्रहीतुं शक्नुमः, यत् प्रत्यक्षं कुशलं च विधिः अस्ति ।

लाभ: एषा पद्धतिः सरलः प्रत्यक्षः च अस्ति, बाह्यपुस्तकालयानां उपरि अवलम्बं विना, अजटिलसञ्चयस्य आवश्यकताभिः सरलपरिदृश्यैः च अनुप्रयोगानाम् कृते अतीव उपयुक्ता अस्ति

हानि: तथापि, अस्मिन् पद्धत्या स्वचालित-सञ्चय-निराकरण-तन्त्रस्य अभावः अस्ति यदि अधिक-उन्नत-सञ्चय-रणनीतयः कार्यान्वितुं आवश्यकाः सन्ति, तर्हि अधिक-अनुकूलित-विकास-व्ययस्य आवश्यकता भवितुम् अर्हति ।

  1. public class LRUCache extends LinkedHashMap {
  2. /**
  3. * 可重入读写锁,保证并发读写安全性
  4. */
  5. private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
  6. private Lock readLock = readWriteLock.readLock();
  7. private Lock writeLock = readWriteLock.writeLock();
  8. /**
  9. * 缓存大小限制
  10. */
  11. private int maxSize;
  12. public LRUCache(int maxSize) {
  13. super(maxSize + 1, 1.0f, true);
  14. this.maxSize = maxSize;
  15. }
  16. @Override
  17. public Object get(Object key) {
  18. readLock.lock();
  19. try {
  20. return super.get(key);
  21. } finally {
  22. readLock.unlock();
  23. }
  24. }
  25. @Override
  26. public Object put(Object key, Object value) {
  27. writeLock.lock();
  28. try {
  29. return super.put(key, value);
  30. } finally {
  31. writeLock.unlock();
  32. }
  33. }
  34. @Override
  35. protected boolean removeEldestEntry(Map.Entry eldest) {
  36. return this.size() > maxSize;
  37. }
  38. }

१.२ अमरूदसञ्चयः

Guava Cache इति गूगलेन विकसितं कैशिंग्-प्रौद्योगिकी अस्ति यत् LRU (अल्पतमं सद्यः प्रयुक्तम्) प्रतिस्थापन-एल्गोरिदम् इत्यस्य आधारेण भवति । परन्तु कैफीनस्य उदयेन सह अमरूदस्य संग्रहः क्रमेण जनानां दृष्ट्या बहिः क्षीणः अभवत् । कैफीनः न केवलं अमरूद-सञ्चयस्य लाभं उत्तराधिकारं प्राप्नोति, अपितु अनेकेषु पक्षेषु अपि अस्य अतिक्रमणं करोति । यद्यपि अत्र विशिष्टः नमूनासङ्केतः न प्रदत्तः तथापि Guava Cache इत्यत्र रुचिं विद्यमानाः पाठकाः अधिकसूचनार्थं तस्य आधिकारिकजालस्थलं गन्तुं शक्नुवन्ति ।

लाभ: Guava Cache अधिकतमक्षमता सीमां निर्धारयितुं समर्थयति तथा च द्वौ अवधिसमाप्तिरणनीतिं प्रदाति: सम्मिलनसमयस्य अभिगमसमयस्य च आधारेण, तथा च केषाञ्चन मूलभूतसांख्यिकीयकार्यस्य समर्थनं करोति।

हानि: Spring Boot 2 तथा Spring 5 इत्येतयोः विमोचनेन सह Guava Cache इत्येतयोः द्वयोः कृते अनुशंसितं नास्ति ।

१.३ कैफीनम्

कैफीनः एकः मुक्तस्रोत-सञ्चय-प्रौद्योगिकी अस्ति या W-TinyLFU एल्गोरिदम् इत्यस्य उपयोगं करोति, यत् एकः संग्रहण-निराकरण-रणनीतिः अस्ति या LRU तथा LFU (कमतः न्यूनतया प्रयुक्ता आवृत्तिः) इत्येतयोः लाभं संयोजयति कैफीनस्य कैश-प्रदर्शनं सैद्धान्तिक-इष्टतम-समाधानस्य समीपे अस्ति तथा च अमरूद-सञ्चयस्य उन्नत-संस्करणरूपेण गणयितुं शक्यते ।

  1. public class CaffeineCacheTest {
  2. public static void main(String[] args) throws Exception {
  3. //创建guava cache
  4. Cache<String, String> loadingCache = Caffeine.newBuilder()
  5. //cache的初始容量
  6. .initialCapacity(5)
  7. //cache最大缓存数
  8. .maximumSize(10)
  9. //设置写缓存后n秒钟过期
  10. .expireAfterWrite(17, TimeUnit.SECONDS)
  11. //设置读写缓存后n秒钟过期,实际很少用到,类似于expireAfterWrite
  12. //.expireAfterAccess(17, TimeUnit.SECONDS)
  13. .build();
  14. String key = "key";
  15. // 往缓存写数据
  16. loadingCache.put(key, "v");
  17. // 获取value的值,如果key不存在,获取value后再返回
  18. String value = loadingCache.get(key, CaffeineCacheTest::getValueFromDB);
  19. // 删除key
  20. loadingCache.invalidate(key);
  21. }
  22. private static String getValueFromDB(String key) {
  23. return "v";
  24. }
  25. }

१.४ एहचाचे

Ehcache इति शुद्धं जावा-प्रक्रिया-अन्तर्गत-सञ्चय-रूपरेखा अस्ति यत् स्वस्य द्रुत-दक्ष-प्रदर्शनार्थं प्रसिद्धम् अस्ति । इदं व्यापकरूपेण ज्ञातं भवति तथा च Hibernate कृते पूर्वनिर्धारितसञ्चयप्रदातृरूपेण कार्यं करोति ।

लाभ : Ehcache कैश निष्कासन एल्गोरिदम् इत्यस्य विस्तृतश्रेणीं प्रदाति, यत्र LFU (कमतः न्यूनतया प्रयुक्तः), LRU (कमतः न्यूनतया प्रयुक्तः) तथा FIFO (प्रथमं अन्तः, प्रथमं बहिः) च सन्ति एतत् भिन्नप्रकारस्य संग्रहणसञ्चयस्य समर्थनं करोति, यथा in-heap cache, off-heap cache तथा disk cache, भिन्न-भिन्न-भण्डार-आवश्यकतानां अनुकूलतायै । तदतिरिक्तं, Ehcache अपि विविधसमूहसमाधानस्य समर्थनं करोति, यत् प्रभावीरूपेण आँकडासाझेदारीसमस्यायाः समाधानं करोति ।

हानि: यद्यपि एहकाचे बहुषु पक्षेषु उत्कृष्टतां प्राप्नोति तथापि प्रदर्शनस्य दृष्ट्या कैफीन इत्यस्मात् किञ्चित् न्यूनं भवति ।

  1. public class EncacheTest {
  2. public static void main(String[] args) throws Exception {
  3. // 声明一个cacheBuilder
  4. CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
  5. .withCache("encacheInstance", CacheConfigurationBuilder
  6. //声明一个容量为20的堆内缓存
  7. .newCacheConfigurationBuilder(String.class,String.class, ResourcePoolsBuilder.heap(20)))
  8. .build(true);
  9. // 获取Cache实例
  10. Cache<String,String> myCache = cacheManager.getCache("encacheInstance", String.class, String.class);
  11. // 写缓存
  12. myCache.put("key","v");
  13. // 读缓存
  14. String value = myCache.get("key");
  15. // 移除换粗
  16. cacheManager.removeCache("myCache");
  17. cacheManager.close();
  18. }
  19. }

 

2. उच्च-प्रदर्शन-सञ्चयम् कैफीनम्

२.१ सञ्चयप्रकारः

२.१.१ सञ्चयः

 

Cache<Key, Graph> cache = Caffeine.newBuilder()    .expireAfterWrite(10, TimeUnit.MINUTES)    .maximumSize(10_000)    .build();
// 查找一个缓存元素, 没有查找到的时候返回nullGraph graph = cache.getIfPresent(key);// 查找缓存,如果缓存不存在则生成缓存元素,  如果无法生成则返回nullgraph = cache.get(key, k -> createExpensiveGraph(key));// 添加或者更新一个缓存元素cache.put(key, graph);// 移除一个缓存元素cache.invalidate(key);

Cache अन्तरफलकं स्पष्टसन्धानस्य उपयोगेन संग्रहीततत्त्वानि अन्वेष्टुं, अद्यतनीकर्तुं, निष्कासयितुं च क्षमता प्रदाति । यदा संग्रहीतं तत्त्वं जनयितुं न शक्यते अथवा जननप्रक्रियायाः समये अपवादः क्षिप्तः भवति तथा च तत्त्वस्य जननम् विफलं भवति तदा cache.get null प्रेषयितुं शक्नोति ।

२.१.२ Cache लोडिंग्

LoadingCache<Key, Graph> cache = Caffeine.newBuilder()    .maximumSize(10_000)    .expireAfterWrite(10, TimeUnit.MINUTES)    .build(key -> createExpensiveGraph(key));
// 查找缓存,如果缓存不存在则生成缓存元素,  如果无法生成则返回nullGraph graph = cache.get(key);// 批量查找缓存,如果缓存不存在则生成缓存元素Map<Key, Graph> graphs = cache.getAll(keys);

 

LoadingCache इति Cache इत्यस्य cache कार्यान्वयनम् अस्ति यस्मिन् CacheLoader क्षमता योजिता अस्ति ।
यदि cache नास्ति तर्हि CacheLoader.load इत्यस्य माध्यमेन तत्सम्बद्धं cache element उत्पद्यते ।

२.१.३ Async Cache इति

AsyncCache<Key, Graph> cache = Caffeine.newBuilder()    .expireAfterWrite(10, TimeUnit.MINUTES)    .maximumSize(10_000)    .buildAsync();
// 查找一个缓存元素, 没有查找到的时候返回nullCompletableFuture<Graph> graph = cache.getIfPresent(key);// 查找缓存元素,如果不存在,则异步生成graph = cache.get(key, k -> createExpensiveGraph(key));// 添加或者更新一个缓存元素cache.put(key, graph);// 移除一个缓存元素cache.synchronous().invalidate(key);

AsyncCache Cache इत्यस्य अतुल्यकालिकं रूपम् अस्ति, यत् Executor कृते cache elements जनयितुं CompletableFuture प्रत्यागन्तुं च क्षमता प्रदाति । पूर्वनिर्धारितं थ्रेड् पूल् कार्यान्वयनम् ForkJoinPool.commonPool() अस्ति, परन्तु भवान् Caffeine.executor(Executor) पद्धतिं अधिलिखित्वा कार्यान्वितं कृत्वा स्वस्य थ्रेड् पूल् चयनं अनुकूलितुं अपि शक्नोति ।

२.१.४ Async Loading Cache इति

AsyncLoadingCache<Key, Graph> cache = Caffeine.newBuilder()    .maximumSize(10_000)    .expireAfterWrite(10, TimeUnit.MINUTES)    // 你可以选择: 去异步的封装一段同步操作来生成缓存元素    .buildAsync(key -> createExpensiveGraph(key));    // 你也可以选择: 构建一个异步缓存元素操作并返回一个future    .buildAsync((key, executor) -> createExpensiveGraphAsync(key, executor));
// 查找缓存元素,如果其不存在,将会异步进行生成CompletableFuture<Graph> graph = cache.get(key);// 批量查找缓存元素,如果其不存在,将会异步进行生成CompletableFuture<Map<Key, Graph>> graphs = cache.getAll(keys);

AsyncLoadingCache LoadingCache इत्यस्य अतुल्यकालिकं रूपम् अस्ति, यत् कैश-तत्त्वानि जनयितुं अतुल्यकालिक-भारस्य कार्यं प्रदाति ।

२.२ निष्कासनरणनीतिः

  • क्षमता आधारित

// 基于缓存内的元素个数进行驱逐LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()    .maximumSize(10_000)    .build(key -> createExpensiveGraph(key));
// 基于缓存内元素权重进行驱逐LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()    .maximumWeight(10_000)    .weigher((Key key, Graph graph) -> graph.vertices().size())    .build(key -> createExpensiveGraph(key));
  • काल आधारित

// 基于固定的过期时间驱逐策略LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()    .expireAfterAccess(5, TimeUnit.MINUTES)    .build(key -> createExpensiveGraph(key));LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()    .expireAfterWrite(10, TimeUnit.MINUTES)    .build(key -> createExpensiveGraph(key));
// 基于不同的过期驱逐策略LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()    .expireAfter(new Expiry<Key, Graph>() {      public long expireAfterCreate(Key key, Graph graph, long currentTime) {        // Use wall clock time, rather than nanotime, if from an external resource        long seconds = graph.creationDate().plusHours(5)            .minus(System.currentTimeMillis(), MILLIS)            .toEpochSecond();        return TimeUnit.SECONDS.toNanos(seconds);      }      public long expireAfterUpdate(Key key, Graph graph,           long currentTime, long currentDuration) {        return currentDuration;      }      public long expireAfterRead(Key key, Graph graph,          long currentTime, long currentDuration) {        return currentDuration;      }    })    .build(key -> createExpensiveGraph(key));
  • उद्धरणम् आधारीकृत्य

//key和缓存元素都不再存在其他强引用的时候驱逐LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()    .weakKeys()    .weakValues()    .build(key -> createExpensiveGraph(key));
// 当进行GC的时候进行驱逐LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()    .softValues()    .build(key -> createExpensiveGraph(key));

२.३ ताजगी तन्त्रम्

LoadingCache<Key, Graph> graphs = Caffeine.newBuilder()    .maximumSize(10_000)    .refreshAfterWrite(1, TimeUnit.MINUTES)    .build(key -> createExpensiveGraph(key));

ताजगीरणनीतिः केवलं LoadingCache इत्यत्र एव उपयोक्तुं शक्यते, यदि ताजगीकरणस्य समये cache-तत्त्वं पृष्टं भवति तर्हि तस्य पुरातनं मूल्यं अद्यापि प्रत्यागमिष्यति, तथा च ताजगीकृतं नूतनं मूल्यं यावत् तत्त्वस्य ताजगीकरणं न समाप्तं भवति तावत् न प्रत्यागमिष्यति

२.४ सांख्यिकी

Cache<Key, Graph> graphs = Caffeine.newBuilder() .maximumSize(10_000) .recordStats() .build();

Caffeine.recordStats() पद्धतेः उपयोगेन आँकडासंग्रहणं चालू कर्तुं शक्यते । Cache.stats() मेथड् CacheStats ऑब्जेक्ट् रिटर्न् करिष्यति, यस्मिन् केचन सांख्यिकीयसूचकाः सन्ति, यथा:

  • hitRate(): क्वेरी कैश हिट् दर

  • evictionCount(): निष्कासितानां संग्रहाणां संख्या

  • averageLoadPenalty(): नूतनमूल्यानां लोडीकरणाय यः औसतसमयः भवति

SpringBoot द्वारा प्रदत्तेन RESTful Controller इत्यनेन सह, भवान् Cache इत्यस्य उपयोगं सहजतया पृच्छितुं शक्नोति ।