Jorgen's blog Jorgen's blog
首页
  • 平台架构
  • 混合式开发记录
  • 推送服务
  • 数据分析
  • 实时调度
  • 架构思想

    • 分布式
  • 编程框架工具

    • 编程语言
    • 框架
    • 开发工具
  • 数据存储与处理

    • 数据库
    • 大数据
  • 消息、缓存与搜索

    • 消息队列
    • 搜索与日志分析
  • 前端与跨端开发

    • 前端技术
    • Android
  • 系统与运维

    • 操作系统
    • 容器化与 DevOps
  • 物联网与安全

    • 通信协议
    • 安全
    • 云平台
newland
  • 关于我
  • 终身学习
  • 关于时间的感悟
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

jorgen

Love it, make mistakes, learn, keep grinding.
首页
  • 平台架构
  • 混合式开发记录
  • 推送服务
  • 数据分析
  • 实时调度
  • 架构思想

    • 分布式
  • 编程框架工具

    • 编程语言
    • 框架
    • 开发工具
  • 数据存储与处理

    • 数据库
    • 大数据
  • 消息、缓存与搜索

    • 消息队列
    • 搜索与日志分析
  • 前端与跨端开发

    • 前端技术
    • Android
  • 系统与运维

    • 操作系统
    • 容器化与 DevOps
  • 物联网与安全

    • 通信协议
    • 安全
    • 云平台
newland
  • 关于我
  • 终身学习
  • 关于时间的感悟
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 时序数据库
  • Postgres
  • MongoDB入门与实践
  • NewSQL数据库:关系型与NoSQL的完美结合
  • Redis入门与实践:高性能键值数据库指南
    • 前言
    • Redis简介
      • 为什么选择Redis?
    • 安装与配置
      • 安装Redis
      • 启动Redis服务
    • Redis数据结构详解
      • 1. 字符串(String)
      • 2. 哈希(Hash)
      • 3. 列表(List)
      • 4. 集合(Set)
      • 5. 有序集合(ZSet)
    • 实战应用场景
      • 1. 缓存系统
      • 2. 分布式锁
      • 3. 限流器
    • Redis持久化
      • RDB (Redis Database)
      • AOF (Append Only File)
    • Redis集群
      • 主从复制
      • 哨兵模式
      • Redis Cluster
    • 性能优化建议
    • 结语
  • Redis入门与实践
  • SQL基础:关系型数据库的语言
  • 关系型数据库基础
  • 关系型数据库基础与SQL入门
  • 关系型数据库基础理论
  • 关系数据库设计与SQL基础
  • 数据库分类与选型指南
  • 数据库性能优化与调优实战指南
  • 数据库索引与性能优化
  • 数据库索引原理与优化
  • 数据库设计与数据建模:从概念到实践
  • 数据库事务与并发控制:保证数据一致性的核心技术
  • 数据库事务与并发控制:保证数据一致性的核心机制
  • 数据库安全与权限管理-保护数据的基石
  • 数据库备份与恢复策略-确保数据安全的最后一道防线
  • 数据库分布式架构:从CAP理论到分片策略的全面解析
  • 数据库监控与运维-确保数据库健康运行的守护者
  • 数据库高可用方案-构建永不掉线的数据库架构
  • 数据库连接池技术:提升应用性能的关键组件
  • 数据库查询优化与执行计划分析-提升SQL性能的关键技术
  • 数据库迁移策略:平滑过渡的关键步骤与技术实现
  • 数据库缓存策略:提升系统性能的关键武器
  • 数据库性能问题诊断与排查-从现象到根源的系统化方法
  • 数据库版本管理与演进-构建平滑升级的技术路径
  • 数据库分片与分布式数据管理-构建可扩展数据架构的核心技术
  • 数据库云服务与托管解决方案-构建现代化数据架构的必经之路
  • database
Jorgen
2023-10-15
目录

Redis入门与实践:高性能键值数据库指南

# 前言

在之前的博客中,我已经介绍了时序数据库、PostgreSQL和MongoDB。今天,我想和大家聊聊另一个在开发中无处不在的工具——Redis。🚀

