gCore

CacheManager Documentation

Overview

The CacheManager provides high-performance distributed caching with zero local state for the gCore framework. Built on ValKey/Redis, it offers advanced features including distributed locking, transactions, streams, batch operations, and script-based atomic operations through a modular architecture.

Core Features

Architecture

The CacheManager architecture has been enhanced with a modular script system:

Core Components

Modular Script System

Initialization

// Get CacheManager instance
$cacheManager = gcore_get_cache_manager();

// Initialize with configuration
$cacheManager->initialize([
    // ValKey/Redis configuration
    'host' => '127.0.0.1',       // ValKey host
    'port' => 6379,              // ValKey port
    'auth' => 'password',        // Authentication password
    'database' => 0,             // Database index
    'timeout' => 2.0,            // Connection timeout
    'prefix' => 'cache_',        // Key prefix
    'retry_interval' => 100,     // Retry interval (ms)
    'persistent' => true,        // Use persistent connection

    // Connection pooling
    'connection_pool_size' => 10,  // Maximum connections
    'min_connections' => 2,        // Minimum persistent connections

    // Cache configuration
    'default_ttl' => 3600,       // Default TTL (seconds)
    'serialize' => true,         // Serialize values

    // Performance options
    'batch_size' => 100,         // Batch operation size
    'script_retry_attempts' => 3, // Script retry attempts
    'script_retry_delay' => 100, // Script retry delay (ms)

    // Feature toggles
    'streams' => [
        'enabled' => true,       // Enable streams
        'auto_create' => true,   // Auto-create streams
        'max_len' => 10000       // Max stream length
    ],

    // Debugging
    'debug' => false,            // Debug mode

    // Trait configuration
    'traits' => [
        'StreamCapabilities' => ['enabled' => true]
    ]
]);

Basic Usage

Simple Cache Operations

// Set a value with TTL
$cacheManager->set('user:123', $userData, 3600);

// Get a value with default fallback
$userData = $cacheManager->get('user:123', ['name' => 'Guest']);

// Check if key exists
$exists = $cacheManager->has('user:123');

// Delete a key
$cacheManager->delete('user:123');

// Increment/decrement counters
$newValue = $cacheManager->increment('visits', 1);
$newValue = $cacheManager->decrement('remaining', 1);

Multiple Operations

// Get multiple values efficiently
$values = $cacheManager->getMultiple(['key1', 'key2', 'key3']);

// Set multiple values in one operation
$cacheManager->setMultiple([
    'key1' => 'value1',
    'key2' => 'value2',
    'key3' => 'value3'
], 3600);

// Delete multiple keys
$cacheManager->deleteMultiple(['key1', 'key2', 'key3']);

Hash Operations

// Set a hash field
$cacheManager->hashSet('user:123:data', 'email', 'user@example.com');

// Get a hash field
$email = $cacheManager->hashGet('user:123:data', 'email');

// Get multiple hash fields
$fields = $cacheManager->hashMultipleGet('user:123:data', ['email', 'name', 'status']);

// Set multiple hash fields
$cacheManager->hashMultipleSet('user:123:data', [
    'email' => 'user@example.com',
    'name' => 'John Doe',
    'status' => 'active'
]);

// Delete hash field
$cacheManager->hashDelete('user:123:data', 'status');

// Get all hash fields
$userData = $cacheManager->hashGetAll('user:123:data');

Advanced Features

Script System

The modular script system allows for atomic, efficient operations:

// Execute a core script
$value = $cacheManager->runScript(
    'GET',                // Script name
    ['user:profile:123']  // Keys
);

// Execute a batch operation script
$values = $cacheManager->runScript(
    'MGET',                            // Script name
    ['batch:keys'],                    // Keys
    [json_encode(['key1', 'key2'])]    // Arguments
);

// Execute a transaction script
$result = $cacheManager->runScript(
    'TRANSACTION_EXEC',                // Script name
    ['transaction:123'],               // Keys
    [json_encode([                     // Arguments
        ['SET', 'key1', 'value1'],
        ['INCR', 'counter'],
        ['EXPIRE', 'key1', 3600]
    ])]
);

Connection Pooling

Connection pooling improves performance by reusing connections:

// Get the connection pool
$pool = $cacheManager->getConnectionPool();

// Execute with a connection from the pool
$result = $pool->executeWithConnection(function($redis) {
    // Use the connection
    return $redis->get('some-key');
});

// Execute with retry logic
$result = $pool->executeWithRetry(
    function($redis) {
        return $redis->set('key', 'value');
    },
    3,    // Max retries
    100   // Retry delay in ms
);

// Get connection pool stats
$stats = $pool->getConnectionStats();

Distributed Locking

Safely coordinate distributed operations:

// Acquire a lock
if ($cacheManager->lock('resource_lock', 30)) {
    try {
        // Perform operations that require exclusive access
        processResource();
    } finally {
        // Always release the lock when done
        $cacheManager->unlock('resource_lock');
    }
}

Streams (with StreamCapabilities Trait)

Process real-time data streams:

// Add entry to stream
$entryId = $cacheManager->streamAdd('events', [
    'type' => 'user_login',
    'user_id' => 123,
    'timestamp' => time()
]);

