Redis的安装及通用命令

发布于:2025-04-07 ⋅ 阅读:(27) ⋅ 点赞:(0)

二. Redis 的安装及通用命令

1. Ubuntu 安装 Redis

(1) 切换到 root 用户:

su root

(2) 搜索 Redis 软件包

apt search redis

(3) 安装 Redis

apt install redis

(4) 查看 Redis

netstat -anp | grep redis

(5) 切换到 Redis 目录下

cd /etc/redis/

(6) 修改 Redis 配置文件:

vim redis.conf

(7) 重启 Redis 服务器:

service redis-server restart

(8) 查看 Redis 服务器状态:

service redis-server status

(9) 使用 Redis 客户端 (自动连到 Redis 服务器):

redis-cli

(10) 验证是否服务器正常工作:

ping

如果返回 pong, 则表明服务器正常工作.

[!NOTE]

  • [补充知识]
  • 退出 Redis 客户端: Ctrl + D
  • Redis 默认端口: 6379
  • Redis 的配置文件: redis.conf (里面包含了 Redis 的相关配置内容)
  • vim 模式下:
i   #修改
:w  #保存当前文件
:q  #退出vim
:wq #保存并退出

2. Redis 客户端

Redis 也是一个 客户端-服务器结构 的程序.

Redis 的客户端和服务器可以在同一主机上, 也可以在不同主机上.

Redis 的客户端可以有一个, 也可以有多个:

image-20250226180759700

Redis 命令行客户端

本机客户端:

redis-cli

其他主机的客户端:

redis-cli -h 127.0.0.2 -p 6379
# -h:其他主机的ip ; -p:其他主机的端口号

!! 一定要学会使用官方文档 !!

3. 通用命令

[!CAUTION]

注意: Redis 在命令方面不区分大小写, 但是在 key-value 方面 严格区分大小写.

必须要先进入 redis-cli 客户端程序, 才能使用 Redis 命令

Redis 中的命令不区分大小写.

Redis 支持很多种数据结构. 整体上来说, Redis 是键值对结构: key 固定就是字符串类型, 但value 会有多种数据类型 (字符串, 哈希表, 列表, 集合, 有序集合 …)

操作不同的数据结构会有不同的命令~

3.1 get 和 set
(1) get

根据 key 取到相应的 value 值.

get key1
# key1 是某个键值对的键.

[!NOTE]

get 一个不存在的 key, 会得到 (nil) --> nil 和 null 的意思是一样的.

(2) set

把 key 和 value 存储进 Redis.

set key value
# 其中, key和value都是字符串
# 使用时,不需要加""
3.2 Redis 全局命令

全局命令,就是能够搭配任意一个数据结构来使用的命令

(1) keys

返回所有满足样式 (pattern) 的 key.

  • pattern 就是包含特殊符号的字符串, 作用是描述目标字符串长什么样.

pattern 样式:

① ?匹配 1个 任意字符.

eg: h?llo 匹配 hello, hallo, hxllo …

* 匹配 0个到多个 任意字符.

eg: hllo 匹配 hllo 和 heeeeello …*

③ [abcde] 匹配固定选项, 只能匹配 a, b, c, d, e ; 别的不行.

eg: h [ae] llo 只能匹配 hello 和 hallo.

[^e] 排除e, 只有e匹配不了, 其他的都能匹配.

eg: h [^e] llo 不能匹配 hello, 但可以匹配 hallo, hbllo …

⑤ [a - b] 匹配 a - b 这个范围内的字符, 包括两侧边界.

eg: h [a-b] llo 匹配 hallo 和 hbllo.

[!WARNING]

注意: keys 命令的时间复杂度是 O(n) (因为要遍历所有的 key).

所以生产环境中, 一般会禁止使用 keys 命令. 尤其是 keys * (查询 Redis 中所有的 key).

如果 keys 使用不当, 可能会导致 Redis 阻塞.

[!NOTE]

未来在工作中会涉及到的几个环境:

(1) 办公环境: 入职公司之后, 公司给发个笔记本电脑 (一般 8C16G512G, (配置较低) )

(2) 开发环境: 有时就是公司发的电脑, 有时是要用单独的服务器.

(3) 线上环境 (生产环境): 用户能够直接访问到的环境 (一旦生产环境出现问题, 一定会对用户的使用产生影响).

(2) exists

用于判断某个或某些 key 是否存在, 返回 key 存在的个数.

eg:

exists key1;       #判断key1是否存在
exists key2 key3;  #判断key2和key3是否存在

时间复杂度: O(1) (因为键值对是用哈希表存储的).

Redis 的很多命令都是支持一次完成多个操作的. 因为每次命令都要从客户端经过网络发往服务器, 所以将多次命令 (也就是网络请求和响应) 合并成一次能够提高性能. (网络开销小了)

