redis一共有哪些数据类型?使用场景是什么?底层原理是什么?
·
Redis 是一个高性能的键值存储系统,支持多种数据类型。
1. Redis 数据类型及其使用场景
(1) String(字符串)
- 描述:最基本的 Redis 数据类型,用于存储字符串或数字。
- 使用场景:
- 缓存简单的键值对数据。
- 计数器(如点赞数、访问量等)。
- 存储 JSON 格式的数据。
- 底层原理:
- 使用 Redis 的 SDS(Simple Dynamic String)结构存储字符串。
- 如果存储的是整数,Redis 会优化为整数操作(如
INCR、DECR)。
(2) Hash(哈希表)
- 描述:类似于字典,存储字段和值的映射关系。
- 使用场景:
- 存储对象(如用户信息、商品详情)。
- 需要对部分字段进行更新时。
- 底层原理:
- 使用哈希表实现。
- 当字段较少时,使用压缩列表(ziplist),字段较多时切换为哈希表。
(3) List(列表)
- 描述:有序的字符串列表,支持从两端插入和弹出元素。
- 使用场景:
- 消息队列(如任务队列)。
- 最新消息列表(如最近的 10 条动态)。
- 底层原理:
- 使用双向链表或压缩列表实现。
- 小列表使用压缩列表,大列表使用链表。
(4) Set(集合)
- 描述:无序且不重复的字符串集合。
- 使用场景:
- 去重(如记录唯一用户 ID)。
- 随机抽取元素(如抽奖活动)。
- 底层原理:
- 使用哈希表实现。
- 支持高效的交集、并集和差集操作。
(5) Sorted Set(有序集合)
- 描述:每个元素关联一个分数,按分数排序。
- 使用场景:
- 排行榜(如游戏分数排名)。
- 带权重的任务队列。
- 底层原理:
- 使用跳跃表(skiplist)和字典实现。
- 跳跃表用于排序,字典用于快速查找。
(6) Bitmaps(位图)
- 描述:基于字符串实现的位操作。
- 使用场景:
- 用户签到记录。
- 统计活跃用户数。
- 底层原理:
- 使用字符串存储位数据,支持位操作命令(如
SETBIT、GETBIT)。
- 使用字符串存储位数据,支持位操作命令(如
(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 能够满足各种场景下的高性能需求。
更多推荐


所有评论(0)