Redis Hashes (Part 2)

This lesson covers numeric operations on hash fields, iterative queries, and other advanced features.

HINCRBY: Increment Field Values

Hash fields can store numeric strings and support atomic arithmetic operations.

HINCRBY: Integer Increment

REDIS
# Create article statistics
HSET article:123 views 1000 likes 50 comments 20

# Increment view count
HINCRBY article:123 views 1
(integer) 1001

# Increment like count
HINCRBY article:123 likes 1
(integer) 51

# Batch increment
HINCRBY article:123 views 10
(integer) 1011

# Decrement (pass a negative number)
HINCRBY article:123 likes -1
(integer) 50

HINCRBYFLOAT: Floating-Point Increment

REDIS
# Product price
HSET product:2001 price 99.99

# Increase price
HINCRBYFLOAT product:2001 price 10.5
"110.49"

# Decrease price (pass a negative number)
HINCRBYFLOAT product:2001 price -5.0
"105.49"

Use Case: Counter Group

REDIS
# User statistics
HSET user:stats:1 posts 0 followers 0 following 0

# Publish an article
HINCRBY user:stats:1 posts 1

# Gain a follower
HINCRBY user:stats:1 followers 1

# Follow someone
HINCRBY user:stats:1 following 1

# View statistics
HGETALL user:stats:1
💡 Advantage: Using a hash to store multiple counters is more memory-efficient than using multiple string keys.

HSCAN: Iterate Through Large Hashes

When a hash has many fields, HGETALL returns all data at once, which can block the server. HSCAN allows batch iteration.

Basic Usage

REDIS
# Create a large hash
HSET large:hash field1 "value1" field2 "value2" ... field1000 "value1000"

# Start iteration
HSCAN large:hash 0
1) "127"          # Cursor for next iteration
2) 1) "field1"
   2) "value1"
   3) "field2"
   4) "value2"
   ...

# Continue iteration
HSCAN large:hash 127
1) "0"            # Cursor of 0 means iteration is complete
2) 1) "field999"
   2) "value999"
   ...

Match Pattern

REDIS
# Get only fields matching a pattern
HSCAN user:1 0 MATCH age*
1) "0"
2) 1) "age"
   2) "25"

Specify Count Per Iteration

REDIS
# Return approximately 100 fields per iteration
HSCAN large:hash 0 COUNT 100
💡 Use case: HSCAN is great for iterating through large hashes without blocking the server.

Advanced Hash Applications

Use Case 1: E-commerce Product Details

REDIS
# Store full product info
HSET product:3001 \
  name "iPhone 15 Pro" \
  brand "Apple" \
  price 8999 \
  stock 100 \
  category "phone" \
  sales 0 \
  rating 4.8

# View basic product info
HMGET product:3001 name price stock

# Increment sales
HINCRBY product:3001 sales 1

# Decrement stock
HINCRBY product:3001 stock -1

# Update rating
HSET product:3001 rating 4.9

# Check stock
HGET product:3001 stock

Use Case 2: User Configuration

REDIS
# Store user config
HSET user:config:1 \
  theme "dark" \
  language "en" \
  notifications "on" \
  privacy "public" \
  timezone "America/New_York"

# Get a single config
HGET user:config:1 theme

# Modify a config
HSET user:config:1 theme "light"

# Batch get configs
HMGET user:config:1 theme language notifications

Use Case 3: Real-time Statistics

REDIS
# Daily site statistics
HSET stats:20260623 \
  page_views 0 \
  unique_visitors 0 \
  new_users 0 \
  orders 0 \
  revenue 0.0

# Increment page views
HINCRBY stats:20260623 page_views 1

# Increment unique visitors
HINCRBY stats:20260623 unique_visitors 1

# Increment orders
HINCRBY stats:20260623 orders 1

# Increment revenue
HINCRBYFLOAT stats:20260623 revenue 299.99

# View statistics
HGETALL stats:20260623

Use Case 4: A/B Test Configuration

REDIS
# Store experiment config
HSET experiment:homepage \
  button_color "blue" \
  layout "grid" \
  show_banner "yes" \
  discount_rate 0.1

