Skip to content

Commit

Permalink
feat: add cache layer (#440)
Browse files Browse the repository at this point in the history
* add dependency

* add class rediscache and string rediscache api

* add Class PCache and add dependency correctly

* read cache config and add cache when processing cmd

* add part kv cmd with cache

* add all kv command with cache

* modify list cmd with cache

* delete useless code

* modify hash cmd with cache

* modify set cmd with cache

* modify zset command with cache

* modify zset part cmd with cache and fix count_ bug

* comment  some tcl cases

* fix build ci error

* tcl cases

* fix rename and String2int error

* fix ttl definition

* clang18 format code

* check clang format version
  • Loading branch information
hahahashen authored Oct 25, 2024
1 parent d08c598 commit 6352471
Show file tree
Hide file tree
Showing 57 changed files with 6,680 additions and 752 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pikiwidb.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:

- name: Check Format
working-directory: ${{ github.workspace }}/build
run: make check-format
run: clang-format --version

build_on_macos:
runs-on: macos-latest
Expand Down
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ INCLUDE(cmake/gtest.cmake)
INCLUDE(cmake/brpc.cmake)
INCLUDE(cmake/rocksdb.cmake)
INCLUDE(cmake/braft.cmake)
INCLUDE(cmake/rediscache.cmake)

SET(PROTO_OUTPUT_DIR "${CMAKE_BINARY_DIR}/generated_pb")
FILE(MAKE_DIRECTORY "${PROTO_OUTPUT_DIR}")
Expand All @@ -190,7 +191,7 @@ ADD_SUBDIRECTORY(src/pstd)
ADD_SUBDIRECTORY(src/net)
ADD_SUBDIRECTORY(src/praft)
ADD_SUBDIRECTORY(src/storage)

ADD_SUBDIRECTORY(src/cache)
ADD_SUBDIRECTORY(src)

#############################################################################
Expand Down
34 changes: 34 additions & 0 deletions cmake/rediscache.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright (c) 2024-present, Qihoo, Inc. All rights reserved.
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.

SET(REDISCACHE_SOURCES_DIR "${LIB_INSTALL_PREFIX}" CACHE PATH "rediscache source directory." FORCE)
SET(REDISCACHE_INSTALL_DIR "${LIB_INSTALL_PREFIX}" CACHE PATH "rediscache install directory." FORCE)
SET(REDISCACHE_INCLUDE_DIR "${LIB_INCLUDE_DIR}" CACHE PATH "rediscache include directory." FORCE)
SET(REDISCACHE_LIBRARIES "${LIB_INSTALL_DIR}/librediscache.a" CACHE FILEPATH "rediscache library." FORCE)

ExternalProject_Add(
extern_rediscache
${EXTERNAL_PROJECT_LOG_ARGS}
#URL https://github.com/pikiwidb/rediscache/archive/refs/tags/v1.0.7.tar.gz
#URL_HASH MD5=02c8aadc018dd8d4d3803cc420d1d75b
#temp used
GIT_REPOSITORY https://github.com/hahahashen/rediscache.git
GIT_TAG feat/removeUseTcMallocMacroDefinition
CMAKE_ARGS
-DCMAKE_BUILD_TYPE=Debug
-DCMAKE_INSTALL_PREFIX=${LIB_INSTALL_PREFIX}
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
-DPROJECT_BINARY_DIR=${LIB_INSTALL_PREFIX}
-DCMAKE_FIND_LIBRARY_SUFFIXES=${LIB_INSTALL_PREFIX}
-DSNAPPY_BUILD_TESTS=OFF
-DCMAKE_INSTALL_INCLUDEDIR=${REDISCACHE_INCLUDE_DIR}
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
BUILD_COMMAND make -j${CPU_CORE}
)

ADD_LIBRARY(rediscache STATIC IMPORTED GLOBAL)
SET_PROPERTY(TARGET rediscache PROPERTY IMPORTED_LOCATION ${REDISCACHE_LIBRARIES})
ADD_DEPENDENCIES(rediscache extern_rediscache)

44 changes: 44 additions & 0 deletions etc/conf/pikiwidb.conf
Original file line number Diff line number Diff line change
Expand Up @@ -346,3 +346,47 @@ rocksdb-periodic-second 259200;
use-raft no
# Braft relies on brpc to communicate via the default port number plus the port offset
raft-port-offset 10

################### Cache Settings ###################
# the number of caches for every db
cache-num 16

# cache-mode 0:cache_none 1:cache_read
cache-mode 1
# cache-type: string, set, zset, list, hash, bit
cache-type string, set, zset, list, hash, bit

# Maximum number of keys in the zset redis cache
# On the disk DB, a zset field may have many fields. In the memory cache, we limit the maximum
# number of keys that can exist in a zset, which is zset-zset-cache-field-num-per-key, with a
# default value of 512.
zset-cache-field-num-per-key 512

# If the number of elements in a zset in the DB exceeds zset-cache-field-num-per-key,
# we determine whether to cache the first 512[zset-cache-field-num-per-key] elements
# or the last 512[zset-cache-field-num-per-key] elements in the zset based on zset-cache-start-direction.
#
# If zset-cache-start-direction is 0, cache the first 512[zset-cache-field-num-per-key] elements from the header
# If zset-cache-start-direction is -1, cache the last 512[zset-cache-field-num-per-key] elements
zset-cache-start-direction 0


# the cache maxmemory of every db, configuration 10G
cache-maxmemory 10737418240

# cache-maxmemory-policy
# 0: volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# 1: allkeys-lru -> Evict any key using approximated LRU.
# 2: volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# 3: allkeys-lfu -> Evict any key using approximated LFU.
# 4: volatile-random -> Remove a random key among the ones with an expire set.
# 5: allkeys-random -> Remove a random key, any key.
# 6: volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# 7: noeviction -> Don't evict anything, just return an error on write operations.
cache-maxmemory-policy 1

# cache-maxmemory-samples
cache-maxmemory-samples 5

# cache-lfu-decay-time
cache-lfu-decay-time 1
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ TARGET_INCLUDE_DIRECTORIES(pikiwidb
PRIVATE ${PROJECT_SOURCE_DIR}/src/pstd
PRIVATE ${PROJECT_SOURCE_DIR}/src/net
PRIVATE ${PROJECT_SOURCE_DIR}/src/storage/include
PRIVATE ${PROJECT_SOURCE_DIR}/src/cache
PRIVATE ${rocksdb_SOURCE_DIR}/
PRIVATE ${rocksdb_SOURCE_DIR}/include
PRIVATE ${BRAFT_INCLUDE_DIR}
Expand All @@ -45,6 +46,7 @@ ADD_DEPENDENCIES(pikiwidb
braft
brpc
storage
pcache
)

TARGET_LINK_LIBRARIES(pikiwidb
Expand All @@ -56,6 +58,7 @@ TARGET_LINK_LIBRARIES(pikiwidb
lz4
zstd
storage
pcache
gflags
spdlog
pstd
Expand Down
60 changes: 59 additions & 1 deletion src/base_cmd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,65 @@ void BaseCmd::Execute(PClient* client) {
if (!DoInitial(client)) {
return;
}
DoCmd(client);

if (IsNeedCacheDo(client) && PCACHE_NONE != g_config.cache_mode.load() &&
PSTORE.GetBackend(dbIndex)->GetCache()->CacheStatus() == PCACHE_STATUS_OK) {
if (IsNeedReadCache()) {
ReadCache(client);
}
if (HasFlag(kCmdFlagsReadonly) && client->CacheMiss()) {
DoThroughDB(client);
if (IsNeedUpdateCache()) {
DoUpdateCache(client);
}
} else if (HasFlag(kCmdFlagsWrite)) {
DoThroughDB(client);
if (IsNeedUpdateCache()) {
DoUpdateCache(client);
}
}
} else {
DoCmd(client);
}
}

bool BaseCmd::IsNeedReadCache() const { return HasFlag(kCmdFlagsReadCache); }
bool BaseCmd::IsNeedUpdateCache() const { return HasFlag(kCmdFlagsUpdateCache); }

bool BaseCmd::IsNeedCacheDo(PClient* client) const {
if (g_config.tmp_cache_disable_flag.load()) {
return false;
}

if (HasFlag(kCmdFlagsKv)) {
if (!g_config.cache_string.load()) {
return false;
}
} else if (HasFlag(kCmdFlagsSet)) {
if (!g_config.cache_set.load()) {
return false;
}
} else if (HasFlag(kCmdFlagsZset)) {
int32_t db_len = 0;
PSTORE.GetBackend(client->GetCurrentDB())->GetStorage()->ZCard(client->Key(), &db_len);
auto zset_cache_field_num_per_key = g_config.zset_cache_field_num_per_key.load();
if (!g_config.cache_zset.load() || db_len > zset_cache_field_num_per_key) {
return false;
}
} else if (HasFlag(kCmdFlagsHash)) {
if (!g_config.cache_hash.load()) {
return false;
}
} else if (HasFlag(kCmdFlagsList)) {
if (!g_config.cache_list.load()) {
return false;
}
} else if (HasFlag(kCmdFlagsBit)) {
if (!g_config.cache_bit.load()) {
return false;
}
}
return (HasFlag(kCmdFlagsDoThroughDB));
}

std::string BaseCmd::ToBinlog(uint32_t exec_time, uint32_t term_id, uint64_t logic_id, uint32_t filenum,
Expand Down
16 changes: 16 additions & 0 deletions src/base_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,15 @@ enum CmdFlags {
kCmdFlagsNoMulti = (1 << 14), // Cannot be pipelined
kCmdFlagsExclusive = (1 << 15), // May change Storage pointer, like pika's kCmdFlagsSuspend
kCmdFlagsRaft = (1 << 16), // raft
kCmdFlagsKv = (1 << 17),
kCmdFlagsHash = (1 << 18),
kCmdFlagsList = (1 << 19),
kCmdFlagsSet = (1 << 20),
kCmdFlagsZset = (1 << 21),
kCmdFlagsBit = (1 << 22),
kCmdFlagsReadCache = (1 << 23),
kCmdFlagsUpdateCache = (1 << 24),
kCmdFlagsDoThroughDB = (1 << 25),
};

enum AclCategory {
Expand Down Expand Up @@ -319,9 +328,16 @@ class BaseCmd : public std::enable_shared_from_this<BaseCmd> {

uint32_t GetCmdID() const;

bool IsNeedUpdateCache() const;
bool IsNeedReadCache() const;
bool IsNeedCacheDo(PClient* client) const;

protected:
// Execute a specific command
virtual void DoCmd(PClient* client) = 0;
virtual void DoThroughDB(PClient* client) {}
virtual void DoUpdateCache(PClient* client) {}
virtual void ReadCache(PClient* client) {}

std::string name_;
int16_t arity_ = 0;
Expand Down
26 changes: 26 additions & 0 deletions src/cache/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright (c) 2024-present, Qihoo, Inc. All rights reserved.
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.

FILE(GLOB PCACHE_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/*.cc"
)
SET(LIBRARY_OUTPUT_PATH ${PLIB_INSTALL_DIR})

ADD_LIBRARY(pcache ${PCACHE_SRC})

TARGET_INCLUDE_DIRECTORIES(pcache
PRIVATE ${PROJECT_SOURCE_DIR}/src
PRIVATE ${rocksdb_SOURCE_DIR}/include
PRIVATE ${REDISCACHE_INCLUDE_DIR}
PRIVATE ${PROJECT_SOURCE_DIR}/src/pstd
PRIVATE ${PROJECT_SOURCE_DIR}/src/storage/include
)

ADD_DEPENDENCIES(pcache rediscache storage )

TARGET_LINK_LIBRARIES(pcache pstd rediscache gflags rocksdb storage)

SET_TARGET_PROPERTIES(pcache PROPERTIES LINKER_LANGUAGE CXX)
66 changes: 66 additions & 0 deletions src/cache/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) 2024-present, Qihoo, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.

#pragma once

#include <cstdint>

#include "rediscache/commondef.h"

namespace cache {

/* Redis maxmemory strategies */
enum RedisMaxmemoryPolicy {
CACHE_VOLATILE_LRU = 0,
CACHE_ALLKEYS_LRU = 1,
CACHE_VOLATILE_LFU = 2,
CACHE_ALLKEYS_LFU = 3,
CACHE_VOLATILE_RANDOM = 4,
CACHE_ALLKEYS_RANDOM = 5,
CACHE_VOLATILE_TTL = 6,
CACHE_NO_EVICTION = 7
};

#define CACHE_DEFAULT_MAXMEMORY CONFIG_DEFAULT_MAXMEMORY // 10G
#define CACHE_DEFAULT_MAXMEMORY_SAMPLES CONFIG_DEFAULT_MAXMEMORY_SAMPLES
#define CACHE_DEFAULT_LFU_DECAY_TIME CONFIG_DEFAULT_LFU_DECAY_TIME

/*
* cache start pos
*/
constexpr int CACHE_START_FROM_BEGIN = 0;
constexpr int CACHE_START_FROM_END = -1;
/*
* cache items per key
*/
#define DEFAULT_CACHE_ITEMS_PER_KEY 512

struct CacheConfig {
uint64_t maxmemory; /* Can used max memory */
int32_t maxmemory_policy; /* Policy for key eviction */
int32_t maxmemory_samples; /* Precision of random sampling */
int32_t lfu_decay_time; /* LFU counter decay factor. */
int32_t zset_cache_start_direction;
int32_t zset_cache_field_num_per_key;

CacheConfig()
: maxmemory(CACHE_DEFAULT_MAXMEMORY),
maxmemory_policy(CACHE_NO_EVICTION),
maxmemory_samples(CACHE_DEFAULT_MAXMEMORY_SAMPLES),
lfu_decay_time(CACHE_DEFAULT_LFU_DECAY_TIME),
zset_cache_start_direction(CACHE_START_FROM_BEGIN),
zset_cache_field_num_per_key(DEFAULT_CACHE_ITEMS_PER_KEY) {}

CacheConfig& operator=(const CacheConfig& obj) {
maxmemory = obj.maxmemory;
maxmemory_policy = obj.maxmemory_policy;
maxmemory_samples = obj.maxmemory_samples;
lfu_decay_time = obj.lfu_decay_time;
zset_cache_start_direction = obj.zset_cache_start_direction;
zset_cache_field_num_per_key = obj.zset_cache_field_num_per_key;
return *this;
}
};
} // namespace cache
Loading

0 comments on commit 6352471

Please sign in to comment.