(3) del

用于删除指定的 key, 一次可以删除一个或者多个, 返回删掉的 key 的个数.

eg:

del key1;       #删除key1
del key2 key3;  #删除key2和key3

时间复杂度: O(1) (因为键值对是用哈希表存储的).

(3) expire

给指定的 key 设置过期时间 (指定key 的存活时间超过这个值, 就会被自动删除), 返回值是1或0 (1表示成功, 0表示失败).

时间单位是 秒(s)

注: 要设置过期时间的 key 必须已经存在.

时间复杂度: O(1) (因为键值对是用哈希表存储的).

典型应用场景: 基于 Redis 实现分布式锁 (其实就是写了一个特殊的 key-value)

[补充]: pexpire --> 也是用于设置 key 的过期时间, 但是单位是毫秒.

eg:

expire hello 3     #给hello设置过期时间为3s
pexpire hello1 50  #给hello1设置过期时间为50ms
(4) ttl

即: “time - to - live”

查看当前 key 的过期时间还剩多少, 返回值: 正常情况 --> 还剩的过期时间 ; 异常情况 --> -1表示没有关联过期时间, -2表示key不存在.

时间单位是 秒(s)

时间复杂度: O(1) (因为键值对是用哈希表存储的).

eg:

ttl hello  #查看hello的过期时间还剩多少(秒)
(5) type

返回当前 key 对应的 value 的数据类型.

时间复杂度: O(1) (因为键值对是用哈希表存储的).

eg:

type key1  #返回key1对应value 的数据类型
[经典面试题: Redis 中 key 的过期策略是怎么实现的?]

一个 Redis 中可能同时存在很多很多 key. 这些 key 中可能有很大一部分都有过期时间. 此时, Redis 服务器如何知道哪些key已经过期要被删除, 哪些key还没过期?

直接遍历所有的 key? --> 显然是行不通的. 因为这样做效率非常低, 要消耗很多网络资源, 很可能会导致 Redis 阻塞.

Redis 的整体策略是: 定期删除 + 惰性删除

(1) 定期删除: 每次抽取一部分, 进行验证过期时间. (为什么只抽一部分? --> 要保证这个抽取检查的过程足够快!! 否则可能阻塞)

[!NOTE]

为啥这里对于定期删除的时间, 有明确的要求呢? --> 因为redis是单线程的程序, 如果扫描过期 key 消耗的时间太多了, 就可能导致正常处理请求命令就被阻塞住 (产生类似于执行 keys * 这样的效果).

(2) 惰性删除: 假设某个key已经到过期时间了, 但是暂时还没删它, key 仍然存在. 紧接着, 后面的一次访问, 正好用到了这个key, 此时就会触发 Redis 服务器删除 key 的操作, 同时再返回一个nil.

[经典面试题: 定时器的实现]

定时器: 在某个时间到达之后, 执行指定的任务.

(1) 基于 优先级队列/堆 实现

正常的队列是先进先出, 优先级队列则是按照指定的优先级出队 (这里的优先级是自定义的. 在 Redis 过期 key 的场景中, 过期时间越早, 就是优先级越高).

现在假定有很多 key 设置了过期时间. 就可以把这些 key 加入到一个优先级队列中, 指定优先级规则是过期时间早的, 先出队. 那么, 队首元素 就是最早的要过期的任务!!

此时定时器中只需要分配一个线程, 让这个线程去检查队首元素, 看它是否过期即可. 如果队首元素还没过期, 后续元素一定没过期.

[!NOTE]

注意: 在扫描线程检查队首元素过期时间的时候, 也不能检查的太频繁 --> 太频繁的话可能会出现忙等的问题. 此时做法就是可以根据当前时刻和队首元素的过期时间, 设置一个等待时间. 当时间差不多到了, 系统再去唤醒醒这个线程.

万一在线程休眠的时候来了一个新任务咋办? --> 在添加新任务的时候唤醒一下线程, 看看是否有要执行的任务.

(2) 基于 时间轮 实现

把时间划分成很多小段 (划分粒度看具体需求)

image-20250227133524339

每个小段上都挂着一个链表, 链表的每个节点都代表一个要执行的任务.

假设需要添加一个 key, 这个 key 在 300ms 之后过期. 此时这个指针, 就会每隔固定的间隔 (这里是 100ms) 每次走到一个格子, 就会把这个格子上链表的任务尝试执行一下: 如果时间没到, 就跳过; 如果时间到了, 就执行.

[!NOTE]

对于时间轮来说,每个格子是多少时间,一共多少个格子,都是需要根据实际场景,灵活调配的~~


网站公告

今日签到

点亮在社区的每一天
去签到