Skip to content

第15章:基础实战(新手必练,逐个突破)

实战1:用户登录会话存储(String类型实战)

15.1 需求分析

实现一个用户登录会话存储系统,需要:

  • 用户登录后,将会话信息存储到Redis
  • 设置会话过期时间(如30分钟)
  • 用户退出时删除会话
  • 支持会话查询和验证

15.2 核心实现

  • String类型命令:SET EX(设置带过期时间的键值对)、GET(获取会话信息)、DEL(删除会话)
  • 过期时间设置:使用EX参数设置过期时间
  • 会话ID生成:使用UUID或随机字符串作为会话标识

15.3 实操步骤

步骤1:生成会话ID并存储会话信息

bash
# 连接Redis
redis-cli

# 生成会话ID(实际应用中使用UUID)
SET session:user:123 "{\"user_id\": 123, \"username\": \"zhangsan\", \"login_time\": \"2026-04-03 10:00:00\"}" EX 1800

# 验证会话是否设置成功
GET session:user:123

步骤2:模拟用户操作期间会话验证

bash
# 检查会话是否存在
EXISTS session:user:123

# 获取会话信息
GET session:user:123

# 查看会话剩余过期时间
TTL session:user:123

步骤3:用户退出,删除会话

bash
# 删除会话
DEL session:user:123

# 验证会话是否已删除
GET session:user:123

15.4 代码实现(Node.js示例)

javascript
const redis = require('redis');
const client = redis.createClient();
const { v4: uuidv4 } = require('uuid');

// 用户登录
function login(username, password) {
  // 验证用户凭证(实际应用中需要查询数据库)
  if (username === 'zhangsan' && password === '123456') {
    const userId = 123;
    const sessionId = uuidv4();
    const sessionData = {
      user_id: userId,
      username: username,
      login_time: new Date().toISOString()
    };
    
    // 存储会话信息,设置30分钟过期
    client.set(`session:${sessionId}`, JSON.stringify(sessionData), 'EX', 1800);
    
    return { success: true, sessionId: sessionId };
  }
  return { success: false, message: '用户名或密码错误' };
}

// 验证会话
function validateSession(sessionId) {
  return new Promise((resolve, reject) => {
    client.get(`session:${sessionId}`, (err, data) => {
      if (err) reject(err);
      if (data) {
        resolve({ valid: true, user: JSON.parse(data) });
      } else {
        resolve({ valid: false, message: '会话已过期或不存在' });
      }
    });
  });
}

// 用户退出
function logout(sessionId) {
  client.del(`session:${sessionId}`);
  return { success: true, message: '已成功退出' };
}

// 使用示例
async function testSession() {
  // 登录
  const loginResult = login('zhangsan', '123456');
  console.log('登录结果:', loginResult);
  
  if (loginResult.success) {
    const sessionId = loginResult.sessionId;
    
    // 验证会话
    const validateResult = await validateSession(sessionId);
    console.log('会话验证结果:', validateResult);
    
    // 退出
    const logoutResult = logout(sessionId);
    console.log('退出结果:', logoutResult);
    
    // 再次验证会话
    const validateAfterLogout = await validateSession(sessionId);
    console.log('退出后会话验证结果:', validateAfterLogout);
  }
}

testSession();

实战2:商品信息缓存(Hash类型实战)

15.4 需求分析

实现一个商品信息缓存系统,需要:

  • 将商品信息(ID、名称、价格、库存)缓存到Redis
  • 支持商品信息的查询
  • 支持商品信息的修改
  • 支持商品信息的删除
  • 提高商品信息的访问速度

15.5 核心实现

  • Hash类型命令:HSET(设置哈希字段)、HGETALL(获取所有字段和值)、HDEL(删除哈希字段)、HMSET(批量设置哈希字段)
  • 键命名规范:使用 product:{id} 作为哈希键
  • 数据结构:使用哈希类型存储商品的多个属性

15.6 实操步骤

步骤1:存储商品信息

bash
# 连接Redis
redis-cli

# 方法1:使用HSET逐个设置字段
HSET product:1001 id 1001
HSET product:1001 name "iPhone 15"
HSET product:1001 price 5999
HSET product:1001 stock 100

# 方法2:使用HMSET批量设置字段
HMSET product:1002 id 1002 name "MacBook Pro" price 12999 stock 50

步骤2:查询商品信息

bash
# 获取商品所有信息
HGETALL product:1001

# 获取商品特定字段
HGET product:1001 name
HGET product:1001 price

步骤3:修改商品信息

bash
# 修改商品价格
HSET product:1001 price 5499

# 修改商品库存
HSET product:1001 stock 95

# 验证修改结果
HGETALL product:1001

步骤4:删除商品信息

bash
# 删除商品的某个字段
HDEL product:1001 stock

# 验证删除结果
HGETALL product:1001

# 删除整个商品信息
DEL product:1001

# 验证商品是否已删除
HGETALL product:1001

15.7 代码实现(PHP示例)

php
<?php

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

// 存储商品信息
function saveProduct($redis, $id, $name, $price, $stock) {
    $key = "product:{$id}";
    $redis->hMSet($key, [
        'id' => $id,
        'name' => $name,
        'price' => $price,
        'stock' => $stock
    ]);
    return true;
}

// 获取商品信息
function getProduct($redis, $id) {
    $key = "product:{$id}";
    return $redis->hGetAll($key);
}

// 更新商品信息
function updateProduct($redis, $id, $data) {
    $key = "product:{$id}";
    foreach ($data as $field => $value) {
        $redis->hSet($key, $field, $value);
    }
    return true;
}

// 删除商品信息
function deleteProduct($redis, $id) {
    $key = "product:{$id}";
    return $redis->del($key);
}

// 使用示例
saveProduct($redis, 1001, "iPhone 15", 5999, 100);

echo "商品信息:\n";
print_r(getProduct($redis, 1001));

updateProduct($redis, 1001, ['price' => 5499, 'stock' => 95]);
echo "\n更新后商品信息:\n";
print_r(getProduct($redis, 1001));

deleteProduct($redis, 1001);
echo "\n删除后商品信息:\n";
print_r(getProduct($redis, 1001));

$redis->close();
?>

实战3:商品销量排行榜(Sorted Set类型实战)

15.7 需求分析

实现一个商品销量排行榜系统,需要:

  • 统计商品销量
  • 实现销量降序排名
  • 展示前10名商品
  • 支持实时更新销量

15.8 核心实现

  • Sorted Set类型命令:ZADD(添加元素及分数)、ZREVRANGE(降序获取元素)、ZINCRBY(增加元素分数)
  • 键命名规范:使用 sales:rank 作为有序集合键
  • 分数设置:使用商品销量作为分数

15.9 实操步骤

步骤1:初始化商品销量数据

bash
# 连接Redis
redis-cli

# 添加商品销量数据
ZADD sales:rank 100 1001  # 商品1001销量100
ZADD sales:rank 150 1002  # 商品1002销量150
ZADD sales:rank 80 1003   # 商品1003销量80
ZADD sales:rank 200 1004  # 商品1004销量200
ZADD sales:rank 120 1005  # 商品1005销量120

步骤2:更新商品销量

bash
# 商品1001销量增加20
ZINCRBY sales:rank 20 1001

# 商品1003销量增加30
ZINCRBY sales:rank 30 1003

步骤3:获取销量排行榜

bash
# 获取销量前3名商品(降序)
ZREVRANGE sales:rank 0 2 WITHSCORES

# 获取销量前10名商品
ZREVRANGE sales:rank 0 9 WITHSCORES

步骤4:查询特定商品的销量和排名

bash
# 获取商品1001的销量
ZSCORE sales:rank 1001

# 获取商品1001的排名(降序,从0开始)
ZREVRANK sales:rank 1001

15.10 代码实现(Python示例)

python
import redis

# 连接Redis
r = redis.Redis(host='localhost', port=6379, db=0)

# 初始化商品销量
def init_sales():
    # 清除现有排行榜
    r.delete('sales:rank')
    
    # 添加初始销量数据
    sales_data = {
        '1001': 100,
        '1002': 150,
        '1003': 80,
        '1004': 200,
        '1005': 120
    }
    
    for product_id, sales in sales_data.items():
        r.zadd('sales:rank', {product_id: sales})
    
    print("初始化销量数据完成")

# 更新商品销量
def update_sales(product_id, increment):
    r.zincrby('sales:rank', increment, product_id)
    print(f"商品{product_id}销量增加{increment}")

# 获取销量排行榜
def get_sales_rank(top_n=10):
    # 获取降序排列的前N个商品
    rank = r.zrevrange('sales:rank', 0, top_n-1, withscores=True)
    
    print(f"\n销量排行榜(前{top_n}名):")
    for i, (product_id, sales) in enumerate(rank, 1):
        print(f"第{i}名:商品{product_id},销量{int(sales)}")

# 获取商品排名和销量
def get_product_rank(product_id):
    sales = r.zscore('sales:rank', product_id)
    rank = r.zrevrank('sales:rank', product_id)
    
    if sales is not None:
        print(f"\n商品{product_id}:")
        print(f"销量:{int(sales)}")
        print(f"排名:第{rank+1}名")
    else:
        print(f"商品{product_id}不存在")

# 使用示例
if __name__ == "__main__":
    init_sales()
    get_sales_rank(5)
    
    # 更新销量
    update_sales('1001', 50)
    update_sales('1003', 100)
    
    # 查看更新后的排行榜
    get_sales_rank(5)
    
    # 查看特定商品排名
    get_product_rank('1001')
    get_product_rank('1003')

实战总结

通过以上三个基础实战案例,我们学习了:

  1. String类型:适合存储会话信息、验证码等简单数据,支持设置过期时间
  2. Hash类型:适合存储对象信息,如商品详情、用户信息等,支持单独修改字段
  3. Sorted Set类型:适合实现排行榜、排名等功能,支持根据分数排序

这些实战案例覆盖了Redis最常用的数据类型和命令,是新手入门的必备练习。在实际应用中,我们可以根据具体场景选择合适的数据类型和命令,以达到最佳的性能和效果。

© 2026 编程马·菜鸟教程 版权所有