redis

package
v1.2.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 1, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

README

Redis

Redis client with connection pooling and simplified operations.

Overview

The redis package provides a convenient wrapper around the Redigo Redis client library, offering connection pooling, automatic health checks, and simplified method signatures for common Redis operations.

Features

  • Connection Pooling - Configurable pool size and idle timeout
  • Automatic Health Checks - PING-based connection validation
  • String Operations - GET, SET, SETEX, MGET, MSET
  • Key Management - DEL, EXISTS, RENAME, TTL, RANDOMKEY
  • Database Selection - SELECT command support
  • Database Operations - FLUSHDB, FLUSHALL, DBSIZE
  • Server Info - INFO command with category filtering

Installation

go get -u github.com/common-library/go/database/redis
go get -u github.com/gomodule/redigo/redis

Quick Start

import (
    "time"
    "github.com/common-library/go/database/redis"
)

func main() {
    var client redis.Client
    
    // Initialize with connection pool
    err := client.Initialize(
        "localhost:6379",  // address
        "",                // password (empty for no auth)
        10,                // max idle connections
        60*time.Second,    // idle timeout
    )
    if err != nil {
        log.Fatal(err)
    }
    defer client.Finalize()
    
    // Set and get values
    err = client.Set("user:1:name", "Alice")
    name, err := client.Get("user:1:name")
    fmt.Println(name) // Alice
}

Basic Operations

String Operations
// SET - Store a value
err := client.Set("key", "value")

// GET - Retrieve a value  
value, err := client.Get("key")
fmt.Println(value) // "value"

// SETEX - Set with expiration (in seconds)
err = client.Setex("session:123", 3600, "session_data")

// MGET - Get multiple values
values, err := client.MGet("key1", "key2", "key3")
for _, val := range values {
    fmt.Println(val)
}

// MSET - Set multiple values
err = client.MSet("key1", "value1", "key2", "value2", "key3", "value3")
Key Management
// DEL - Delete a key
err := client.Del("key")

// EXISTS - Check if key exists
exists, err := client.Exists("key")
if exists {
    fmt.Println("Key exists")
}

// EXISTS - Check multiple keys
exists, err = client.Exists("key1", "key2", "key3")

// RENAME - Rename a key
err = client.Rename("old_key", "new_key")

// RANDOMKEY - Get random key
key, err := client.RandomKey()

// TTL - Get time to live (in seconds)
ttl, err := client.Ttl("session:123")
if ttl == -2 {
    fmt.Println("Key does not exist")
} else if ttl == -1 {
    fmt.Println("Key has no expiration")
} else {
    fmt.Printf("Key expires in %d seconds\n", ttl)
}
Database Operations
// SELECT - Select database by index (0-15)
err := client.Select(1)

// DBSIZE - Get number of keys in current database
count, err := client.DBsize()
fmt.Printf("Database has %d keys\n", count)

// FLUSHDB - Delete all keys in current database
err = client.FlushDB()

// FLUSHALL - Delete all keys in all databases
err = client.FlushAll()
Server Information
// INFO - Get all server information
info, err := client.Info("ALL")
fmt.Println(info)

// INFO - Get specific category
serverInfo, err := client.Info("Server")
memoryInfo, err := client.Info("Memory")
statsInfo, err := client.Info("Stats")

// Available categories:
// - Server, Clients, Memory, Persistence
// - Stats, Replication, CPU, Cluster, Keyspace
Connection Management
// PING - Test connection
err := client.Ping()
if err != nil {
    fmt.Println("Redis connection failed")
}

// Finalize - Close all connections
defer client.Finalize()

Complete Examples

Session Storage
package main

import (
    "fmt"
    "log"
    "time"
    
    "github.com/common-library/go/database/redis"
)