// Create consumer group
$created = $cacheManager->streamCreateGroup('events', 'processors', '0');

// Read from stream with a consumer group
$entries = $cacheManager->streamReadGroup(
    'events',       // Stream
    'processors',   // Group
    'worker1',      // Consumer
    10              // Count
);

// Process entries
foreach ($entries as $entry) {
    // Process entry
    processEvent($entry['data']);

    // Acknowledge processing
    $cacheManager->streamAck('events', 'processors', $entry['id']);
}

// Get pending entries
$pending = $cacheManager->streamPending('events', 'processors');

// Claim abandoned entries
$claimed = $cacheManager->streamClaim(
    'events',       // Stream
    'processors',   // Group
    'worker2',      // New consumer
    60000,          // Min idle time (ms)
    [$messageId]    // Message IDs to claim
);

Pub/Sub Messaging

Real-time messaging between components:

// Publish a message
$recipients = $cacheManager->publish('channel', json_encode([
    'event' => 'user.created',
    'data' => ['id' => 123, 'name' => 'John']
]));

// Subscribe to channel (blocking operation)
$cacheManager->subscribe('channel', function($message) {
    $data = json_decode($message, true);
    if ($data['event'] === 'user.created') {
        // Handle user creation event
    }
});

Circuit Breaking with Adaptive Backoff

Prevent cascading failures with circuit breaking:

// Get the connection pool with adaptive backoff
$pool = $cacheManager->getConnectionPool();

// Execute with adaptive backoff
try {
    $result = $pool->executeWithRetry(function($redis) {
        return $redis->get('key');
    });
} catch (\Exception $e) {
    // Circuit may be open after multiple failures
    if ($pool->isCircuitOpen('redis_get')) {
        // Use fallback mechanism
        $result = getFallbackValue();
    }
}

// Check circuit status
$status = $pool->getCircuitStatus('redis_get');

API Digest

Main CacheManager Class

StreamCapabilities Trait

ValKeyConnectionPool

CacheScripts Classes

Performance Optimization

Batch Operations

Use batch operations for better performance:

// Inefficient: Multiple individual operations
foreach ($keys as $key) {
    $value = $cacheManager->get($key);
}

// Efficient: Single batch operation
$values = $cacheManager->getMultiple($keys);

Connection Pooling

Configure connection pooling for optimal performance:

$cacheManager->initialize([
    'connection_pool_size' => 20,        // More connections for high traffic
    'min_connections' => 5,              // Keep min connections open
    'connection_idle_timeout' => 60,     // Close idle connections after 60s
    'adaptive_pool_sizing' => true       // Dynamically adjust pool size
]);

Script-Based Operations

Use script-based operations for complex atomic operations:

// Multiple operations with race condition risk
$count = $cacheManager->get('counter');
$count++;
$cacheManager->set('counter', $count);

// Atomic operation using script
$count = $cacheManager->runScript('INCR', ['counter']);

Intelligent Retry Logic

Configure retry behavior for optimal resilience:

$cacheManager->initialize([
    'retry_interval' => 100,     // Initial retry delay in ms
    'retry_jitter' => 0.1,       // Add randomness to prevent thundering herd
    'max_retries' => 3,          // Maximum retry attempts
    'circuit_threshold' => 5,    // Failures before circuit opens
    'circuit_reset' => 30        // Seconds to keep circuit open
]);

Best Practices

  1. Use Appropriate TTLs

    • Set realistic expiration times based on data volatility
    • Use shorter TTLs for frequently changing data
    • Use longer TTLs for static content
  2. Implement Key Naming Conventions

    • Use colon-separated namespaces: type:id:field
    • Include entity type in keys
    • Be consistent with naming patterns
  3. Handle Cache Failures Gracefully

    • Always have fallback mechanisms
    • Use circuit breakers to prevent cascade failures
    • Log cache failures for monitoring
  4. Use Batch Operations

    • Group related operations into batches
    • Use multi-key operations instead of loops
    • Consider using transactions for related updates
  5. Monitor Cache Performance

    • Track hit/miss ratios
    • Monitor memory usage
    • Set up alerts for abnormal patterns
  6. Use Connection Pooling Effectively

    • Configure pool size based on expected traffic
    • Use adaptive pool sizing for variable loads
    • Monitor connection pool metrics

Troubleshooting

Common Issues

  1. Connection Failures

    • Verify ValKey/Redis server is running
    • Check network connectivity
    • Ensure authentication credentials are correct
    • Check for firewall restrictions
  2. Performance Issues

    • Monitor connection pool utilization
    • Check for key hotspots
    • Verify appropriate batch operations are used
    • Examine script execution times
  3. Memory-Related Issues

    • Monitor ValKey/Redis memory usage
    • Implement key eviction policies
    • Ensure appropriate TTLs are set
    • Consider data compression for large values
  4. Script Execution Failures

    • Verify script syntax
    • Check script load performance
    • Monitor script execution times
    • Use script caching for better performance

Conclusion

The CacheManager provides a reliable, high-performance distributed caching solution for gCore applications. With its modular script system, connection pooling, and feature set, it enables efficient data caching, processing, and coordination in distributed environments.


Updated: March 2025