如果你曾经开发过Web应用,那么你很可能已经接触过Redis。它就像一个超级快的内存数据存储,被广泛用于缓存、会话管理、消息队列等场景。但Redis到底是什么?它为什么这么快?我们又该如何在实际项目中使用它呢?

今天,我将带你从零开始了解Redis,并通过实际案例展示如何将它应用到项目中。

提示

Redis的全称是REmote DIctionary Server,是一个开源的、基于内存的高性能键值数据库。

# Redis简介

Redis是一个开源的、基于内存的数据结构存储系统,可以用作数据库、缓存和消息中间件。它支持多种数据结构,如字符串、哈希、列表、集合、有序集合等。

# 为什么选择Redis?

  1. 内存存储:数据存储在内存中,读写速度极快,通常能达到每秒数万次操作
  2. 丰富的数据结构:支持多种数据结构,满足不同场景需求
  3. 持久化支持:可以通过RDB和AOF两种方式将数据持久化到磁盘
  4. 高可用性:支持主从复制和哨兵模式,以及最新的Redis Cluster
  5. 原子操作:所有操作都是原子性的,适合做分布式锁等场景

# 安装与配置

# 安装Redis

在Linux系统上,可以通过包管理器安装Redis:

# Ubuntu/Debian
sudo apt update
sudo apt install redis-server

# CentOS/RHEL
sudo yum install redis
1
2
3
4
5
6

或者通过源码编译安装:

# 下载最新稳定版
wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable
make
1
2
3
4
5

# 启动Redis服务

安装完成后,可以通过以下命令启动Redis服务:

# 使用默认配置启动
redis-server

# 使用指定配置文件启动
redis-server /path/to/redis.conf
1
2
3
4
5

连接Redis客户端:

redis-cli
1

# Redis数据结构详解

Redis支持多种数据结构,每种结构都有其特定的用途。

# 1. 字符串(String)

字符串是Redis最基本的数据结构,可以存储文本、JSON、序列化对象等。

# 设置键值
SET mykey "Hello"
# 获取值
GET mykey
# 设置并设置过期时间(秒)
SETEX mykey 60 "This will expire in 60 seconds"
# 批量设置
MSET key1 "value1" key2 "value2"
1
2
3
4
5
6
7
8

在Python中使用Redis字符串:

import redis

r = redis.Redis(host='localhost', port=6379, db=0)
# 设置值
r.set('name', 'Jorgen')
# 获取值
name = r.get('name')
print(name.decode('utf-8'))  # 输出: Jorgen
1
2
3
4
5
6
7
8

# 2. 哈希(Hash)

哈希是键值集合,适合存储对象。

# 设置哈希字段
HSET user:1000 name "Jorgen" age 30 email "jorgen@example.com"
# 获取所有字段和值
HGETALL user:1000
# 获取特定字段
HGET user:1000 name
1
2
3
4
5
6

在Python中使用Redis哈希:

# 设置哈希
r.hset('user:1000', mapping={
    'name': 'Jorgen',
    'age': 30,
    'email': 'jorgen@example.com'
})
# 获取哈希
user = r.hgetall('user:1000')
print(user)  # 输出: {b'name': b'Jorgen', b'age': b'30', b'email': b'jorgen@example.com'}
1
2
3
4
5
6
7
8
9

# 3. 列表(List)

列表是字符串元素的有序集合,常用于实现消息队列。

# 向列表左侧添加元素
LPUSH mylist "world"
LPUSH mylist "hello"
# 获取列表所有元素
LRANGE mylist 0 -1
# 向列表右侧添加元素
RPUSH mylist "redis"
1
2
3
4
5
6
7

在Python中使用Redis列表:

# 添加元素
r.lpush('mylist', 'world', 'hello')
# 获取列表
items = r.lrange('mylist', 0, -1)
print([item.decode('utf-8') for item in items])  # 输出: ['hello', 'world']
1
2
3
4
5

# 4. 集合(Set)

集合是唯一字符串的无序集合,适合存储标签、用户ID等。

# 添加元素到集合
SADD myset "hello"
SADD myset "world"
SADD myset "hello"  # 重复添加不会生效
# 获取集合所有元素
SMEMBERS myset
# 检查元素是否存在
SISMEMBER myset "hello"
1
2
3
4
5
6
7
8

在Python中使用Redis集合:

# 添加元素
r.sadd('myset', 'hello', 'world')
# 获取集合
members = r.smembers('myset')
print([member.decode('utf-8') for member in members])  # 输出: ['hello', 'world'] 或 ['world', 'hello']
1
2
3
4
5

# 5. 有序集合(ZSet)

有序集合是字符串成员与浮点数分数的有序集合,常用于排行榜。

# 添加成员及分数
ZADD leaderboard 100 "user1"
ZADD leaderboard 200 "user2"
ZADD leaderboard 150 "user3"
# 按分数从低到高获取成员
ZRANGE leaderboard 0 -1
# 按分数从高到低获取成员
ZREVRANGE leaderboard 0 -1
# 获取成员分数
ZSCORE leaderboard "user1"
1
2
3
4
5
6
7
8
9
10

在Python中使用Redis有序集合:

# 添加成员
r.zadd('leaderboard', {'user1': 100, 'user2': 200, 'user3': 150})
# 获取排名
rankings = r.zrevrange('leaderboard', 0, -1, withscores=True)
print([(item.decode('utf-8'), score) for item, score in rankings])  
# 输出: [('user2', 200.0), ('user3', 150.0), ('user1', 100.0)]
1
2
3
4
5
6

# 实战应用场景

# 1. 缓存系统

Redis最常见的用途是作为缓存,减轻数据库压力。

import redis
import time
import json
import pymysql

# 初始化连接
redis_conn = redis.Redis(host='localhost', port=6379, db=0)
db_conn = pymysql.connect(host='localhost', user='root', password='password', db='mydb')

def get_user(user_id):
    # 先从缓存获取
    cache_key = f"user:{user_id}"
    cached_user = redis_conn.get(cache_key)
    
    if cached_user:
        print("Cache hit!")
        return json.loads(cached_user.decode('utf-8'))
    
    # 缓存未命中,从数据库获取
    print("Cache miss, querying database...")
    with db_conn.cursor() as cursor:
        cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
        user = cursor.fetchone()
    
    if user:
        # 将结果存入缓存,设置5分钟过期
        redis_conn.setex(cache_key, 300, json.dumps(dict(user)))
    
    return user
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 2. 分布式锁

在高并发场景下,Redis可以用来实现分布式锁。

import redis
import time
import uuid

class RedisLock:
    def __init__(self, redis_conn, lock_name, expire_time=10):
        self.redis_conn = redis_conn
        self.lock_name = f"lock:{lock_name}"
        self.identifier = str(uuid.uuid4())
        self.expire_time = expire_time
    
    def acquire(self):
        # 尝试获取锁
        end = time.time() + self.expire_time
        while time.time() < end:
            # 使用SETNX命令设置锁,并设置过期时间
            if self.redis_conn.set(self.lock_name, self.identifier, nx=True, ex=self.expire_time):
                return True
            time.sleep(0.001)
        return False
    
    def release(self):
        # 使用Lua脚本确保只有锁的持有者才能释放锁
        lua_script = """
        if redis.call("get", KEYS[1]) == ARGV[1] then
            return redis.call("del", KEYS[1])
        else
            return 0
        end
        """
        return self.redis_conn.eval(lua_script, 1, self.lock_name, self.identifier)

# 使用示例
lock = RedisLock(redis_conn, "my_resource")
try:
    if lock.acquire():
        print("Lock acquired, doing some work...")
        time.sleep(10)  # 模拟工作
    else:
        print("Failed to acquire lock")
finally:
    lock.release()
    print("Lock released")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# 3. 限流器

Redis可以用来实现API限流,防止恶意请求。

import redis

class RateLimiter:
    def __init__(self, redis_conn, key, limit, window):
        self.redis_conn = redis_conn
        self.key = f"rate_limit:{key}"
        self.limit = limit  # 限制次数
        self.window = window  # 时间窗口(秒)
    
    def is_allowed(self):
        # 使用Lua脚本实现限流逻辑
        lua_script = """
        local key = KEYS[1]
        local limit = tonumber(ARGV[1])
        local window = tonumber(ARGV[2])
        local current = redis.call("incr", key)
        if current == 1 then
            redis.call("expire", key, window)
        end
        return current <= limit
        """
        result = self.redis_conn.eval(lua_script, 1, self.key, self.limit, self.window)
        return bool(result)

# 使用示例
limiter = RateLimiter(redis_conn, "user:123", 10, 60)  # 1分钟内最多10次请求
for i in range(15):
    if limiter.is_allowed():
        print(f"Request {i+1} allowed")
    else:
        print(f"Request {i+1} rejected")
    time.sleep(5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# Redis持久化

Redis提供了两种持久化机制:RDB和AOF。

# RDB (Redis Database)

RDB是通过快照的方式将数据保存到磁盘,配置示例:

save 900 1     # 900秒内至少有1个key被修改,则保存
save 300 10    # 300秒内至少有10个key被修改,则保存
save 60 10000  # 60秒内至少有10000个key被修改,则保存
1
2
3

优点:

  • 文件紧凑,体积小
  • 恢复速度快
  • 适合做备份

缺点:

  • 可能会丢失最后一次快照后的数据
  • 占用内存大时,fork子进程可能会阻塞

# AOF (Append Only File)

AOF是记录所有写操作命令到日志文件,配置示例:

appendonly yes
appendfsync everysec  # 每秒同步一次
1
2

优点:

  • 数据安全性高,最多丢失1秒数据
  • 日志文件可读,便于修复

缺点:

  • 文件体积大
  • 恢复速度比RDB慢

# Redis集群

当单机Redis无法满足需求时,可以使用Redis集群。

# 主从复制

主从复制是最简单的集群方式,一个主节点可以有多个从节点。

# 从节点配置
slaveof 192.168.1.100 6379
1
2

# 哨兵模式

哨兵模式用于监控主从节点,在主节点故障时自动进行故障转移。

# 启动哨兵
redis-sentinel /path/to/sentinel.conf
1
2

# Redis Cluster

Redis Cluster是官方推荐的集群方案,采用分片存储。

# 创建集群
redis-cli --cluster create 192.168.1.100:7000 192.168.1.100:7001 \
192.168.1.100:7002 192.168.1.100:7003 192.168.1.100:7004 192.168.1.100:7005 \
--cluster-replicas 1
1
2
3
4

# 性能优化建议

  1. 使用连接池:避免频繁创建和销毁连接

    pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
    r = redis.Redis(connection_pool=pool)
    
    1
    2
  2. 批量操作:使用Pipeline减少网络往返

    pipe = r.pipeline()
    for i in range(1000):
        pipe.set(f'key:{i}', f'value:{i}')
    pipe.execute()
    
    1
    2
    3
    4
  3. 合理设置过期时间:避免内存泄漏

    r.setex('temp_data', 3600, 'value')  # 设置1小时后过期
    
    1
  4. 选择合适的数据结构:根据使用场景选择最优的数据结构

    • 存储对象:Hash
    • 排行榜:ZSet
    • 消息队列:List
  5. 避免大Key:大Key会阻塞Redis,影响性能

# 结语

Redis作为一个高性能的键值数据库,在现代应用开发中扮演着至关重要的角色。从缓存到分布式锁,从消息队列到限流器,Redis的应用场景非常广泛。

通过今天的介绍,我们了解了Redis的基本概念、数据结构、持久化机制以及集群方案。更重要的是,我们通过实际案例看到了如何将Redis应用到项目中解决实际问题。

"Redis就像瑞士军刀,虽然小,但功能强大,总能解决你的问题。"

如果你还没有使用过Redis,我强烈建议你动手尝试一下。它不仅能提升你的应用性能,还能让你对数据存储有更深入的理解。

在下一篇文章中,我可能会聊聊Redis的高级特性,比如模块开发、事务处理等。敬请期待!🚀

最后,别忘了Redis的官方文档是最好的学习资源:https://redis.io/documentation

#Redis#NoSQL#缓存#键值数据库
上次更新: 2026/01/28, 14:21:05
NewSQL数据库:关系型与NoSQL的完美结合
Redis入门与实践

← NewSQL数据库:关系型与NoSQL的完美结合 Redis入门与实践→

最近更新
01
LLM
01-30
02
intro
01-30
03
intro
01-30
更多文章>
Theme by Vdoing | Copyright © 2019-2026 Jorgen | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式