func main() {
    var client redis.Client
    
    err := client.Initialize("localhost:6379", "", 20, 120*time.Second)
    if err != nil {
        log.Fatal(err)
    }
    defer client.Finalize()
    
    // Store session with 1 hour expiration
    sessionID := "session:user123"
    sessionData := `{"user_id": 123, "name": "Alice", "role": "admin"}`
    
    err = client.Setex(sessionID, 3600, sessionData)
    if err != nil {
        log.Fatal(err)
    }
    
    // Check if session exists
    exists, err := client.Exists(sessionID)
    if exists {
        // Retrieve session
        data, err := client.Get(sessionID)
        if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("Session data: %s\n", data)
        
        // Check remaining time
        ttl, _ := client.Ttl(sessionID)
        fmt.Printf("Session expires in %d seconds\n", ttl)
    }
    
    // Delete session on logout
    err = client.Del(sessionID)
}
Caching
func getCachedUser(client *redis.Client, userID int) (User, error) {
    cacheKey := fmt.Sprintf("user:%d", userID)
    
    // Try to get from cache
    cached, err := client.Get(cacheKey)
    if err == nil && cached != "" {
        var user User
        json.Unmarshal([]byte(cached), &user)
        return user, nil
    }
    
    // Cache miss - fetch from database
    user, err := fetchUserFromDB(userID)
    if err != nil {
        return User{}, err
    }
    
    // Store in cache with 5 minute expiration
    userData, _ := json.Marshal(user)
    client.Setex(cacheKey, 300, string(userData))
    
    return user, nil
}
Rate Limiting
func checkRateLimit(client *redis.Client, userID int, limit int) (bool, error) {
    key := fmt.Sprintf("rate_limit:user:%d", userID)
    
    // Check current count
    countStr, err := client.Get(key)
    if err != nil {
        // First request - initialize counter
        client.Setex(key, 60, "1") // 1 minute window
        return true, nil
    }
    
    count, _ := strconv.Atoi(countStr)
    if count >= limit {
        return false, nil // Rate limit exceeded
    }
    
    // Increment counter
    newCount := count + 1
    ttl, _ := client.Ttl(key)
    client.Setex(key, ttl, strconv.Itoa(newCount))
    
    return true, nil
}
Batch Operations
// Store multiple user preferences
err := client.MSet(
    "pref:user1:theme", "dark",
    "pref:user1:lang", "en",
    "pref:user1:timezone", "UTC",
)

// Retrieve multiple preferences
prefs, err := client.MGet(
    "pref:user1:theme",
    "pref:user1:lang",
    "pref:user1:timezone",
)

fmt.Printf("Theme: %s, Language: %s, Timezone: %s\n", prefs[0], prefs[1], prefs[2])
Database Maintenance
// Switch to analytics database
client.Select(2)

// Get statistics
count, _ := client.DBsize()
fmt.Printf("Analytics database has %d keys\n", count)

// Clear old analytics data
client.FlushDB()

// Switch back to main database
client.Select(0)

API Reference

Initialization
Initialize(address, password string, maxConnection int, timeout time.Duration) error

Initialize the Redis client with connection pool settings.

Parameters:

  • address - Redis server address (host:port)
  • password - Authentication password (empty string for no auth)
  • maxConnection - Maximum number of idle connections in pool
  • timeout - Idle connection timeout duration

Returns: Error if initialization fails

Connection Methods
Ping() error

Test connection to Redis server.

Finalize() error

Close all connections and clean up resources.

Select(index int) error

Select database by index (0-15 for default Redis configuration).

String Operations
Get(key any) (string, error)

Retrieve value for the given key.

Set(key, value any) error

Set key to hold the string value.

Setex(key any, second int, value any) error

Set key with expiration time in seconds.

MGet(keys ...any) ([]string, error)

Get values of multiple keys.

MSet(args ...any) error

Set multiple keys to multiple values. Arguments: key1, value1, key2, value2, ...

Key Management
Del(key any) error

Delete the specified key.

Exists(keys ...any) (bool, error)

Check if one or more keys exist.

Rename(currentKey, newKey any) error

Rename a key.

RandomKey() (string, error)

Return a random key from the current database.

Ttl(key any) (int, error)

Get time to live for a key in seconds.

Return values:

  • -2 if key does not exist
  • -1 if key has no expiration
  • Positive integer for remaining seconds
Database Operations
DBsize() (int, error)

Return the number of keys in the current database.

FlushDB() error

Delete all keys in the current database.

FlushAll() error

Delete all keys in all databases.

Server Information
Info(info string) (string, error)

Get information and statistics about the server.

Parameters:

  • info - Category name (case-insensitive) or "ALL" for everything

Categories:

  • Server - General server information
  • Clients - Client connections section
  • Memory - Memory consumption
  • Persistence - RDB and AOF information
  • Stats - General statistics
  • Replication - Master/replica replication info
  • CPU - CPU consumption statistics
  • Cluster - Cluster section
  • Keyspace - Database related statistics

Best Practices

1. Configure Pool Size Appropriately
// Web application with high concurrency
client.Initialize(addr, pass, 100, 300*time.Second)

// Background worker
client.Initialize(addr, pass, 10, 60*time.Second)
2. Always Close Connections
defer client.Finalize()
3. Use SETEX for Temporary Data
// Good: Automatic expiration
client.Setex("temp:token", 3600, token)

