grass-redis
Redis Sentinel client with optional mutual TLS for high-availability Redis clusters.
Features
- Automatic failover via Sentinel
- Connection pooling and caching
- Read replicas for load distribution
- TLS security with optional client certificates
- Service discovery - automatically find primary and replicas
- Multiple databases - manage multiple Redis instances from one client
Installation
pip install grass-redis
Quick Start
Using Factory Method (Recommended)
Load configuration from /etc/redis/credentials.env:
from grass_redis import create_client_from_credentials
# One-line client creation
with create_client_from_credentials() as client:
# Connect to database
db = client.get_primary("redis-instance-01")
db.set("key", "value")
# Read from replica for load distribution
replica = client.get_replica("redis-instance-01")
value = replica.get("key")
The factory method automatically:
- Loads Sentinel endpoints from
/etc/redis/credentials.env - Loads all database passwords
- Configures TLS with
/etc/redis/ca.crt - Returns a ready-to-use client
Manual Configuration
from pathlib import Path
from grass_redis import RedisSentinelClient, SentinelConfig
config = SentinelConfig(
sentinel_hosts=[
("sentinel1.example.com", 26379),
("sentinel2.example.com", 26379),
("sentinel3.example.com", 26379),
],
databases={"redis-instance-01": "password"},
certs_dir=Path("/etc/redis"),
)
with RedisSentinelClient(config) as client:
db = client.get_primary("redis-instance-01")
db.set("key", "value")
Configuration
Credentials File Format
Deploy to /etc/redis/credentials.env:
# Sentinel endpoints
REDIS_SENTINEL_HOSTS=sentinel1.example.com:26379,sentinel2.example.com:26379
# Database credentials
REDIS_INSTANCE_01_MASTER=redis-instance-01
REDIS_INSTANCE_01_PORT=6379
REDIS_INSTANCE_01_PASSWORD=your-password
Required Files
/etc/redis/ca.crt- CA certificate (required, 644)/etc/redis/credentials.env- Configuration and passwords (600)
Common Operations
Basic Operations with TTL
db = client.get_primary("redis-instance-01")
db.set("key", "value", ex=60) # Expires in 60 seconds
value = db.get("key")
Hash Operations
db.hset("user:123", mapping={
"name": "John",
"email": "john@example.com",
"status": "active"
})
data = db.hgetall("user:123")
name = db.hget("user:123", "name")
List Operations
# Push items to list
db.lpush("queue:tasks", "task1", "task2")
# Pop from list
task = db.rpop("queue:tasks")
# Get list length
length = db.llen("queue:tasks")
Set Operations
# Add items to set
db.sadd("processed:urls", "url1", "url2", "url3")
# Check membership
exists = db.sismember("processed:urls", "url1")
# Get all members
urls = db.smembers("processed:urls")
Using Read Replicas
Distribute read load across replicas:
with create_client_from_credentials() as client:
# Write to primary
primary = client.get_primary("redis-instance-01")
primary.set("data", "value")
# Read from replica (automatic load balancing)
replica = client.get_replica("redis-instance-01")
value = replica.get("data")
Service Discovery
Find where databases are currently running:
with create_client_from_credentials() as client:
# Find current primary
host, port = client.discover_primary("redis-instance-01")
print(f"Primary: {host}:{port}")
# Find all replicas
replicas = client.discover_replicas("redis-instance-01")
for host, port in replicas:
print(f"Replica: {host}:{port}")
Error Handling
from redis.exceptions import ConnectionError, TimeoutError
try:
with create_client_from_credentials() as client:
db = client.get_primary("redis-instance-01")
db.set("key", "value")
except FileNotFoundError as e:
print(f"Missing credentials file: {e}")
except ConnectionError as e:
print(f"Cannot connect to Redis: {e}")
except TimeoutError as e:
print(f"Operation timed out: {e}")
except KeyError as e:
print(f"Database not configured: {e}")
API
Factory Method
create_client_from_credentials()- Load from/etc/redis/credentials.env
SentinelConfig
sentinel_hosts- List[(host, port)]databases- Dict[db_name, password]certs_dir- Path (default:/etc/redis)
RedisSentinelClient
get_primary(db)- Connection for writesget_replica(db)- Connection for reads (load balanced)discover_primary(db)- Get current primary addressdiscover_replicas(db)- Get all replica addressestest_connection(db)- PING test
Key Features
- No Hardcoded Endpoints - Everything loaded from configuration files
- Sentinel Discovery - Sentinels automatically find current primary location
- TLS Required - All connections use TLS with CA certificate
- Connection Pooling - Automatically managed, connections reused efficiently
- Automatic Failover - Sentinel promotes replicas if primary fails
Example Scripts
Included example scripts:
example_production_usage.py- Comprehensive production examplesexample_new_setup.py- Simple manual configuration example
Publishing to PyPI
See PUBLISHING.md for complete instructions on publishing this package to PyPI.
License
MIT License - see LICENSE file for details.
Metadata
Release files for grass-redis 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| grass_redis-0.2.0.tar.gz | 12.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| grass_redis-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.6 kB
Release files / grass_redis-0.2.0.tar.gz
| Download URL | grass_redis-0.2.0.tar.gz |
|---|---|
| Size | 12.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d6d76dbe45695510bd3c96831f2086326c5d0c1b86f6ea8e3d42bdf65f3dd9e0
|
|
BLAKE2b-256 checksum How to use checksums |
1f1abe4923feaa805c760a1b07df263a1ffb4c8e066856b055420cbb144d67e1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / grass_redis-0.2.0-py3-none-any.whl
| Download URL | grass_redis-0.2.0-py3-none-any.whl |
|---|---|
| Size | 6.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a000ae6d70b68b19851fb5255e6f17434275ccdcafcdfc6acce6a9d0b3259905
|
|
BLAKE2b-256 checksum How to use checksums |
81a4636ceeeeaa9a75c3ed02c5071782f173d910b90d7e6b4e4260afcd45ecc8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|