Redis 初步入门教程:简单介绍和安装配置

文章目录

    • [1. 什么是redis?](#1. 什么是redis?)
    • [2. redis的一些特性](#2. redis的一些特性)
    • [3. redis典型应用场景](#3. redis典型应用场景)
        • [1. 缓存(Cache)](#1. 缓存(Cache))
        • [2. 排行榜系统](#2. 排行榜系统)
        • [3. 计数器应用](#3. 计数器应用)
        • [4. 社交网络](#4. 社交网络)
        • [5. 消息队列系统](#5. 消息队列系统)
    • [4. redis安装与配置](#4. redis安装与配置)
      • [1. 更新并安装 Redis Server](#1. 更新并安装 Redis Server)
      • [2. 检查 Redis 服务状态](#2. 检查 Redis 服务状态)
      • [3. 常用服务管理命令](#3. 常用服务管理命令)
      • [4. 配置文件](#4. 配置文件)
        • [1. 配置密码(不是很推荐)](#1. 配置密码(不是很推荐))
        • [2. 允许远程访问](#2. 允许远程访问)
      • [5. 重启 Redis 使配置生效](#5. 重启 Redis 使配置生效)
      • [6. 卸载 Redis](#6. 卸载 Redis)
    • [5. Redis-cli 客户端使用](#5. Redis-cli 客户端使用)
    • [6. 数据结构和内部编码](#6. 数据结构和内部编码)
      • [1. string 字符串](#1. string 字符串)
      • [2. hash 哈希](#2. hash 哈希)
      • [3. list 列表](#3. list 列表)
      • [4. set 集合](#4. set 集合)
      • [5. zset 有序集合](#5. zset 有序集合)
    • [7. 单线程架构](#7. 单线程架构)
      • [1. 单线程模型](#1. 单线程模型)
      • [2. 为什么单线程还能这么快](#2. 为什么单线程还能这么快)

1. 什么是redis?

Redis 是一种基于键值对(key-value)的 NoSQL 数据库 ,与很多键值对数据库不同的是,Redis 中的值可以是由 string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)、 Bitmaps(位图)、HyperLogLog、GEO(地理信息定位)等多种数据结构和算法组成,因此 Redis 可以满足很多的应用场景,而且因为 Redis 会将所有数据都存放再内存中,所以它的读写性能非常惊人。不仅如此,Redis 还可以将内存的数据利用快照和日志的形式保存到硬盘上,这样在发生类似断电或者机器故障的时候,内存中的数据不会"丢失"。

2. redis的一些特性

Redis 之所以受到如此多公司的⻘睐,必然有之过⼈之处,下⾯是关于 Redis 的 8 个重要特性:

一、极致的高性能与低延迟

这是Redis最核心的基础特性,核心优势来自底层架构设计:

  1. 基于内存的存储 :所有数据默认存储在内存中,内存读写速度远超磁盘IO,随机读写延迟可达微秒级,单机QPS(每秒查询率)轻松突破10万+。
  2. 优化的线程模型
    • 核心命令执行采用单线程模型,彻底避免了多线程上下文切换、锁竞争带来的性能开销,同时天然保证了单命令的原子性。
    • Redis 6.0+引入多线程IO,但是仅将网络请求的读写、协议解析等操作交给多线程处理,核心命令执行依然保持单线程,在高并发场景下进一步提升吞吐量,同时不破坏命令原子性。
  3. IO多路复用模型:采用epoll/kqueue等IO多路复用技术,实现非阻塞网络IO,可高效处理数万级的并发客户端连接。

二、丰富的原生数据类型支持

区别于普通键值数据库,Redis提供了丰富的内置数据类型,可直接适配多样化业务场景,无需额外编码转换:

核心数据类型 核心说明 典型适用场景
String(字符串) 最基础的二进制安全类型,单key最大支持512MB 业务缓存、计数器、分布式锁、限流、Session存储
Hash(哈希) 键值对集合,专为结构化对象设计 用户信息、商品属性、配置项等对象型数据存储
List(列表) 双向链表,支持两端高效插入/弹出,有序可重复 轻量消息队列、时间线、任务队列、排行榜
Set(集合) 无序不可重复集合,原生支持交/并/差集运算 好友关注、共同好友、数据去重、标签系统
ZSet(有序集合) 不可重复集合,每个元素关联score权重,按权重自动排序 实时排行榜、延时队列、优先级任务调度

除此之外,Redis还原生支持Bitmap(位图)、HyperLogLog(基数统计)、Geospatial(地理空间)、Stream(流)、Bitfield等进阶数据结构。

三、可靠的持久化机制

作为内存数据库,Redis提供了完善的持久化方案,解决内存数据断电丢失的问题,保障数据可靠性:

  1. RDB(快照持久化):在指定时间间隔内,对内存全量数据生成快照并写入磁盘。优点是恢复速度快,适合备份、灾难恢复;缺点是两次快照之间的故障会丢失数据。
  2. AOF(追加日志持久化):以日志形式记录每一条写命令,服务重启时重放AOF文件恢复数据。优点是数据安全性更高,可配置每秒/每次写命令刷盘,最多丢失1秒数据;缺点是文件体积大,恢复速度慢于RDB。
  3. 混合持久化:结合RDB与AOF的优势,持久化文件前半段是RDB格式的全量快照,后半段是AOF格式的增量写命令。兼顾了恢复速度与数据安全性,是当前主流推荐的持久化方案。

四、原生的高可用能力

Redis提供了完整的高可用架构方案,保障服务持续可用:

  1. 主从复制(Replication) :支持一主多从架构,主节点负责写请求,从节点同步主节点数据、承担读请求,实现读写分离,提升集群读吞吐量,同时提供多副本数据备份。支持全量同步与增量同步(PSYNC,2.8+新增),断线重连后可基于复制积压缓冲区实现增量同步,避免全量同步的性能开销。
  2. 哨兵机制:专为主从架构设计的高可用组件,核心能力包括:节点健康监控、自动故障转移(主节点故障时自动将从节点晋升为主节点)、配置中心、故障告警。解决了主从架构手动故障转移的痛点,实现服务秒级切换,大幅提升服务可用性。

五、分布式集群横向扩展能力

Redis Cluster(3.0+正式推出)是官方原生的分布式集群方案,彻底解决单机内存、并发、容量的瓶颈问题:

  • 采用哈希槽分片机制,集群预分16384个哈希槽,数据按key的哈希值分配到不同槽位,分散到多个集群节点,实现数据分布式存储。
  • 支持水平在线扩容/缩容,可动态增减节点,哈希槽可平滑迁移,业务无感知。
  • 内置副本机制与自动故障转移,每个主节点可配置多个从节点,主节点故障时自动切换从节点,保障集群高可用。
  • 采用去中心化对等架构,无中心节点,客户端可访问任意集群节点获取数据。

六、原子性与事务支持

  1. 单命令原子性:Redis所有单个命令的执行都是原子性的,得益于核心单线程执行模型,不会出现并发竞争导致的数据异常。
  2. 事务支持 :通过MULTI/EXEC/DISCARD/WATCH四个命令实现事务,可将多个命令打包成一个事务单元,按顺序原子性执行,执行过程中不会被其他客户端的命令打断。通过WATCH命令实现乐观锁,保障事务执行前后的数据一致性。 注:Redis事务为弱事务,不支持回滚,仅语法错误会导致整体事务失败,运行时错误不会回滚已执行的命令。

七、丰富的进阶功能特性

  1. 过期键与内存淘汰策略 :支持给key设置TTL过期时间,到期自动删除;当内存使用达到上限时,提供8种灵活的淘汰策略(如allkeys-lruvolatile-lfunoeviction等),适配不同业务场景。
  2. Lua脚本支持(新增):支持编写Lua脚本,将多个Redis命令打包成一个脚本原子性执行,减少网络往返开销,同时可实现复杂的业务逻辑,是分布式锁、限流等场景的核心实现方案。
  3. Pipeline管道机制:支持批量打包发送多个命令,一次性接收返回结果,大幅减少TCP网络往返的RTT开销,提升批量操作的性能。
  4. 发布订阅(Pub/Sub)模式:支持消息的发布与订阅,包括频道精准订阅、模式匹配订阅,可实现广播、消息通知、实时消息推送等场景。
  5. Stream流(新增):专为消息队列设计的数据结构,支持消息持久化、消费者组、消息确认、回溯消费,弥补了Pub/Sub、List做消息队列的缺陷,可实现轻量级的消息中间件能力。
  6. 精细化安全访问控制 :支持基础密码认证,Redis 6.0+新增ACL(访问控制列表) 功能,可创建多个用户,为不同用户分配精细化的命令执行权限、key访问权限,同时支持SSL/TLS传输加密,保障数据安全。

八、完善的生态与可扩展性

  1. 全语言客户端支持:几乎覆盖所有主流编程语言(Java、Python、Go、PHP、C/C++、Node.js等),拥有成熟稳定的官方/社区客户端SDK,接入成本极低。
  2. 模块化扩展:支持自定义模块扩展能力,官方与社区提供了大量成熟模块,如RedisJSON(JSON原生支持)、RediSearch(全文检索)、RedisTimeSeries(时序数据处理)、RedisBloom(布隆过滤器)等,大幅扩展了Redis的能力边界,形成了完整的Redis Stack生态。
  3. 跨平台兼容:支持Linux、Windows、macOS等主流操作系统,可部署在物理机、虚拟机、容器、云平台等多种环境。

3. redis典型应用场景

1. 缓存(Cache)

缓存机制几乎在所有大型网站都有使用,合理地使用缓存不仅可以加速数据的访问速度,而且能够有效地降低后端数据源的压力。Redis提供了键值过期时间设置,并且也提供了灵活控制最大内存和内存溢出后的淘汰策略。

2. 排行榜系统

排行榜系统几乎存在于所有的网站,例如按照热度排名的排行榜,按照发布时间的排行榜,按照各种复杂维度计算出的排行榜,Redis提供了列表和有序集合的结构,合理地使用这些数据结构可以很方便地构建各种排行榜系统。

3. 计数器应用

计数器在网站中的作用至关重要,例如视频网站有播放数、电商网站有浏览数,为了保证数据的实时性,每一次播放和浏览都要做加1的操作,如果并发量很大对于传统关系型数据的性能是一种挑战。Redis天然支持计数功能而且计数的性能也非常好,可以说是计数器系统的重要选择。

4. 社交网络

赞/踩、粉丝、共同好友/喜好、推送、下拉刷新等是社交网站的必备功能,由于社交网站访问量通常比较大,而且传统的关系型数据不太适合保存这种类型的数据,Redis提供的数据结构可以相对比较容易地实现这些功能。

5. 消息队列系统

消息队列系统可以说是一个大型网站的必备基础组件,因为其具有业务解耦、非实时业务削峰等特性。Redis提供了发布订阅功能和阻塞队列的功能,虽然和专业的消息队列比还不足够强大,但是对于一般的消息队列功能基本可以满足。

redis 最大的缺点即是无法存储大量数据

4. redis安装与配置

在 Ubuntu 24.04 中安装和配置 Redis 非常简单,以下是完整的步骤指南,包括安装、基础配置和安全加固。

Ubuntu 24.04 的官方软件仓库中已经包含了 Redis,直接使用 apt 安装即可(版本通常为 Redis 7.x,稳定可靠)。

1. 更新并安装 Redis Server

首先更新本地的包列表,确保安装的是最新版本:

bash 复制代码
sudo apt update

执行以下命令安装 Redis 服务端:

bash 复制代码
sudo apt install redis-server -y

2. 检查 Redis 服务状态

bash 复制代码
sudo systemctl status redis-server

如果看到 active (running) 绿色字样,说明服务已成功启动。

可以选择设置开机自启(默认已开启,可确认)

bash 复制代码
sudo systemctl enable redis-server

3. 常用服务管理命令

  • 启动服务:sudo systemctl start redis-server
  • 停止服务:sudo systemctl stop redis-server
  • 重启服务:sudo systemctl restart redis-server
  • 重载配置:sudo systemctl reload redis-server

4. 配置文件

Redis 的主配置文件位于 /etc/redis/redis.conf,所有重要配置都在此文件中修改。

注意:修改配置前建议先备份:

bash 复制代码
sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.bak

使用文本编辑器(如 nanovim)打开配置文件:

bash 复制代码
sudo nano /etc/redis/redis.conf
1. 配置密码(不是很推荐)

默认 Redis 没有密码,生产环境必须设置。找到 # requirepass foobared 这一行,去掉注释并修改密码:

conf 复制代码
requirepass your_secure_password_here

设置后,连接 Redis 需要认证:

bash 复制代码
redis-cli -a your_secure_password_here
# 或者进入后再认证:
redis-cli
auth your_secure_password_here
2. 允许远程访问

默认 Redis 仅绑定 127.0.0.1(本地访问)。如果需要从其他服务器连接,修改 bind 配置:

找到 bind 127.0.0.1 -::1 这一行,修改为:

conf 复制代码
# 允许所有 IP 访问(生产环境不建议,建议绑定具体 IP)
bind 0.0.0.0 -::1

# 或者仅允许指定 IP 访问(更安全)
# bind 127.0.0.1 192.168.1.100

同时,将 protected-mode 改为 no(否则远程连接会被拒绝):

conf 复制代码
protected-mode no

提醒 :允许远程访问时,务必配置强密码,并通过防火墙(ufw)限制仅允许信任的 IP 访问 6379 端口。

bash 复制代码
# 允许所有 IP(不推荐,仅用于测试)
sudo ufw allow 6379

# 查看防火墙状态
sudo ufw status

5. 重启 Redis 使配置生效

修改完配置后,必须重启 Redis 服务:

bash 复制代码
sudo systemctl restart redis-server

再次检查服务状态,确保重启成功:

bash 复制代码
sudo systemctl status redis-server

验证:

bash 复制代码
root@VM-0-14-ubuntu:/etc/redis# redis-cli #启动redis客户端
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> exit

6. 卸载 Redis

如果需要完全卸载 Redis:

bash 复制代码
# 停止服务
sudo systemctl stop redis-server
# 卸载软件包
sudo apt purge redis-server redis-tools -y
# 删除残留文件
sudo rm -rf /etc/redis /var/lib/redis

5. Redis-cli 客户端使用

1. 交互式方式

通过 redis-cli -h {host} -p {port} 的方式连接到 Redis 服务,后续所有的操作都是通过交互式的方式实现,不需要再重复执行 redis-cli 命令,例如:

shell 复制代码
[root@host ~]# redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set key hello
OK
127.0.0.1:6379> get key
"hello"

2. 命令方式

redis-cli -h {host} -p {port} {command} 可以直接执行命令并获取返回结果,无需进入交互终端,例如:

shell 复制代码
[root@host ~]# redis-cli -h 127.0.0.1 -p 6379 ping
PONG
[root@host ~]# redis-cli -h 127.0.0.1 -p 6379 set key hello
OK
[root@host ~]# redis-cli -h 127.0.0.1 -p 6379 get key
"hello"

图 1-3 Redis 客户端与服务端的交互过程

  1. 发送命令
  2. 执行命令
  3. 返回结果
    Redis 客户端
    网络
    Redis 服务端

基本全局命令

Redis 有 5 种数据结构,它们都是键值对的值,对于键来说有一些通用的命令:

KEYS

返回所有满足样式(pattern)的 key。支持如下通配样式:

  • h?llo 匹配 hellohallohxllo

  • h*llo 匹配 hlloheeeello

  • h[ae]llo 匹配 hellohallo,但不匹配 hillo

  • h[^e]llo 匹配 hallohbllo 等,但不匹配 hello

  • h[a-b]llo 匹配 hallohbllo

  • 语法:

shell 复制代码
KEYS pattern
  • 示例:
shell 复制代码
127.0.0.1:6379> keys a?d
1) "add"
127.0.0.1:6379> keys a*
1) "apple"
2) "any"
3) "analysis"
4) "add"
127.0.0.1:6379> keys a[^a]*
1) "apple"
2) "any"
3) "analysis"
4) "add"
127.0.0.1:6379> keys *
1) "backup1"
2) "backup3"
3) "apple"
4) "any"
5) "backup4"
6) "backup2"
7) "analysis"
8) "add"

谨慎使用keys命令,如果key太多会阻塞进程(redis为单进程),redis可能会崩溃


EXISTS

判断某个 key 是否存在。

  • 语法:
shell 复制代码
EXISTS key [key ...]
  • 时间复杂度:O(1) (keys由哈希表存储

  • 返回值:key 存在的个数。

  • 示例:

shell 复制代码
127.0.0.1:6379> exists add
(integer) 1
127.0.0.1:6379> exists asdasdasd
(integer) 0
127.0.0.1:6379> exists add apple 
(integer) 2

推荐使用exists一次查询多个key,减少网络使用开销,提升性能!


DEL

删除指定的 key。

  • 语法:
shell 复制代码
DEL key [key ...]
  • 命令有效版本:1.0.0 之后

  • 时间复杂度:O(1)

  • 返回值:删除掉的 key 的个数。

  • 示例:

shell 复制代码
redis> SET key1 "Hello"
"OK"
redis> SET key2 "World"
"OK"
redis> DEL key1 key2 key3
(integer) 2

EXPIRE

为指定的 key 添加秒级的过期时间(Time To Live TTL)

  • 语法:
shell 复制代码
EXPIRE key seconds
  • 命令有效版本:1.0.0 之后

  • 时间复杂度:O(1)

  • 返回值:1 表示设置成功,0 表示设置失败。

  • 示例:

shell 复制代码
redis> SET mykey "hello"
"OK"
redis> EXPIRE mykey 10
(integer) 1
redis> TTL mykey
(integer) 10

TTL

获取指定 key 的过期时间,秒级。

  • 语法:
shell 复制代码
TTL key
  • 命令有效版本:1.0.0 之后

  • 时间复杂度:O(1)

  • 返回值:剩余过期时间。-1 表示没有关联过期时间,-2 表示 key 不存在。

  • 示例:

shell 复制代码
redis> SET mykey "Hello"
"OK"
redis> EXPIRE mykey 10
(integer) 1
redis> TTL mykey
(integer) 10

EXPIRE 和 TTL 命令都有对应的支持毫秒为单位的版本:PEXPIREPTTL,详细用法就不再介绍了。

TYPE

返回key对应的数据类型。

  • 语法:

    TYPE key

  • 命令有效版本: 1.0.0之后

  • 时间复杂度: O(1)

  • 返回值: none, string, list, set, zset, hash and stream

  • 示例:

    127.0.0.1:6379> keys *

    1. "abcdef"
    2. "abcd"
      127.0.0.1:6379> type abcd
      string
      127.0.0.1:6379> type "abcdef"
      string

扩展内容:定时器的两种主流实现方案

一、优先级队列(最小堆)

优先级队列是定时器最经典的实现方式,采用任务到期时间作为优先级排序依据,到期时间越早的任务,优先级越高,始终位于堆顶。

  • 堆的每个节点存储定时任务的完整信息:唯一ID、绝对到期时间、回调函数、自定义参数等。

  • 最小堆的核心特性:堆顶节点永远是全局最近到期的任务 ,可直接获取,无需遍历,这样使得时间复杂度非常低(只需要考虑堆调整的时间复杂度)。
    核心操作的时间复杂度:

    操作 实现逻辑 时间复杂度
    插入任务 将任务追加到堆尾,执行「向上堆化」,调整堆结构保证最小堆特性 O(logn)
    取出到期任务 取出堆顶任务,将堆尾节点移到堆顶,执行「向下堆化」调整结构 O(logn)
    取消任务 配合哈希表(任务ID→堆下标)O(1)定位节点,修改值后堆化调整 O(logn)
二、时间轮

时间轮通过时间分片、环形结构,将所有定时操作的时间复杂度降至O(1)

  1. 一个固定长度的环形数组(时间轮盘) ,数组的每个元素称为时间槽(Slot);槽位数N、每个槽对应的时间间隔tickMs,整个轮盘的最大时间跨度为 N * tickMs

  2. 每个时间槽挂载一个双向链表,存储该时间点到期的所有定时任务;

  3. 一个当前指针currentTime,指向轮盘当前正在处理的槽位。

  4. 任务插入:计算任务到期时间与当前时间的差值,算出目标槽位与剩余圈数,将任务追加到对应槽位的链表尾部,时间复杂度O(1);

  5. 时钟推进 :每经过tickMs时间,当前指针向前移动一个槽位,遍历该槽位的链表,执行所有到期任务,其余任务的剩余圈数减1;

  6. 任务取消:通过哈希表定位任务所在的槽位与链表节点,直接从链表中删除,时间复杂度O(1)。

redis 的定时器没有采用上述任何一种实现方式,详细的实现方式将在后面介绍

6. 数据结构和内部编码

type命令实际返回的就是当前键的数据结构类型,它们分别是:string(字符串)list(列表)hash(哈希)set(集合)zset(有序集合),但这些只是Redis对外的数据结构。

Redis一个key对应value,value的类型分为:

  • 字符串:纯字符串或字节流(相当于std::string)
  • 哈希:field-value 键值对集合(相当于std::unordered_map)
  • 列表:有序的元素序列(相当于std::deque)
  • 集合:无序、不重复的元素集合(相当于std::set)
  • 有序集合:带分数的、有序不重复的元素集合(与stl的数据结构都有差别)

实际上Redis针对每种数据结构都有自己的底层内部编码实现,而且是多种实现,这样Redis会在合适的场景选择合适的内部编码(具体的实现方式可能会根据使用场景进行改变或优化,不一定完全按照规定方式实现!):

数据结构 内部编码
string raw
int
embstr
hash hashtable
ziplist
list linkedlist
ziplist
set hashtable
intset
zset skiplist
ziplist

1. string 字符串

对外都是string,底层3种结构自动切换:

  • int :存整数 (比如1009999),直接用整型数字存储;
  • embstr :存短字符串 (比如helloname),优化内存布局;
  • raw :存长字符串(比如长文章、大JSON),用普通字符串结构存储

例:存SET age 18 → Redis自动用int编码;存SET content 长文本 → 自动用raw

2. hash 哈希

对外都是hash,底层二选一:

  • ziplist(压缩列表)紧凑的连续数组结构,适用于字段少、值很小的哈希(比如存单个用户信息)
  • hashtable(哈希表) :标准字典结构,查询速度O(1),适用于字段多、值很大的哈希(比如存海量用户)

3. list 列表

  • ziplist:短列表、小数据
  • linkedlist(链表):长列表、大数据
  • 新版用quicklist(结合ziplist+linkedlist,是一个链表,每一个元素又是一个ziplist短列表 )

4. set 集合

  • intset(整数集合) :存纯整数、元素少的集合;
  • hashtable(哈希表):元素多、包含非整数;

5. zset 有序集合

  • ziplist(压缩列表):元素少、值小
  • skiplist(跳表):元素多、需要排序 , seloch排序/查询超快

可以看到每种数据结构都有至少两种以上的内部编码实现,例如list数据结构包含了linkedlist和ziplist两种内部编码。同时有些内部编码,例如ziplist,可以作为多种数据结构的内部实现,可以通过object encoding命令查询内部编码:

复制代码
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> lpush mylist a b c
(integer) 3
127.0.0.1:6379> object encoding hello
"embstr"
127.0.0.1:6379> object encoding mylist
"quicklist"

Redis这样设计有两个核心好处:

  1. 可以改进内部编码,而对外的数据结构和命令没有任何影响,这样一旦开发出更优秀的内部编码,无需改动外部数据结构和命令,例如Redis 3.2提供了quicklist,结合了ziplist和linkedlist两者的优势,为列表类型提供了一种更为优秀的内部编码实现,而对用户来说基本无感知
  2. 多种内部编码实现可以在不同场景下发挥各自的优势,例如ziplist比较节省内存,但是在列表元素比较多的情况下,性能会下降,这时候Redis会根据配置选项将列表类型的内部实现转换为linkedlist,整个过程用户同样无感知。

7. 单线程架构

1. 单线程模型

现在开启了三个redis-cli客户端同时执行命令。

客户端1设置一个字符串键值对:

复制代码
127.0.0.1:6379> set hello world

客户端2对counter做自增操作:

复制代码
127.0.0.1:6379> incr counter

客户端3对counter做自增操作:

复制代码
127.0.0.1:6379> incr counter

从客户端发送的命令会经历三个阶段:发送命令、执行命令、返回结果 ,其中核心是执行命令 阶段。所谓Redis单线程执行命令,是指:虽然多个客户端看起来同时向Redis发送命令,但所有命令都会采用线性方式执行,同一时刻绝对不会有两条命令被同时执行

宏观上,多个客户端是同时请求Redis服务的;微观上,客户端发送命令的时间有先后次序,只是顺序不确定,所有命令都会在Redis服务端排队串行执行。

2. 为什么单线程还能这么快

通常来讲,单线程处理能力要比多线程差,那为什么Redis使用单线程模型能达到每秒万级别的处理能力呢?可以将其归结为三点核心原因:

  1. 纯内存访问:Redis将所有数据放在内存中,内存的响应时长大约为100纳秒,这是Redis达到每秒万级别访问的最重要基础。
  2. 非阻塞I/O :Redis使用epoll作为I/O多路复用技术的实现,再加上Redis自身的事件处理模型,将epoll中的连接、读写、关闭都转换为事件,不在网络I/O上浪费过多的时间
  3. 单线程避免了线程 切换和竞态产生的消耗:单线程可以避免线程切换带来的系统开销,让程序执行更简单稳定;其次多线程开发模式下,线程访问共享数据会带来锁竞争,一旦处理不当会导致严重的性能问题,单线程可以完全规避这些问题,且代码更容易维护和实现。

虽然单线程给Redis带来诸多好处,但也有一个致命的限制:对单个命令的执行时长有严格要求。如果某个Redis命令执行耗时过长,会导致其他所有命令都阻塞在等待队列

相关推荐
ChatInfo2 小时前
Etsy 把 1000 个 MySQL 分片迁进 Vitess:425TB 数据背后的真正问题不是性能,而是运维规模
数据库·人工智能·mysql
SPC的存折2 小时前
6、MySQL设置TLS加密访问
linux·运维·服务器·数据库·mysql
老苏畅谈运维2 小时前
DBA分析 ORA 报错的利器,errorstack让 Oracle 错误现原形
数据库·oracle·dba
juniperhan3 小时前
Flink 系列第 3 篇:核心概念精讲|分布式缓存 + 重启策略 + 并行度 底层原理 + 代码实战 + 生产规范
大数据·分布式·缓存·flink
紫青宝剑3 小时前
向量数据库 Milvus
数据库·milvus
雪碧聊技术3 小时前
数据库系统基础知识
数据库
Elastic 中国社区官方博客3 小时前
如何使用 LogsDB 降低 Elasticsearch 日志存储成本
大数据·运维·数据库·elasticsearch·搜索引擎·全文检索·可用性测试
Dreamboat-L3 小时前
HBase远程访问配置(详细教程)
大数据·数据库·hbase
架构师老Y3 小时前
012、缓存架构设计:Redis高级应用与优化
redis·python·架构