Redis是什么?
Redis 是Remote Dictionary Server(Redis) 的缩写,是一个使用 C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型的Key-Value数据库,并提供多种语言的API。
它是一种 NoSQL(not-only sql,泛指非关系型数据库)的数据库,可以用作数据库、缓存、消息中间件、分布式锁等。
Redis 的特点和功能
- 性能优秀,数据在内存中,读写速度非常快,支持并发 10W QPS(每秒查询量)。
- 单进程单线程,是线程安全的,采用 IO 多路复用机制。
- 丰富的数据类型,支持字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。
- 支持数据持久化。
- 可以将内存中数据保存在磁盘中,重启时加载。
- 主从复制,哨兵,高可用。
- 可以用作分布式锁。
- 可以作为消息中间件使用,支持发布订阅
Redis工作模式
Redis 基于 客户端-服务器模型:
客户端发送请求(如 GET、SET)
→ Redis 处理请求(在内存中)
→ Redis 立即返回响应(低延迟)
与MySQL的区别
Redis | MySQL | |
数据类型 | 支持字符串、哈希、列表、集合、有序集合等丰富数据类型 | 主要有整型、浮点型、字符型、日期时间型等 |
存储方式 | 主要是内存(读写速度快,适合缓存) | 磁盘(速度相对较慢,适合存储) |
使用场景 | 缓存、排行榜、消息队列 | 持久化存储、复杂查询 |
支持事务 | 基础事务支持 | 完整事务机制(ACID) |
数据持久化 | 提供RDB和AOF等,但并非实时持久化 | 实时持久化 |
安装编译和启动
git clone https://gitee.com/mirrors/redis.git -b 6.2
cd redis
make
make test
make install
# 默认安装在 /usr/local/bin
# redis-server 是服务端程序
# redis-cli 是客户端程序
mkdir redis-data
# 把redis文件夹下 redis.conf 拷贝到 redis-data
# 修改 redis.conf
# requirepass 修改密码 123456
# daemonize yes
cd redis-data
redis-server redis.conf
# 通过 redis-cli 访问 redis-server
redis-cli -h 127.0.0.1 -a 123456
redis的value类型编码
Redis 会根据 数据的类型 + 内容大小 + 特性 来动态的选择最优的编码方式,即省内存又加快速度。
string类型
编码方式 | 长度规定 |
int | 字符串长度小于等于 20 且能转成整数 |
embstr | 字符串长度小于等于 44 |
raw | 字符串长度大于 44 |
基础命令
命令 | 功能说明 |
SET key value | 设置键的值 |
GET key | 获取键的值 |
SETEX key seconds value | 设置键并指定过期时间 |
INCR key/ DECR key | 数值型累加 / 累减 |
INCRBY key n/ DECRBY key n | 按指定数值增减 |
APPEND key value | 追加内容到原字符串 |
STRLEN key | 获取字符串长度 |
GETRANGE key start end | 获取指定范围的子串 |
SETRANGE key offset value | 替换子串 |
应用
1.对象存储
SET role:10001 '{["name"]:"kk",["sex"]:"male",["age"]:30}'
SET role:10002 '{["name"]:"mm",["sex"]:"male",["age"]:30}'
# 极少修改,对象属性字段很少改变的时候
GET role:10001
2.累加器
#统计阅读数 累计加1
incr reads
# 累计加100
incrby reads 100
3.分布式锁
# 加锁 加锁 和 解析 redis 实现是 非公平锁 ectd zk 用来实现公平锁
# 阻塞等待 阻塞连接的方式
# 介绍简单的原理: 事务
setnx lock 1 # 不存在才能设置 定义加锁行为 占用锁
setnx lock uuid # expire 30 过期
set lock uuid nx ex 30
# 释放锁
del lock
if (get(lock) == uuid)
del(lock);
4.位运算
# 猜测一下 string 是用的 int 类型 还是 string 类型
# 月签到功能 10001 用户id 202106 2021年6月份的签到 6月份的第1天
setbit sign:10001:202106 1 1
# 计算 2021年6月份 的签到情况
bitcount sign:10001:202106
# 获取 2021年6月份 第二天的签到情况 1 已签到 0 没有签到
getbit sign:10001:202106 2
list类型
双向链表实现,列表首尾操作(删除和增加)时间复杂度O(1);查找中间元素时间复杂度为 O(n);
列表中数据是否压缩的依据:
- 元素长度小于 48,不压缩;
- 元素压缩前后长度差不超过 8,不压缩;
基础命令
命令 | 功能说明 |
LPUSH key value | 从左侧插入 |
RPUSH key value | 从右侧插入 |
LPOP key | 弹出左边第一个元素 |
RPOP key | 弹出右边第一个元素 |
LRANGE key start stop | 获取指定范围内的元素 |
LLEN key | 获取列表长度 |
LREM key count value | 删除指定值的元素(count 为次数) |
LTRIM key start stop | 截取指定范围,保留该范围 |
LSET key index value | 设置索引位置的值 |
LINDEX key index | 获取指定索引的元素 |
BLPOP key [key2...] timeout | 阻塞式左弹出 |
BRPOP key [key2...] timeout | 阻塞式右弹出 |
应用
1.栈(先进后出 FILO)
LPUSH + LPOP
# 或者
RPUSH + LPOP
2.队列(先进先出 FIFO)
LPUSH + RPOP
# 或者
RPUSH + LPOP
3.阻塞队列(blocking queue)
LPUSH + BRPOP
# 或者
RPUSH + BLPOP
4.异步消息队列
#结合生产/消费模型,通过 List 实现轻量级消息队列,支持异步处理和消费速度差异
# 生产者写入日志消息
RPUSH logs:system "log1"
RPUSH logs:system "log2"
# 消费者阻塞式读取
BLPOP logs:system 0
5.获取固定窗口记录
#每次登录都插入新记录,只保留前 N 条,模拟滑动窗口效果
LPUSH login:user:1001 "2025-04-15T10:00"
LTRIM login:user:1001 0 4 # 保留最近5条
hash类型
散列表,在很多高级语言当中包含这种数据结构;c++ unordered_map 通过 key 快速索引 value;
基础命令
命令 | 功能说明 |
HSET key field value | 设置哈希表字段的值 |
HGET key fileld | 获取哈希表字段的值 |
HDEL key field | 删除一个或多个字段 |
HEXISTS key field | 判断哈希表中所有字段和值 |
HGETALL key | 获取哈希表中所有字段和值 |
HKEYS key | 获取所有字段名 |
HVALS key | 获取所有字段值 |
HMSET key field value1 field value2 | 批量设置字段值 |
HMGET key field1 field2 ... | 批量获取字段值 |
HLEN key | 获取字段数量 |
HINCRBY key field increment | 整数值自增 |
HINCRBYFLOAT key field increment | 浮点数值自增 |
存储结构
节点数量大于 512(hash-max-ziplist-entries) 或所有字符串长度大于 64(hash-max-ziplist value),则使用 dict 实现;
节点数量小于等于 512 且有一个字符串长度小于 64,则使用 ziplist 实现;
应用
1.存储对象
#一个 key 代表一个对象,多个 field 对应字段名,模拟关系型数据库中一行记录
HSET user:1001 name "Alice"
HSET user:1001 age "24"
HSET user:1001 email "alice@example.com"
HGETALL user:1001
set类型
集合;用来存储唯一性字段,不要求有序
基础命令
命令 | 功能说明 |
SADD key member [member ...] | 添加一个或多个元素到集合中 |
SREM key member [member ...] | 移除一个或多个元素 |
SISMEMBER key member | 判断元素是否存在 |
SCARD key | 获取集合元素数量 |
SMEMBERS key | 返回集合中所有元素 |
SRANDMEMBER key [count] | 随机返回一个或多个元素 |
SPOP key [count] | 随即弹出元素 |
SMOVE source destination member | 将元素从一个集合移动到另一个集合 |
SDIFF key1 key2 | 返回 key1 有但 key2 没有的元素 |
SINTER key1 key2 | 返回 key1 和 key2 的交集 |
SUNION key1 key2 | 返回两个集合的并集 |
存储结构
- 元素都为整数且节点数量小于等于 512(set-max-intset-entries),则使用整数数组存储;
- 元素当中有一个不是整数或者节点数量大于 512,则使用字典存储;
应用
1.抽奖
# 添加抽奖用户
sadd Award:1 10001 10002 10003 10004 10005 10006
sadd Award:1 10009
# 查看所有抽奖用户
smembers Award:1
# 抽取多名幸运用户
srandmember Award:1 10
2.共同关注
sadd follow:A mark king darren mole vico
sadd follow:C mark king darren
sinter follow:A follow:C
3.推荐好友
sadd follow:A mark king darren mole vico
sadd follow:C mark king darren
# C可能认识的人:
sdiff follow:A follow:C
zset类型
有序集合;用来实现排行榜;它是一个有序唯一;
基础命令
命令 | 功能说明 |
ZADD key [NX|XX] [CH] [INCR] score member [score member ...] | 添加到键为key有序集合(sorted set)里面 |
ZREM key member [member ...] | 从键为key有序集合中删除 member 的键值对 |
ZSCORE key member | 返回有序集key中,成员member的score值 |
ZINCRBY key increment member | 为有序集key的成员member的score值加上增量increment |
ZCARD key | 返回key的有序集元素个数 |
ZRANK key member | 返回有序集key中成员member的排名 |
ZRANGE key start stop [WITHSCORES] | 返回存储在有序集合key中的指定范围的元素 |
ZREVRANGE key start stop [WITHSCORES] | 返回有序集key中,指定区间内的成员(逆序) |
存储结构
节点数量大于 128 或者有一个字符串长度大于 64,则使用跳表(skiplist);
节点数量小于等于 128(zset-max-ziplist-entries)且所有字符串长度小于等于 64(zset-max ziplist-value),则使用 ziplist 存储;
- 数据少的时候,节省空间; $O(n)$
- 数量多的时候,访问性能;$O(1)$ or $O(log_{2}{n})$
应用
1.百度热榜
# 点击新闻:
zincrby hot:20230612 1 10001
zincrby hot:20230612 1 10002
zincrby hot:20230612 1 10003
zincrby hot:20230612 1 10004
zincrby hot:20230612 1 10005
zincrby hot:20230612 1 10006
zincrby hot:20230612 1 10007
zincrby hot:20230612 1 10008
zincrby hot:20230612 1 10009
zincrby hot:20230612 1 10010
# 获取排行榜:
zrevrange hot:20230612 0 9 withscores