// Avoid: Manual cleanup needed
client.Set("temp:token", token)
// Remember to delete later!
4. Batch Operations When Possible
// Good: Single round trip
values, err := client.MGet("key1", "key2", "key3")

// Avoid: Multiple round trips
val1, _ := client.Get("key1")
val2, _ := client.Get("key2")
val3, _ := client.Get("key3")
5. Handle TTL Return Values
ttl, err := client.Ttl("key")
if err != nil {
    return err
}

switch ttl {
case -2:
    fmt.Println("Key does not exist")
case -1:
    fmt.Println("Key has no expiration")
default:
    fmt.Printf("Expires in %d seconds\n", ttl)
}
6. Use Key Naming Conventions
// Good: Hierarchical naming
"user:123:profile"
"session:abc123:data"
"cache:product:456"

// Avoid: Flat naming
"user123profile"
"sessionabc123"

Error Handling

Common errors and solutions:

// Not initialized
err := client.Get("key")
// Error: "please call Initialize first"
// Solution: Call Initialize before any operation

// Connection failed
err := client.Initialize("localhost:6379", "", 10, 60*time.Second)
// Error: dial tcp connection refused
// Solution: Ensure Redis server is running

// Authentication failed
err := client.Initialize("localhost:6379", "wrong_password", 10, 60*time.Second)
// Error: NOAUTH Authentication required / ERR invalid password
// Solution: Use correct password or empty string for no auth

Performance Tips

  1. Use Connection Pooling - Reuse connections instead of creating new ones
  2. Batch Operations - Use MGET/MSET to reduce network round trips
  3. Set Appropriate TTLs - Prevent memory bloat from stale keys
  4. Monitor Memory - Use INFO Memory to track usage
  5. Use SELECT Sparingly - Minimize database switching overhead

Limitations

  1. Limited Data Structures - Only basic string operations (no Lists, Sets, Hashes, etc.)
  2. No Pipeline Support - Cannot batch commands into pipeline
  3. No Pub/Sub - No support for publish/subscribe messaging
  4. No Lua Scripts - Cannot execute Lua scripts
  5. No Transactions - No MULTI/EXEC transaction support

For advanced features, consider using the Redigo library directly.

Dependencies

  • github.com/gomodule/redigo/redis - Redis client library
  • Redigo - Full-featured Redis client
  • go-redis - Alternative Redis client

Further Reading

Documentation

Overview

Package redis provides a Redis client implementation with connection pooling.

This package offers a convenient wrapper around the Redigo Redis client library, providing connection pooling, automatic reconnection, and simplified method signatures for common Redis operations.

Features:

  • Connection pooling with configurable size and timeout
  • Automatic health checks via PING
  • Support for all common Redis data types and operations
  • Database selection
  • Key expiration (TTL) management
  • Batch operations (MGET, MSET)

Example:

var client redis.Client
client.Initialize("localhost:6379", "", 10, 60*time.Second)
defer client.Finalize()
client.Set("key", "value")
value, _ := client.Get("key")

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a struct that provides client related methods.

func (*Client) DBsize

func (c *Client) DBsize() (int, error)

DBsize returns the number of keys in the currently selected database.

Returns:

  • int: Number of keys in the current database, or -1 if client not initialized
  • error: Error if client not initialized or DBSIZE command fails, nil on success

This command provides a count of all keys in the current database, regardless of their type. The operation is very fast as Redis maintains a count internally.

Example:

count, err := client.DBsize()
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Database has %d keys\n", count)

func (*Client) Del

func (c *Client) Del(key any) error

Del deletes the specified key.

Parameters:

  • key: The key to delete (can be string, int, or any type convertible to string)

Returns:

  • error: Error if client not initialized or DEL command fails, nil on success

If the key does not exist, the operation succeeds without error. This function removes the key and its associated value from the database.

Example:

err := client.Del("session:abc123")
if err != nil {
    log.Fatal(err)
}

func (*Client) Exists

func (c *Client) Exists(keys ...any) (bool, error)

Exists checks if one or more keys exist.

Parameters:

  • keys: Variable number of keys to check

Returns:

  • bool: true if at least one key exists, false if none exist
  • error: Error if client not initialized or EXISTS command fails, nil on success

When multiple keys are provided, this function returns true if at least one of them exists. The actual EXISTS command returns the count of existing keys, but this function converts it to a boolean.

Example:

// Check single key
exists, err := client.Exists("user:1")
if err != nil {
    log.Fatal(err)
}
if exists {
    fmt.Println("User exists")
}