# Get experiment config
HGET experiment:homepage button_color

# Update experiment config
HSET experiment:homepage button_color "red"

Hash vs JSON Comparison

Storage Comparison

Method 1: Hash

REDIS
HSET user:1 name "Alice" age 25 email "alice@example.com"

Method 2: String JSON

REDIS
SET user:1 '{"name":"Alice","age":25,"email":"alice@example.com"}'

Operation Comparison

Operation Hash String JSON
Get single field HGET user:1 name Need to parse JSON
Modify single field HSET user:1 age 26 Read → parse → modify → serialize → write back
Get all fields HGETALL user:1 GET user:1 + parse JSON
Numeric operation HINCRBY user:1 age 1 Need to parse → modify → serialize
Memory usage Smaller Larger (JSON format overhead)

Use Case Comparison

Scenario Recommended Reason
User profile Hash Independent fields, frequent updates
Product info Hash Independent fields, partial updates
Complex nested objects String JSON Hash does not support nesting
Array data String JSON Hash does not support arrays
Configuration object Hash Independent fields, fast queries
💡 Selection principle:

  • Independent fields, frequent partial updates → Hash
  • Complex nesting, arrays needed → String JSON
  • Numeric operations needed → Hash

Performance Optimization

1. Avoid Large Hashes

REDIS
# ❌ Not recommended: single hash with too many fields
HSET big:hash field1 ... field10000

# ✅ Recommended: shard into multiple hashes
HSET hash:part1 field1 ... field1000
HSET hash:part2 field1001 ... field2000

2. Use HSCAN Instead of HGETALL

REDIS
# ❌ HGETALL on large hash
HGETALL large:hash  # May block

# ✅ Use HSCAN for iteration
HSCAN large:hash 0

3. Batch Operations Reduce Network Round Trips

REDIS
# ❌ Multiple individual operations
HSET user:1 name "Alice"
HSET user:1 age 25
HSET user:1 city "Beijing"

# ✅ Batch operation
HSET user:1 name "Alice" age 25 city "Beijing"

4. Configure Encoding Thresholds

In redis.conf:

CONF
# Hash field count threshold (default 512)
hash-max-ziplist-entries 512

# Hash field value max length (default 64 bytes)
hash-max-ziplist-value 64
ℹ️ Note: Increasing thresholds can save memory but may reduce performance. Adjust based on your actual data.

Hash Limitations

1. No Nesting Support

REDIS
# ❌ Cannot store nested objects directly
HSET user:1 address '{"city":"Beijing","zip":"100000"}'

# ✅ Use string for nested parts
HSET user:1 city "Beijing" zip "100000"

2. No Array Support

REDIS
# ❌ Cannot store arrays
HSET user:1 tags ["redis","database","cache"]

# ✅ Use set or list for arrays
SADD user:1:tags "redis" "database" "cache"

3. Values Can Only Be Strings

REDIS
# All values are strings
HSET user:1 age 25
HGET user:1 age
"25"  # Returns string, not integer

❓ FAQ

Q What happens if HINCRBY is used on a non-numeric field?
A It returns an error: (error) ERR hash value is not an integer. Make sure the field value is a numeric string.
Q Are hash fields ordered?
A No. Hash fields are unordered — HGETALL does not guarantee any specific order.
Q How do I check if a key is a hash type?
A Use the TYPE command: TYPE user:1 returns hash.
Q Does HSCAN guarantee no duplicates?
A No. HSCAN may return duplicate fields — the application layer needs to handle deduplication.
Q What's the difference between hash and set?
A A hash stores field-value pairs; a set stores unique elements. Hashes are for objects, sets are for tags and relationships.

📖 Summary

📝 Exercises

  1. Numeric operations: Use a hash to store article stats (views, likes, comments) and increment with HINCRBY
  2. Product management: Use hash to store product info, practice viewing, modifying, incrementing sales, decrementing stock
  3. Configuration management: Use hash for user config, practice getting single config, batch get, and modifying configs
  4. Performance comparison: Compare the steps for modifying a single field using hash vs String JSON

Next Lesson

In the next lesson, we will learn Redis Lists (Part 1), covering basic list operations.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