Marketplace

redis-strings

Master Redis Strings - SET, GET, INCR, DECR, atomic counters, binary-safe operations, and caching patterns

$ インストール

git clone https://github.com/pluginagentmarketplace/custom-plugin-redis /tmp/custom-plugin-redis && cp -r /tmp/custom-plugin-redis/skills/redis-strings ~/.claude/skills/custom-plugin-redis

// tip: Run this command in your terminal to install the skill


name: redis-strings description: Master Redis Strings - SET, GET, INCR, DECR, atomic counters, binary-safe operations, and caching patterns sasmp_version: "1.3.0" bonded_agent: 02-redis-data-structures bond_type: PRIMARY_BOND

Production Configuration

version: "2.1.0" last_updated: "2025-01"

Parameters

parameters: key: type: string required: true pattern: "^[a-zA-Z0-9:_-]+$" max_length: 512 value: type: string required: true max_size: "512MB" ttl_seconds: type: integer required: false min: 1 max: 31536000 nx_xx: type: string required: false enum: [NX, XX] description: "NX=only if not exists, XX=only if exists"

Retry Configuration

retry_config: max_retries: 3 backoff_strategy: exponential backoff_base_ms: 100 retryable_errors: - connection_timeout - BUSY

Observability

observability: logging: level: debug include_key_pattern: true metrics: - operation_latency_ms - cache_hit_ratio - key_size_bytes

Validation Rules

validation: key_naming: pattern: "object:id:field" examples: ["user:123:profile", "cache:api:users"] value_limits: warn_size_kb: 100 max_size_kb: 10240

Redis Strings Skill

Overview

Production-grade String operations for Redis. Master atomic counters, caching patterns, and binary-safe string manipulation.

Core Commands

Basic Operations

SET key value [EX seconds] [PX milliseconds] [NX|XX] [KEEPTTL]
GET key
GETEX key [EX seconds|PX ms|EXAT ts|PXAT ts|PERSIST]  # Get + set TTL
DEL key [key ...]
EXISTS key [key ...]

Atomic Counters

INCR key                      # +1 (creates if missing, starts at 0)
DECR key                      # -1
INCRBY key increment          # +N
DECRBY key decrement          # -N
INCRBYFLOAT key increment     # Float increment

String Manipulation

APPEND key value              # Append to value
STRLEN key                    # Get length
GETRANGE key start end        # Substring (0-indexed, inclusive)
SETRANGE key offset value     # Replace from offset

Batch Operations

MSET key value [key value ...]      # Set multiple
MGET key [key ...]                  # Get multiple
MSETNX key value [key value ...]    # Set multiple if none exist

Advanced Options (Redis 6.2+)

SET key value GET                   # Set and return old value
SET key value IFEQ oldvalue         # Set if current equals (Redis 7.4+)
GETDEL key                          # Get and delete
SETEX key seconds value             # Set with TTL (deprecated, use SET EX)

Production Patterns

Pattern 1: Cache with TTL

# Set with 1-hour TTL
SET cache:user:123 '{"name":"John","email":"john@example.com"}' EX 3600

# Get (returns nil if expired)
GET cache:user:123

# Refresh TTL on access
GETEX cache:user:123 EX 3600

Pattern 2: Rate Limiter (Fixed Window)

# Increment counter, set TTL on first request
INCR ratelimit:user:123:minute
EXPIRE ratelimit:user:123:minute 60 NX

# Check count
GET ratelimit:user:123:minute

Pattern 3: Distributed Lock

# Acquire lock (NX = only if not exists)
SET lock:resource:123 "holder-uuid" NX EX 30

# Release lock (only if we own it) - use Lua
EVAL "if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end" 1 lock:resource:123 "holder-uuid"

Pattern 4: Session Storage

# Create session
SET session:abc123 '{"user_id":1,"created":1704067200}' EX 86400

# Touch session (reset TTL)
GETEX session:abc123 EX 86400

# Invalidate session
DEL session:abc123

Command Complexity

CommandComplexityNotes
SET/GETO(1)Constant time
MSET/MGETO(N)N = number of keys
INCR/DECRO(1)Atomic
APPENDO(1)Amortized
GETRANGEO(N)N = returned length
STRLENO(1)Stored metadata

Assets

  • rate-limiter.lua - Atomic rate limiting script
  • config.yaml - Pattern configuration

Scripts

  • string-benchmark.sh - Performance testing script
  • helper.py - Python utilities

References

  • STRING_PATTERNS.md - Common patterns guide
  • GUIDE.md - Complete reference

Troubleshooting Guide

Common Issues & Solutions

1. WRONGTYPE Error

WRONGTYPE Operation against a key holding the wrong kind of value

Cause: Trying string operation on non-string key

Diagnosis:

TYPE mykey  # Check actual type

Prevention:

  • Use consistent key naming conventions
  • Check type before operations in scripts

2. Value Too Large

string exceeds maximum allowed size (512MB)

Fix:

  • Compress data before storing
  • Split into multiple keys
  • Use appropriate data structure (Hash for objects)

3. INCR on Non-Integer

ERR value is not an integer or out of range

Cause: INCR/DECR on string that isn't a valid integer

Fix:

# Check current value
GET counter

# Reset if corrupted
SET counter 0

4. NX/XX Not Working as Expected

# NX only sets if key doesn't exist
SET key value NX  # Returns nil if key exists

# XX only sets if key exists
SET key value XX  # Returns nil if key missing

Debug Checklist

□ Key exists? (EXISTS key)
□ Correct type? (TYPE key)
□ Value is valid integer for INCR? (GET key)
□ TTL set correctly? (TTL key)
□ Key pattern consistent?
□ Value size reasonable?

Performance Considerations

ScenarioIssueSolution
Large valuesHigh latencyCompress or split
Many small keysMemory overheadUse Hash for related data
No TTL on cacheMemory leakAlways set TTL
MGET 1000+ keysBlockingBatch into smaller chunks

Error Codes Reference

CodeNameDescriptionRecovery
S001WRONGTYPEType mismatchCheck TYPE, fix key
S002OVERFLOWInteger overflowUse INCRBYFLOAT or reset
S003NANNot a numberValidate before INCR
S004TOOLARGEValue > 512MBCompress or split
S005SYNTAXInvalid commandCheck syntax

Test Template

# test_redis_strings.py
import redis
import pytest

@pytest.fixture
def r():
    return redis.Redis(decode_responses=True)

def test_set_get(r):
    r.set("test:string:1", "hello")
    assert r.get("test:string:1") == "hello"
    r.delete("test:string:1")

def test_incr(r):
    r.set("test:counter", "10")
    r.incr("test:counter")
    assert r.get("test:counter") == "11"
    r.delete("test:counter")

def test_set_nx(r):
    r.delete("test:nx")
    assert r.set("test:nx", "first", nx=True) == True
    assert r.set("test:nx", "second", nx=True) == None
    r.delete("test:nx")

def test_ttl(r):
    r.set("test:ttl", "value", ex=60)
    ttl = r.ttl("test:ttl")
    assert 55 < ttl <= 60
    r.delete("test:ttl")