// Check multiple keys
exists, err = client.Exists("key1", "key2", "key3")

func (*Client) Finalize

func (c *Client) Finalize() error

Finalize closes all connections and cleans up resources.

Returns:

  • error: Always returns nil

This function should be called when the client is no longer needed, typically using defer after Initialize. It closes both the active connection (if any) and the connection pool.

Example:

var client redis.Client
client.Initialize("localhost:6379", "", 10, 60*time.Second)
defer client.Finalize() // Ensure cleanup

func (*Client) FlushAll

func (c *Client) FlushAll() error

FlushAll deletes all keys in all databases.

Returns:

  • error: Error if client not initialized or FLUSHALL command fails, nil on success

This operation removes all keys from all databases on the Redis server. Use with extreme caution as this operation cannot be undone and affects all databases.

Warning: This is a destructive operation that will delete ALL data across ALL databases.

Example:

err := client.FlushAll() // Clears all databases
if err != nil {
    log.Fatal(err)
}

func (*Client) FlushDB

func (c *Client) FlushDB() error

FlushDB deletes all keys in the currently selected database.

Returns:

  • error: Error if client not initialized or FLUSHDB command fails, nil on success

This operation removes all keys from the current database only. Keys in other databases are not affected. Use with caution as this operation cannot be undone.

Warning: This is a destructive operation that will delete all data in the current database.

Example:

client.Select(1) // Switch to database 1
err := client.FlushDB() // Only database 1 is cleared
if err != nil {
    log.Fatal(err)
}

func (*Client) Get

func (c *Client) Get(key any) (string, error)

Get retrieves the value of the specified key.

Parameters:

  • key: The key to retrieve (can be string, int, or any type convertible to string)

Returns:

  • string: The value stored at the key, or empty string if key doesn't exist
  • error: Error if client not initialized or GET command fails, nil on success

If the key does not exist, Redis returns a nil reply which is converted to an empty string. If the key holds a value that is not a string, an error is returned.

Example:

value, err := client.Get("user:1:name")
if err != nil {
    log.Fatal(err)
}
fmt.Println(value) // "Alice"

func (*Client) Info

func (c *Client) Info(info string) (string, error)

Info retrieves information and statistics about the Redis server.

Parameters:

  • info: Category name (case-insensitive) or "ALL" for all categories. Valid categories: "Server", "Clients", "Memory", "Persistence", "Stats", "Replication", "CPU", "Cluster", "Keyspace"

Returns:

  • string: Server information in text format with key-value pairs
  • error: Error if client not initialized or INFO command fails, nil on success

The returned string contains multiple lines with information about the selected category. Each line is in the format "field:value". Sections are separated by "# Section" lines.

Example:

memoryInfo, err := client.Info("Memory")
if err != nil {
    log.Fatal(err)
}
fmt.Println(memoryInfo)
// Output: # Memory
// used_memory:1234567
// used_memory_human:1.18M
// ...

func (*Client) Initialize

func (c *Client) Initialize(address, password string, maxConnection int, timeout time.Duration) error

Initialize initializes the Redis client with connection pool settings.

Parameters:

  • address: Redis server address in the format "host:port" (e.g., "localhost:6379")
  • password: Authentication password. Use empty string "" for no authentication
  • maxConnection: Maximum number of idle connections in the pool
  • timeout: Idle connection timeout duration. Connections idle longer than this will be closed

Returns:

  • error: Error if connection test fails, nil on success

The function creates a connection pool and validates connectivity by sending a PING command. All connections in the pool are tested on borrow using PING to ensure they are still alive.

Example:

var client redis.Client
err := client.Initialize("localhost:6379", "", 10, 60*time.Second)
if err != nil {
    log.Fatal(err)
}
defer client.Finalize()

func (*Client) MGet

func (c *Client) MGet(keys ...any) ([]string, error)

MGet retrieves the values of all specified keys.

Parameters:

  • keys: Variable number of keys to retrieve

Returns:

  • []string: Slice of values corresponding to the keys. Empty string for non-existing keys
  • error: Error if client not initialized or MGET command fails, nil on success

For every key that does not hold a string value or does not exist, the slice contains an empty string. The returned values are in the same order as the requested keys.

Example:

values, err := client.MGet("key1", "key2", "key3")
if err != nil {
    log.Fatal(err)
}
for i, val := range values {
    fmt.Printf("Key %d: %s\n", i+1, val)
}

func (*Client) MSet

func (c *Client) MSet(args ...any) error

