Redis 是一个高性能的键值存储系统,支持多种数据类型。


1. Redis 数据类型及其使用场景

(1) String(字符串)
  • 描述:最基本的 Redis 数据类型,用于存储字符串或数字。
  • 使用场景
    • 缓存简单的键值对数据。
    • 计数器(如点赞数、访问量等)。
    • 存储 JSON 格式的数据。
  • 底层原理
    • 使用 Redis 的 SDS(Simple Dynamic String)结构存储字符串。
    • 如果存储的是整数,Redis 会优化为整数操作(如 INCRDECR)。
(2) Hash(哈希表)
  • 描述:类似于字典,存储字段和值的映射关系。
  • 使用场景
    • 存储对象(如用户信息、商品详情)。
    • 需要对部分字段进行更新时。
  • 底层原理
    • 使用哈希表实现。
    • 当字段较少时,使用压缩列表(ziplist),字段较多时切换为哈希表。
(3) List(列表)
  • 描述:有序的字符串列表,支持从两端插入和弹出元素。
  • 使用场景
    • 消息队列(如任务队列)。
    • 最新消息列表(如最近的 10 条动态)。
  • 底层原理
    • 使用双向链表或压缩列表实现。
    • 小列表使用压缩列表,大列表使用链表。
(4) Set(集合)
  • 描述:无序且不重复的字符串集合。
  • 使用场景
    • 去重(如记录唯一用户 ID)。
    • 随机抽取元素(如抽奖活动)。
  • 底层原理
    • 使用哈希表实现。
    • 支持高效的交集、并集和差集操作。
(5) Sorted Set(有序集合)
  • 描述:每个元素关联一个分数,按分数排序。
  • 使用场景
    • 排行榜(如游戏分数排名)。
    • 带权重的任务队列。
  • 底层原理
    • 使用跳跃表(skiplist)和字典实现。
    • 跳跃表用于排序,字典用于快速查找。
(6) Bitmaps(位图)
  • 描述:基于字符串实现的位操作。
  • 使用场景
    • 用户签到记录。
    • 统计活跃用户数。
  • 底层原理
    • 使用字符串存储位数据,支持位操作命令(如 SETBITGETBIT)。
(7) HyperLogLog
  • 描述:用于基数统计(估算集合中唯一元素的数量)。
  • 使用场景
    • 统计独立访客数(UV)。
  • 底层原理
    • 使用概率算法实现,占用内存小但有一定误差。
(8) Geo(地理空间)
  • 描述:存储地理位置信息,并支持距离计算。
  • 使用场景
    • 附近的人或地点查询。
  • 底层原理
    • 使用 GeoHash 编码将经纬度转换为字符串,并存储在有序集合中。

2. 完整 PHP 实例代码

以下是一个完整的 PHP 示例,演示如何使用 Redis 的各种数据类型:

<?php
// 连接到 Redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

// (1) String 类型
$redis->set('username', 'Alice');
echo "String: username = " . $redis->get('username') . "\n";

// (2) Hash 类型
$redis->hSet('user:1001', 'name', 'Bob');
$redis->hSet('user:1001', 'age', 25);
$user = $redis->hGetAll('user:1001');
echo "Hash: user info = " . json_encode($user) . "\n";

// (3) List 类型
$redis->lPush('messages', 'Hello');
$redis->lPush('messages', 'World');
$messages = $redis->lRange('messages', 0, -1);
echo "List: messages = " . json_encode($messages) . "\n";

// (4) Set 类型
$redis->sAdd('unique_users', 'Alice');
$redis->sAdd('unique_users', 'Bob');
$redis->sAdd('unique_users', 'Alice'); // 不会重复添加
$users = $redis->sMembers('unique_users');
echo "Set: unique users = " . json_encode($users) . "\n";

// (5) Sorted Set 类型
$redis->zAdd('leaderboard', 100, 'Alice');
$redis->zAdd('leaderboard', 200, 'Bob');
$redis->zAdd('leaderboard', 150, 'Charlie');
$topUsers = $redis->zRange('leaderboard', 0, -1, true); // 按分数排序
echo "Sorted Set: leaderboard = " . json_encode($topUsers) . "\n";

// (6) Bitmaps 类型
$redis->setBit('attendance:2023-10-01', 0, 1); // 第 0 天签到
$redis->setBit('attendance:2023-10-01', 1, 1); // 第 1 天签到
$day0 = $redis->getBit('attendance:2023-10-01', 0);
$day1 = $redis->getBit('attendance:2023-10-01', 1);
echo "Bitmaps: Day 0 attendance = $day0, Day 1 attendance = $day1\n";

// (7) HyperLogLog 类型
$redis->pfAdd('unique_visitors', ['Alice', 'Bob']);
$redis->pfAdd('unique_visitors', ['Charlie', 'Alice']); // Alice 已存在
$count = $redis->pfCount('unique_visitors');
echo "HyperLogLog: Unique visitors count = $count\n";

// (8) Geo 类型
$redis->geoAdd('locations', -73.9947, 40.7502, 'New York');
$redis->geoAdd('locations', -118.2437, 34.0522, 'Los Angeles');
$distance = $redis->geoDist('locations', 'New York', 'Los Angeles', 'km');
echo "Geo: Distance between New York and Los Angeles = $distance km\n";
?>

3. 输出结果示例

运行上述代码后,输出结果可能如下:

String: username = Alice
Hash: user info = {"name":"Bob","age":"25"}
List: messages = ["World","Hello"]
Set: unique users = ["Alice","Bob"]
Sorted Set: leaderboard = {"Alice":100,"Charlie":150,"Bob":200}
Bitmaps: Day 0 attendance = 1, Day 1 attendance = 1
HyperLogLog: Unique visitors count = 3
Geo: Distance between New York and Los Angeles = 3935.7535 km

4. 底层原理总结

数据类型 底层实现 特点
String SDS(简单动态字符串) 支持字符串和整数操作
Hash 压缩列表/哈希表 字段少时用压缩列表,字段多时用哈希表
List 压缩列表/双向链表 小列表用压缩列表,大列表用链表
Set 哈希表 支持高效的集合操作
Sorted Set 跳跃表 + 字典 支持按分数排序和快速查找
Bitmaps 字符串 基于位操作实现高效存储
HyperLogLog 概率算法 内存占用小,适合基数统计
Geo GeoHash + 有序集合 支持地理位置相关的操作

通过这些数据类型和底层原理,Redis 能够满足各种场景下的高性能需求。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