内置缓存系统 AbsCache

在构建高性能的网络应用时,缓存系统起着至关重要的作用。Tio-boot 框架内置了一种轻量级的缓存系统——AbsCache。本文将详细介绍如何使用 AbsCache 来缓存数据,并通过 CacheFactory 实现缓存实例的注册和管理。Tio-boot 框架内部状态都使用 AbsCache 来进行存储

简介

1. 什么是 AbsCache

AbsCache 是 Tio-boot 框架中的抽象类,用于定义缓存的核心功能。它提供了基本的缓存操作,例如存储、获取、删除缓存条目,并支持配置缓存的生存时间(TTL, Time to Live)和空闲时间(TTI, Time to Idle)。AbsCache 支持各种实现,如基于 Map 的缓存。

AbsCache 核心功能

  • TTL(存活时间):缓存条目从创建开始有效,超过设定时间后将自动过期。
  • TTI(空闲时间):缓存条目在最后一次访问后有一定的有效期,如果在此期间未再次访问,也会过期。

使用

1. CacheFactory 和 AbsCache 的使用流程

使用 AbsCache 时,主要通过 CacheFactory 工厂类来管理缓存实例。它可以注册并返回缓存实例,允许开发者根据需要缓存数据。

核心步骤:

  1. 注册缓存实例:通过 CacheFactory.register() 方法,创建或获取一个 AbsCache 实例。
  2. 缓存数据:调用缓存实例的 put() 方法,将数据存储到缓存中。
  3. 获取缓存数据:使用 get() 方法,从缓存中获取数据。
  4. 移除缓存数据:通过 remove() 方法,删除缓存中的某个键值对。

2. 使用示例

    CacheFactory cacheFactory = TioBootServer.me().getServerTioConfig().getCacheFactory();
    AbsCache absCache = cacheFactory.register("test001",300L,3000L);
    absCache.put("key", "value");

下面是一个简单的示例代码,展示如何向 AbsCache 缓存系统添加数据

解释:

  1. 缓存工厂获取:通过 TioBootServer 获取 CacheFactory 实例.
  2. 添加缓存名称:通过register,添加缓存名称到缓存系统。
  3. 添加缓存数据:通过 absCache 添加数据。

3. 实现类 ConcurrentMapCache

ConcurrentMapCacheAbsCache 的一个具体实现,它使用 ConcurrentHashMap 来保存缓存数据,并提供 TTL 和 TTI 的过期机制。

主要功能:

  • 数据存储put() 方法用于将数据存储到缓存,并为缓存项设定过期时间。
  • 数据获取get() 方法用于从缓存中获取数据,并更新 TTI 时间。
  • 数据删除remove() 方法用于删除缓存项,并调用删除监听器。

在上面的实现中,缓存系统通过 ConcurrentHashMap 保存数据,并且会根据 TTL 和 TTI 自动过期条目。

4. 使用场景

AbsCache 适用于以下场景:

  • 短期缓存:需要快速访问的数据,例如用户会话信息、临时配置等。
  • 限制过期时间:当你需要在一定时间内缓存数据,且希望在不使用后自动过期。
  • 轻量级缓存系统AbsCache 的实现轻便、易于集成,非常适合内存敏感的场景。

获取所有缓存数据

IndexController 示例

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import com.jfinal.kit.Kv;
import com.litongjava.tio.boot.server.TioBootServer;
import com.litongjava.tio.http.server.annotation.RequestPath;
import com.litongjava.tio.utils.cache.AbsCache;
import com.litongjava.tio.utils.cache.CacheFactory;
import com.litongjava.tio.utils.resp.RespVo;

@RequestPath("/internal")
public class InternalController {

  @RequestPath()
  public RespVo cache() {
    CacheFactory cacheFactory = TioBootServer.me().getServerTioConfig().getCacheFactory();
    Map<String, ? extends AbsCache> map = cacheFactory.getMap();

    Kv kv = Kv.by("cacheFactory", cacheFactory);
    kv.set("map", map);

    for (Map.Entry<String, ? extends AbsCache> entry : map.entrySet()) {
      String cacheName = entry.getKey();
      AbsCache cache = entry.getValue();
      Collection<String> keysCollection = cache.keysCollection();
      Map<String, Object> cacheMap = new HashMap<>();
      for (String key : keysCollection) {
        cacheMap.put(key, cache.get(key));
      }
      kv.set("cache_" + cacheName, cacheMap);
    }

    return RespVo.ok(kv);
  }
}

返回数据格式示例

下面是一个返回的 JSON 数据格式示例:

{
  "data": {
    "cache_TIO_HTTP_STATIC_RES_CONTENT": {},
    "cacheFactory": "INSTANCE",
    "cache_com.litongjava.tio.utils.lock.LockUtilsOBJ": {},
    "cache_com.litongjava.tio.utils.lock.LockUtilsRW": {
      "StrCache:getLowercase-606089688": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes653303108": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase-1844712829": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes3151881": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase1217813246": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes3178825": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase1577755768": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes1520117783": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "_tio_ips__0:0:0:0:0:0:0:1": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes78": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes-579138113": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes1381242263": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes-227623528": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase12634714": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase12565974": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase-1399754748": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase-129587587": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes100245": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes-1452090263": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes1519667058": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase12115249": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase-2040128046": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes-1610277289": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase2024076932": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase-1580933225": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes78355": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes-1450561559": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase2255304": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes-1383386683": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes-640121764": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase-1099743112": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes1749280625": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes1519944307": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes-1368734941": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase1955373352": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getLowercase12392498": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      },
      "StrCache:getBytes1520186523": {
        "queueLength": 0,
        "fair": false,
        "readHoldCount": 0,
        "readLockCount": 0,
        "writeHoldCount": 0,
        "writeLocked": false,
        "writeLockedByCurrentThread": false
      }
    },
    "cache_TIO_HTTP_SESSIONRATELIMITER_CACHENAME": {
      "/?d87d6737327c4ee680f1213c67465403": {
        "path": "/",
        "lastAccessTime": "0",
        "accessCount": 0
      }
    },
    "cache_TIO_IP_BLACK_LIST__global__": {},
    "cache_TIO_IP_STAT_null_300": {
      "0:0:0:0:0:0:0:1": {
        "durationType": "300",
        "duration": "203",
        "ip": "0:0:0:0:0:0:0:1",
        "handledPackets": 0,
        "handledPacketCosts": 0,
        "receivedPackets": 1,
        "handledCostsPerPacket": 0,
        "packetsPerTcpReceive": 1,
        "bytesPerTcpReceive": 1469,
        "handledBytes": 0,
        "sentPackets": 0,
        "receivedTcps": 1,
        "receivedBytes": 1469,
        "sentBytes": 0,
        "requestCount": 2,
        "start": "2024-09-08 22:16:41",
        "decodeErrorCount": 0,
        "formatedDuration": "203毫秒"
      }
    },
    "map": {
      "com.litongjava.tio.utils.lock.LockUtilsOBJ": {
        "cacheName": "com.litongjava.tio.utils.lock.LockUtilsOBJ",
        "timeToIdleSeconds": "3600",
        "timeToLiveSeconds": null
      },
      "TIO_HTTP_SESSIONRATELIMITER_CACHENAME": {
        "cacheName": "TIO_HTTP_SESSIONRATELIMITER_CACHENAME",
        "timeToIdleSeconds": null,
        "timeToLiveSeconds": "60"
      },
      "tio-h-s": {
        "cacheName": "tio-h-s",
        "timeToIdleSeconds": "1800",
        "timeToLiveSeconds": null
      },
      "TIO_IP_STAT_null_300": {
        "cacheName": "TIO_IP_STAT_null_300",
        "timeToIdleSeconds": null,
        "timeToLiveSeconds": "300"
      },
      "TIO_HTTP_STATIC_RES_CONTENT": {
        "cacheName": "TIO_HTTP_STATIC_RES_CONTENT",
        "timeToIdleSeconds": null,
        "timeToLiveSeconds": "600"
      },
      "com.litongjava.tio.utils.lock.LockUtilsRW": {
        "cacheName": "com.litongjava.tio.utils.lock.LockUtilsRW",
        "timeToIdleSeconds": "3600",
        "timeToLiveSeconds": null
      },
      "TIO_IP_BLACK_LIST__global__": {
        "cacheName": "TIO_IP_BLACK_LIST__global__",
        "timeToIdleSeconds": null,
        "timeToLiveSeconds": "10368000"
      }
    },
    "cache_tio-h-s": {}
  },
  "ok": true,
  "code": 1,
  "msg": null
}

总结

Tio-boot 内置的缓存系统 AbsCache 提供了灵活且易用的缓存管理方式。通过 CacheFactory 注册并管理缓存实例,我们可以轻松实现高效的缓存机制,减少频繁数据重复计算。对于有 TTL 和 TTI 要求的场景,AbsCache 能帮助我们自动管理缓存条目的过期,提升系统性能。