Pogocache

repository·main·Indexed 25 days ago

https://github.com/tidwall/pogocache

A high-performance, low-latency caching software designed for CPU efficiency. It can be run as a standalone server supporting HTTP, Memcache, RESP (Valkey/Redis), and Postgres wire protocols, or embedded directly into applications as a C library. Features include a sharded hashmap architecture with Robin Hood hashing, TLS support, and flexible memory management with configurable eviction policies.

Tokens
3.5K
Snippets
12
Records
18
Agent score
82%

What's inside pogocache

  1. How Pogocache manages data and memory

    main

    Pogocache uses a sharded hashmap architecture designed for low latency and high CPU efficiency.

    Sharding and Hashing

    • Shards: Data is stored in a sharded hashmap (defaulting to a high fanout, e.g., 4096 shards). The number of shards is automatically configured at startup but can be changed by the user.
    • Hashing: A 64-bit hash (using th64) is generated for each key. The high 32 bits determine the shard, and the low 32 bits determine the position in the per-shard hashmap.
    • Hashmap Implementation: Each shard uses an independent hashmap with open addressing and Robin Hood hashing.
    • Concurrency: Shards are protected by lightweight spinlocks during operations.

    Memory and Eviction

    • Entry Storage: Each entry is a single heap allocation containing a header, key (using sixpack compression), and value. Optional fields like expiry, CAS, and flags may also be present.
    • Expiration: Entries can have an optional expiry. Expired entries are evicted during periodic background sweeps to ensure no more than 10% of total cache memory is occupied by evicted entries.
    • Low Memory Eviction: If the system runs low on memory, the insert operation automatically evicts older entries using the 2-random algorithm to free memory immediately.
  2. Connect to Pogocache via TLS

    main

    Once Pogocache is running with TLS enabled, you can connect using standard clients by providing the certificates.

    Using valkey/redis cli

    valkey-cli --tls         \
        --cert pogocache.crt \
        --key pogocache.key  \
        --cacert ca.crt      \
        -h localhost -p 9401

    Using curl

    curl "https://localhost:9401" \
      --cert pogocache.crt        \
      --key pogocache.key         \
      --cacert ca.crt
  3. Run Pogocache tests

    main

    You can run the Pogocache test suite from the repository root using make test. Alternatively, you can use the test runner script directly, optionally specifying a particular test name.

    To run all tests:

    make test

    To run the test runner script:

    tools/tests/run.sh

    To run a specific test:

    tools/tests/run.sh [testname]
  4. Package Pogocache for various architectures

    main

    The packaging system builds Pogocache for multiple architectures, producing .tar.gz packages that include the Pogocache program and its license. These packages are output to the packages directory in the repository root.

    To build all architecture packages:

    make package

    To build a specific architecture package (e.g., linux-aarch64), use the build script:

    tools/build/run.sh linux-aarch64
  5. Build and run Pogocache

    main

    Pogocache is designed for 64-bit Linux and MacOS. You can build it from source using make and run the resulting binary.

    To start the server on the default localhost address (127.0.0.1) at port 9401, run:

    ./pogocache

    To allow connections from other machines, bind to a specific host address:

    ./pogocache -h <host_address>

    Alternatively, you can run Pogocache using Docker:

    docker run pogocache/pogocache
    make
    ./pogocache
    ./pogocache -h 172.30.2.84
    docker run pogocache/pogocache
  6. Configure TLS/HTTPS for Pogocache

    main

    To enable TLS, you must start Pogocache with TLS-specific flags and provide certificates. You will need a CA certificate (ca.crt), a server certificate (pogocache.crt), and a server private key (pogocache.key).

    1. Generate Certificates

    You can generate self-signed certificates using openssl:

    # Generate CA key and cert
    openssl req -x509 -newkey rsa:4096 -sha256 -days 365 -nodes \
      -keyout ca.key -out ca.crt -subj "/CN=My Pogocache CA"
    
    # Generate server key and CSR
    openssl req -newkey rsa:4096 -nodes -keyout pogocache.key -out pogocache.csr -subj "/CN=localhost"
    
    # Sign server cert with CA
    openssl x509 -req -sha256 -days 365 -in pogocache.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out pogocache.crt

    2. Start Pogocache with TLS

    Use the --tlsport, --tlscert, --tlskey, and --tlscacert flags. Use -p 0 to disable the plain-text port.

    pogocache -p 0             \
       --tlsport 9401          \
       --tlscert pogocache.crt \\
       --tlskey pogocache.key  \
       --tlscacert ca.crt
  7. Configure memory limits with various units

    main

    The --maxmemory flag accepts several formats for specifying memory limits:

    • Percentage: e.g., 80% (of total system memory).
    • Bytes: raw numeric value.
    • Suffixes:
      • k or K for Kilobytes
      • m or M for Megabytes
      • g or G for Gigabytes
      • t or T for Terabytes
    • Unlimited: Use the literal string unlimited to disable limits.
  8. Configure Auth Password

    main

    You can protect Pogocache by providing an optional password via the --auth flag. When enabled, all client requests must include this password.

    Start Server with Auth

    pogocache --auth mypass

    Client Authentication

    valkey/redis cli

    valkey-cli -p 9401 -a mypass

    HTTP (curl)

    Use either the Authorization header or a query string:

    # Using header
    curl -H "Authorization: Bearer mypass" "http://localhost:9401/mykey"
    
    # Using query string
    curl "http://localhost:9401/mykey?auth=mypass"
  9. Run the Pogocache server via CLI

    main

    Pogocache can be run as a standalone server using various command-line options to configure networking, memory management, security, and performance.

    Basic Usage: Specify a host, port, or Unix socket to start listening for connections.

    Memory Management:

    • Use --maxmemory to set a limit (e.g., 80%, 1g, 512m).
    • Use --evict yes/no to enable or disable key eviction when the memory limit is reached.
    • Use --persist path to specify a file for loading and saving data.

    Security:

    • Use --auth passwd to set an authentication token or password.
    • For TLS, specify --tlsport, --tlscert, --tlskey, and --tlscacert.
  10. Use Pogocache as an embeddable C library

    main

    The pogocache.c file in the src directory is a standalone library that can be compiled directly into C projects. This provides access to primary caching operations.

    Example Usage

    #include <stdio.h>
    #include "pogocache.h"
    
    static void load_callback(int shard, int64_t time, const void *key,
        size_t keylen, const void *value, size_t valuelen, int64_t expires, 
        uint32_t flags, uint64_t cas, struct pogocache_update **update, 
        void *udata)
    {
        printf("%.*s\n", (int)valuelen, (char*)value);
    }
    
    int main(void) {
        // Create a Pogocache instance
        struct pogocache *cache = pogocache_new(0);
    
        // Store some values
        pogocache_store(cache, "user:1391:name", 14, "Tom", 3, 0);
        pogocache_store(cache, "user:1391:last", 14, "Anderson", 8, 0);
        pogocache_store(cache, "user:1391:age", 13, "37", 2, 0);
    
        // Read the values back
        struct pogocache_load_opts lopts = { .entry = load_callback };
        pogocache_load(cache, "user:1391:name", 14, &lopts);
        pogocache_load(cache, "user:1391:last", 14, &lopts);
        pogocache_load(cache, "user:1391:age", 13, &lopts);
        return 0;
    }

    Compilation

    Compile the program by including both your source and pogocache.c:

    cc prog.c pogocache.c
    ./a.out
    // prog.c
    #include <stdio.h>
    #include "pogocache.h"
    
    static void load_callback(int shard, int64_t time, const void *key,
        size_t keylen, const void *value, size_t valuelen, int64_t expires, 
        uint32_t flags, uint64_t cas, struct pogocache_update **update, 
        void *udata)
    {
        printf("%.*s\n", (int)valuelen, (char*)value);
    }
    
    int main(void) {
        // Create a Pogocache instance
        struct pogocache *cache = pogocache_new(0);
    
        // Store some values
        pogocache_store(cache, "user:1391:name", 14, "Tom", 3, 0);
        pogocache_store(cache, "user:1391:last", 14, "Anderson", 8, 0);
        pogocache_store(cache, "user:1391:age", 13, "37", 2, 0);
    
        // Read the values back
        struct pogocache_load_opts lopts = { .entry = load_callback };
        pogocache_load(cache, "user:1391:name", 14, &lopts);
        pogocache_load(cache, "user:1391:last", 14, &lopts);
        pogocache_load(cache, "user:1391:age", 13, &lopts);
        return 0;
    }
  11. Use the RESP (Valkey/Redis) wire protocol

    main

    Pogocache supports RESP commands, making it compatible with Valkey and Redis clients. Supported commands include:

    • SET, GET, DEL, MGET, MGETS, TTL, PTTL, EXPIRE, DBSIZE, QUIT, ECHO, EXISTS, FLUSH, PURGE, SWEEP, KEYS, PING, APPEND, PREPEND, AUTH, SAVE, LOAD.
    valkey-cli -p 9401
    > SET mykey value
    OK
    > GET mykey
    "my value"
    > DEL mykey
    (integer) 1