MSet sets multiple keys to multiple values in a single atomic operation.

Parameters:

  • args: Variable number of alternating key-value pairs (key1, value1, key2, value2, ...)

Returns:

  • error: Error if client not initialized or MSET command fails, nil on success

This operation is atomic, meaning all keys are set at once. Existing values are overwritten. The number of arguments must be even (pairs of keys and values).

Example:

err := client.MSet(
    "user:1:name", "Alice",
    "user:1:email", "alice@example.com",
    "user:1:age", "30",
)
if err != nil {
    log.Fatal(err)
}

func (*Client) Ping

func (c *Client) Ping() error

Ping tests the connection to the Redis server.

Returns:

  • error: Error if client not initialized or PING command fails, nil if connection is healthy

This function sends a PING command to the Redis server to verify connectivity. It returns an error if Initialize has not been called first.

Example:

err := client.Ping()
if err != nil {
    log.Println("Redis connection failed:", err)
}

func (*Client) RandomKey

func (c *Client) RandomKey() (string, error)

RandomKey returns a random key from the currently selected database.

Returns:

  • string: A random key from the database, or empty string if database is empty
  • error: Error if client not initialized or RANDOMKEY command fails, nil on success

This function selects a random key from the current database. If the database is empty, an empty string is returned. This is useful for sampling or debugging.

Example:

key, err := client.RandomKey()
if err != nil {
    log.Fatal(err)
}
if key != "" {
    fmt.Printf("Random key: %s\n", key)
} else {
    fmt.Println("Database is empty")
}

func (*Client) Rename

func (c *Client) Rename(currentKey, newKey any) error

Rename renames a key to a new name.

Parameters:

  • currentKey: The existing key to rename
  • newKey: The new name for the key

Returns:

  • error: Error if client not initialized, key doesn't exist, or RENAME command fails

If newKey already exists, it will be overwritten. If currentKey does not exist, an error is returned. The operation is atomic.

Example:

err := client.Rename("old_session", "new_session")
if err != nil {
    log.Fatal(err)
}

func (*Client) Select

func (c *Client) Select(index int) error

Select switches to the specified database by index.

Parameters:

  • index: Database index to select (default Redis configuration supports 0-15)

Returns:

  • error: Error if client not initialized or SELECT command fails, nil on success

Redis supports multiple databases identified by a numeric index. The default database is 0. This function changes the currently active database for subsequent operations.

Example:

err := client.Select(1) // Switch to database 1
if err != nil {
    log.Fatal(err)
}

func (*Client) Set

func (c *Client) Set(key, value any) error

Set sets the key to hold the specified string value.

Parameters:

  • key: The key to set (can be string, int, or any type convertible to string)
  • value: The value to store (can be string, int, or any type convertible to string)

Returns:

  • error: Error if client not initialized or SET command fails, nil on success

If the key already holds a value, it is overwritten. Any existing time-to-live (TTL) associated with the key is discarded.

Example:

err := client.Set("user:1:name", "Alice")
if err != nil {
    log.Fatal(err)
}

func (*Client) Setex

func (c *Client) Setex(key any, second int, value any) error

Setex sets the key to hold the value with an expiration time in seconds.

Parameters:

  • key: The key to set (can be string, int, or any type convertible to string)
  • second: Time to live in seconds before the key is automatically deleted
  • value: The value to store (can be string, int, or any type convertible to string)

Returns:

  • error: Error if client not initialized or SETEX command fails, nil on success

This is an atomic operation that sets both the value and expiration time. The key will be automatically deleted after the specified number of seconds. This is useful for temporary data like sessions, caches, or rate limiting.

Example:

// Store session data that expires in 1 hour (3600 seconds)
err := client.Setex("session:abc123", 3600, "user_data")
if err != nil {
    log.Fatal(err)
}

func (*Client) Ttl

func (c *Client) Ttl(key any) (int, error)

Ttl returns the remaining time to live of a key in seconds.

Parameters:

  • key: The key to check (can be string, int, or any type convertible to string)

Returns:

  • int: Time to live in seconds, or special values: -2 if the key does not exist -1 if the key exists but has no associated expiration Positive integer for the remaining seconds until expiration
  • error: Error if client not initialized or TTL command fails, nil on success

Example:

ttl, err := client.Ttl("session:abc123")
if err != nil {
    log.Fatal(err)
}
switch ttl {
case -2:
    fmt.Println("Key does not exist")
case -1:
    fmt.Println("Key has no expiration")
default:
    fmt.Printf("Key expires in %d seconds\n", ttl)
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL