캐시된 Lookup 모듈

캐시된 Lookup 모듈 (Cached Lookup Module)

JDBC 데이터 소스에 대해 lookup별 캐싱 메커니즘을 제공하는 Apache Druid 모듈이에요. 고지연 lookup 소스에 대한 접근을 가속화하고, 각 lookup 소스에 캐싱 격리를 제공해요.

출처: 문서

본문

설명 (Description)

이 Apache Druid 모듈은 JDBC 데이터 소스에 대한 lookup별 캐싱 메커니즘을 제공해요. 이 캐시의 주요 목표는 고지연(high latency) lookup 소스에 대한 접근을 빠르게 하고, 모든 lookup 소스에 대한 캐싱 격리(caching isolation)를 제공하는 것이에요. 따라서 소스가 동일하더라도 lookup별로 다양한 캐싱 전략이나 구현을 정의할 수 있어요. 이 모듈은 전역 캐시된 lookup 모듈과 같은 다른 lookup 모듈과 나란히 사용할 수 있어요.

이 Apache Druid 확장 기능을 사용하려면 extensions load list에 druid-lookups-cached-single을 포함하세요.

info

JDBC를 사용하려면 데이터베이스 클라이언트 JAR 파일을 확장 기능 디렉터리에 추가해야 해요. Postgres의 경우 커넥터 JAR는 이미 포함되어 있어요. MySQL 또는 MariaDB 커넥터 라이브러리를 얻으려면 MySQL 확장 기능 문서를 참고하세요. 다운로드한 파일을 배포 루트 디렉터리의 extensions/druid-lookups-cached-single 아래에 복사하거나 심볼릭 링크를 만드세요.

아키텍처 (Architecture)

일반적으로 이 모듈은 데이터 페처(data fetcher) 레이어와 캐싱(caching) 레이어라는 두 가지 주요 컴포넌트로 나눌 수 있어요.

데이터 페처 레이어 (Data Fetcher layer)

첫 번째 부분은 데이터 페처 레이어 API인 DataFetcher로, 실제 Lookup 차원 소스에서 데이터를 가져오는 일련의 fetch 메서드를 노출해요. 예를 들어 JdbcDataFetcher는 JDBC 드라이버를 통해 RDBMS에서 key/value를 가져오는 데 사용할 수 있는 DataFetcher 구현을 제공해요. 새 유형의 데이터 페처가 필요하면 DataFetcher 인터페이스를 구현하고 다른 druid 모듈을 통해 로드하기만 하면 돼요.

캐싱 레이어 (Caching layer)

이 확장 기능은 두 가지 서로 다른 캐싱 전략을 제공해요. 첫 번째는 폴링(poll) 기반이고, 두 번째는 로딩(load) 기반이에요.

폴링 lookup 캐시 (Poll lookup cache)

폴링 전략 캐시 전략은 lookup 소스에서 모든 key/value 쌍을 주기적으로 가져와 교체해요. 따라서 사용자는 캐시가 모든 데이터를 담을 수 있는지 확인해야 해요. 현재 구현은 2가지 유형의 poll cache를 제공하는데, 첫 번째는 온힙(on-heap, 불변 맵 사용)이고 두 번째는 MapDB 기반 오프힙(off-heap) 맵이에요. 사용자는 PollingCacheFactory와 PollingCache 인터페이스를 구현해 다른 lookup 폴링 캐시를 구현할 수도 있어요.

로딩 lookup (Loading lookup)

로딩 캐시 전략은 키 자체에 대한 요청 시 key/value 쌍을 로드하는데, 일반적인 알고리즘은 키가 없으면 로드하는 것(load key if absent)이에요. key/value 쌍이 로드되면 캐시 퇴거 정책(cache eviction policy)에 따라 퇴거가 발생해요. 이 모듈은 두 가지 로딩 lookup 구현을 제공하는데, 첫 번째는 Guava 캐시 구현이 뒷받침하는 온힙 구현이고, 두 번째는 MapDB 오프힙 구현이에요. 두 구현 모두 다양한 퇴거 전략을 제공해요. 로딩 캐시도 마찬가지로 개발자는 LookupLoadingCache 인터페이스를 구현해 새 유형의 로딩 캐시를 구현할 수 있어요.

구성과 작동 (Configuration and Operation)

폴링 Lookup (Polling Lookup)

현재 offHeapPolling과 onHeapPolling 구현은 키를 기준으로 값을 조회하는 캐시 하나와 값에서 키를 역조회(reverse lookup)하는 캐시 하나, 총 두 개의 캐시를 생성한다는 점에 유의하세요.

| Field | Type | Description | Required | default | | dataFetcher | JSON object | Specifies the lookup data fetcher type for fetching data | yes | null | | cacheFactory | JSON Object | Cache factory implementation | no | onHeapPolling | | pollPeriod | Period | polling period | no | null (poll once) |

폴링 온힙 Lookup 예제 (Example of Polling On-heap Lookup)

이 예제는 10분마다 온힙 캐시를 갱신하는 폴링 캐시를 보여줘요.

{
    "type": "pollingLookup",
    "pollPeriod": "PT10M",
    "dataFetcher": {
       "type": "jdbcDataFetcher",
       "connectorConfig": {
          "connectURI": "jdbc://mysql://localhost:3306/my_data_base",
          "user": "druid",
          "password": "druid"
       },
       "table": "lookup_table_name",
       "keyColumn": "key_column_name",
       "valueColumn": "value_column_name"
    },
    "cacheFactory": {
       "type": "onHeapPolling"
    }
}
폴링 오프힙 Lookup 예제 (Example Polling Off-heap Lookup)

이 예제는 한 번 캐시되고 전혀 교체되지 않는 오프힙 lookup(pollPeriod == null)을 보여줘요.

{
   "type": "pollingLookup",
   "dataFetcher": {
      "type": "jdbcDataFetcher",
      "connectorConfig": {
         "connectURI": "jdbc://mysql://localhost:3306/my_data_base",
         "user": "druid",
         "password": "druid"
      },
      "table": "lookup_table_name",
      "keyColumn": "key_column_name",
      "valueColumn": "value_column_name"
   },
   "cacheFactory": {
      "type": "offHeapPolling"
   }
}

로딩 lookup (Loading lookup)

| Field | Type | Description | Required | default | | dataFetcher | JSON object | Specifies the lookup data fetcher type to use in order to fetch data | yes | null | | loadingCacheSpec | JSON Object | Lookup cache spec implementation | yes | null | | reverseLoadingCacheSpec | JSON Object | Reverse lookup cache implementation | yes | null |

로딩 온힙 Guava 예제 (Example Loading On-heap Guava)

Guava 캐시 구성 스펙.

| Field | Type | Description | Required | default | | concurrencyLevel | int | Allowed concurrency among update operations | no | 4 | | initialCapacity | int | Initial capacity size | no | null | | maximumSize | long | Specifies the maximum number of entries the cache may contain. | no | null (infinite capacity) | | expireAfterAccess | long | Specifies the eviction time after last read in milliseconds. | no | null (No read-time-based eviction when set to null) | | expireAfterWrite | long | Specifies the eviction time after last write in milliseconds. | no | null (No write-time-based eviction when set to null) |

{
   "type": "loadingLookup",
   "dataFetcher": {
      "type": "jdbcDataFetcher",
      "connectorConfig": {
         "connectURI": "jdbc://mysql://localhost:3306/my_data_base",
         "user": "druid",
         "password": "druid"
      },
      "table": "lookup_table_name",
      "keyColumn": "key_column_name",
      "valueColumn": "value_column_name"
   },
   "loadingCacheSpec": {
      "type": "guava"
   },
   "reverseLoadingCacheSpec": {
      "type": "guava",
      "maximumSize": 500000,
      "expireAfterAccess": 100000,
      "expireAfterWrite": 10000
   }
}
로딩 오프힙 MapDB 예제 (Example Loading Off-heap MapDB)

오프힙 캐시는 MapDB 구현이 뒷받침해요. MapDB는 메모리 풀로 direct memory를 사용하므로, JVM direct memory 설정을 제한할 때 이 점을 고려하세요.

| Field | Type | Description | Required | default | | maxStoreSize | double | maximal size of store in GiB, if store is larger entries will start expiring | no | 0 | | maxEntriesSize | long | Specifies the maximum number of entries the cache may contain. | no | 0 (infinite capacity) | | expireAfterAccess | long | Specifies the eviction time after last read in milliseconds. | no | 0 (No read-time-based eviction when set to null) | | expireAfterWrite | long | Specifies the eviction time after last write in milliseconds. | no | 0 (No write-time-based eviction when set to null) |

{
   "type": "loadingLookup",
   "dataFetcher": {
      "type": "jdbcDataFetcher",
      "connectorConfig": {
         "connectURI": "jdbc://mysql://localhost:3306/my_data_base",
         "user": "druid",
         "password": "druid"
      },
      "table": "lookup_table_name",
      "keyColumn": "key_column_name",
      "valueColumn": "value_column_name"
   },
   "loadingCacheSpec": {
      "type": "mapDb",
      "maxEntriesSize": 100000
   },
   "reverseLoadingCacheSpec": {
      "type": "mapDb",
      "maxStoreSize": 5,
      "expireAfterAccess": 100000,
      "expireAfterWrite": 10000
   }
}

JDBC 데이터 페처 (JDBC Data Fetcher)

| Field | Type | Description | Required | default | | connectorConfig | JSON object | Specifies the database connection details. You can set connectURI , user and password . You can selectively allow JDBC properties in connectURI . See JDBC connections security config for more details. | yes | | | table | string | The table name to read from. | yes | | | keyColumn | string | The column name that contains the lookup key. | yes | | | valueColumn | string | The column name that contains the lookup value. | yes | | | streamingFetchSize | int | Fetch size used in JDBC connections. | no | 1000 |

더 알아보기 (Learn more)