Redis-搭建和使用

Redis 官网
Redis 中文网

简介

Redis (Remote Dictionary Server) 是一种开源的键值存储的 NoSQL 数据库, 其由 C 语言编写, 提供多种数据结构的支持, 且所有数据存储在内存中, 可以实现快速的读写访问.

相关概念

RDBMS

RDBMS 指 Relation Database Management System, 关系型数据库管理系统. 存储的数据结构化, 使用预定义的表格和模式来组织数据.

NoSQL

NoSQL 指 Not Only SQL, 泛指非关系型数据库, 指存储的信息不需要固定的格式, 数据之间没有关系.

NoSQL 的特点有:

  • 方便扩展
  • 没有固定的查询语言

其主要分为 4 大类:

  • 键值存储 (Key-Value Stores), 使用键值对存储数据, 如 Redis, Memcached
  • 文档数据库 (Document Databases), 存储和检索文档型数据, 通常用 JSON 或 XML 格式存储, 如 MongoDB
  • 列存储数据库 (Column Family Databases), 将数据组织为列进行存储, 如 Apache HBase
  • 图形数据库 (Graph Databases), 用于存储和查询图结构数据, 这里指复杂的关系网络, 如 Amazon Neptune

Redis, Redis Stack 和 Redisinsight 的区别

Redis 本身只包含数据库.

Redis Stack 包含数据库以及可以配合使用的其他组件.

RedisInsight 是 Redis 的可视化和管理工具, 其提供了一个直观的界面来监控和管理 Redis.

安装

以 Fedora 38 为例:

1
dnf install -y redis

配置

配置文件为 /etc/redis/redis.conf.

修改监听 ip

1
bind 127.0.0.1

修改监听端口

Redis 的默认端口为 6379, 可以通过:

1
port xxxx

来修改.

是否以守护进程开启

1
daemonize yes

修改日志等级以及文件

1
2
loglevel notice
logfile ""

修改默认数据库数量

1
databases 16

持久化配置

1
2
3
save 900 1
save 300 10
save 60 10000

即, 如果在 900s 内至少有 1 个 key 被修改, 则进行持久化操作.

rdb 文件名以及保存的目录

1
2
dbfilename dump.rdb
dir ./

安全设置

密码设置:

1
requirepass 123456

默认没有.

限制客户端连接数量

1
maxclients 10000

启用

1
2
3
systemctl enable --now redis
ss -ntplu | grep redis
ps -ef | grep redis

连接

1
2
3
4
5
6
7
redis-cli -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> get hello
"world"

基本知识

Redis 默认有 16 个数据库 (可以在配置文件中修改), 且默认使用的是第 0 个.

Redis 是单线程的, 其基于内存操作, CPU 不是 Redis 性能瓶颈, 而是机器的内存和网络宽带.

五种基本数据类型

String

String 是创建键值对时的默认类型. 其值可以为字符串和数字.

向 string 类型的键值追加字符串

1
2
3
4
5
6
127.0.0.1:6379> set hello world
127.0.0.1:6379> get hello
"world"
127.0.0.1:6379> APPEND hello test
127.0.0.1:6379> get hello
"worldtest"

如果当前 key 不存在, 则会新建.

查看 string 长度

1
2
3
4
5
127.0.0.1:6379> set name hello
127.0.0.1:6379> get name
"hello"
127.0.0.1:6379> STRLEN name
(integer) 5

让数字加 1 和减 1

1
2
3
4
5
6
7
8
9
10
11
12
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views
(integer) 1
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> decr views
(integer) 0
127.0.0.1:6379> get views
"0"

让数字加/减指定大小

1
2
3
4
5
6
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> INCRBY views 10
(integer) 10
127.0.0.1:6379> DECRBY views 10
(integer) 0

获取字符串切片

1
2
3
4
127.0.0.1:6379> set hello "hah, world"
OK
127.0.0.1:6379> GETRANGE name 3 5
", w"

索引从 0 开始. -1 代表字符串末尾.

替换掉字符串的部分

1
2
3
4
5
6
7
8
127.0.0.1:6379> set test abcdef
OK
127.0.0.1:6379> get test
"abcdef"
127.0.0.1:6379> SETRANGE test 2 xx
(integer) 6
127.0.0.1:6379> get test
"abxxef"

设置过期时间

1
127.0.0.1:6379> setex test 30 "Hello"

setex 是 “Set Expire” 的缩写, 这里设置的过期时间为 30s.

不存在时创建

1
2
3
4
127.0.0.1:6379> setnx test "redis"
(integer) 1
127.0.0.1:6379> setnx test "hello"
(integer) 0

setnx 是 “Set Not Exist” 的缩写, 只有在键值对不存在时才会创建. 返回值为 1 表示创建了一个字符串.

批量创建键值对

1
2
3
4
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> msetnx k1 v1 k4 v4
(integer) 0

mset 为 “Multiple Set” 的缩写, msetnx 是 “Multiple Set if Not Exists” 的缩写.

msetnx 是原子性的操作 (其中一个存在则都创建失败).

批量获取键值对

1
2
3
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> mget k1 k2 k3

层次结构键值对

1
2
3
4
5
127.0.0.1:6379> mset user:1:name hello user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "hello"
2) "2"

先获取值再设置值

1
2
3
4
5
6
127.0.0.1:6379> getset db "redis"
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db "hello"
"redis"

List

可以把 List 当作栈, 队列来使用. List 中可以有重复值.

所有和 List 相关的命令都是以 l 开头.

向 List 的头部插入值

1
2
3
4
5
6
127.0.0.1:6379> LPUSH list one
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three
(integer) 3

此时 List 的内容为:

  • 0 “three”
  • 1 “two”
  • 2 “one”

向 List 尾部添加值

1
2
3
4
5
6
127.0.0.1:6379> RPUSH list one
(integer) 1
127.0.0.1:6379> RPUSH list two
(integer) 2
127.0.0.1:6379> RPUSH list three
(integer) 3

此时 List 的内容为:

  • 0 “one”
  • 1 “two”
  • 2 “three”

从头部获取 List 中的切片值

1
2
3
4
5
6
7
8
9
127.0.0.1:6379> LPUSH list one
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three
(integer) 3
127.0.0.1:6379> LRANGE list 0 1
1) "three"
2) "two"

从头部移除 List 的元素

1
2
3
4
5
6
7
8
127.0.0.1:6379> LPUSH list one
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three
(integer) 3
127.0.0.1:6379> LPOP
"three"

从尾部移除 List 的元素

1
2
3
4
5
6
7
8
127.0.0.1:6379> LPUSH list one
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three
(integer) 3
127.0.0.1:6379> RPOP
"one"

通过下标获取 List 的某个元素值

1
2
3
4
5
6
7
8
127.0.0.1:6379> LPUSH list one
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three
(integer) 3
127.0.0.1:6379> LINDEX list 0
"three"

查看 List 长度

1
2
3
4
5
6
7
8
127.0.0.1:6379> LPUSH list one
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three
(integer) 3
127.0.0.1:6379> LLEN list
(integer) 3

移除 List 中的指定值

1
2
3
4
5
6
7
127.0.0.1:6379> LPUSH list one
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three three
(integer) 3
127.0.0.1:6379> LREM list 1 three

1 表示移除 1 个 three.

截断 List

修剪列表,使其只保留指定范围内的元素:

1
2
3
4
5
6
7
8
9
10
11
127.0.0.1:6379> LPUSH list one
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three three
(integer) 3
127.0.0.1:6379> LTRIM list 1 2
OK
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"

移除 List 的最后一个元素并向另一个 List 头部添加一个新元素

1
127.0.0.1:6379> rpoplpush list newlist

判断一个 List 是否存在

1
2
127.0.0.1:6379> EXISTS list
(integer) 0

0 表示不存在.

更新 List 中指定 index 的值

1
2
3
4
5
6
7
8
9
10
11
12
127.0.0.1:6379> LPUSH list one
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three three
(integer) 3
127.0.0.1:6379> lset list 0 "hello"
OK
127.0.0.1:6379> lrange list 0 -1
1) "hello"
2) "two"
3) "one"

向 List 某一个 key 的前/后插入指定值

1
2
3
4
5
6
7
8
9
10
11
12
13
127.0.0.1:6379> LPUSH list one
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three three
(integer) 3
127.0.0.1:6379> linsert list before "two" "newvalue"
OK
127.0.0.1:6379> lrange list 0 -1
1) "hello"
2) "newvalue"
3) "two"
4) "one"

若向后插入则用 after.

Set

Set 和 List 类似, 只不过其中的元素不能重复.

和 Set 相关的指令都以 s 开头.

向一个 Set 中添加值

1
2
127.0.0.1:6379> sadd myset "hello" "world"
(integer) 2

查看 Set 中的成员

1
2
3
127.0.0.1:6379> smembers myset
1) "hello"
2) "world"

判断一个成员是否在 Set 中

1
2
127.0.0.1:6379> sismember myset hello
(integer) 1

返回值 1 表示存在.

查看 Set 的长度

1
2
127.0.0.1:6379> scard myset
(integer) 2

移除 Set 中的指定元素

1
2
127.0.0.1:6379> srem myset hello
(integer) 1

从 Set 中随机取出指定个数的元素

1
2
127.0.0.1:6379> srandmember myset
"world"

可以随机取出多个元素如:

1
2
3
127.0.0.1:6379> srandmember myset 2
"hello"
"world"

从 Set 中随机弹出一个元素

1
2
127.0.0.1:6379> spop myset
"one"

将一个指定值移动到另一个 Set 中

1
127.0.0.1:6379> smove source_set destination_set member
  • source_set: 要移动元素的原始 Set 的键名
  • destination_set: 要将元素移动到的目标 Set 的键名
  • member: 要移动的元素的值

查看两个 Set 的差集

这里是查看 set1 中存在而 set2 中不存在的元素集合:

1
2
3
4
5
6
127.0.0.1:6379> sadd set1 aa bb cc dd
(integer) 4
127.0.0.1:6379> sadd set1 bb cc dd ee
(integer) 4
127.0.0.1:6379> sdiff set1 set2
"aa"

查看两个 Set 的交集

set1set2 中都存在的元素:

1
2
3
4
5
6
7
8
127.0.0.1:6379> sadd set1 aa bb cc dd
(integer) 4
127.0.0.1:6379> sadd set1 bb cc dd ee
(integer) 4
127.0.0.1:6379> sinter set1 set2
"bb"
"cc"
"dd"

查看两个 Set 的并集

1
2
3
4
5
6
7
8
9
10
127.0.0.1:6379> sadd set1 aa bb cc dd
(integer) 4
127.0.0.1:6379> sadd set1 bb cc dd ee
(integer) 4
127.0.0.1:6379> sunion set1 set2
"aa"
"bb"
"cc"
"dd"
"ee"

Hash

就可以理解为 Perl 中的 Hash:

1
2
3
4
my %test = (
key1 => "value1",
key2 => "value2",
);

所有与 Hash 相关的命令都是以 h 开头.

创建一个 Hash

1
2
127.0.0.1:6379> hset myhash key1 value1
(integer) 1

获取 Hash 的指定字段

1
2
127.0.0.1:6379> hget myhash key1
"value1"

给 Hash 同时设置多个元素

1
2
127.0.0.1:6379> hmset myhash key1 value1 key2 value2
OK

同时获取 Hash 的多个元素值

1
2
3
127.0.0.1:6379> hmget myhash key1 key2
1) "value1"
2) "value2"

获取全部的 Hash 值

1
2
3
4
5
127.0.0.1:6379> hgetall myhash
1) "key1"
2) "value1"
3) "key2"
4) "value2"

输出包含 key 和 value.

移除 Hash 中的指定字段

1
2
127.0.0.1:6379> hdel myhash key1
(integer) 1

获取 Hash 中键值对的个数

1
2
127.0.0.1:6379> hlen myhash
(integer) 2

获取 Hash 中全部的 keys

1
2
3
127.0.0.1:6379> hkeys myhash
1) "key1"
2) "key2"

获取 Hash 中全部的 values

1
2
3
127.0.0.1:6379> hvals myhash
1) "value1"
2) "value2"

Zset

Zset 为有序集合. 和 Set 相比, Zset 中的元素可以通过添加一个额外的标识 score 来进行分组.

所有和 Zset 相关的命令都以 z 开头.

向 Zset 中添加元素

1
2
3
4
127.0.0.1:6379> zadd myset 1 one
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 three
(integer) 2

查看 Zset 切片

1
2
3
4
127.0.0.1:6379> zrange myset 0 -1
1) "one"
2) "two"
3) "three"

对 Zset 进行升序排序

1
2
3
4
5
6
7
8
9
10
127.0.0.1:6379> zadd salary 1000 haha 
(integer) 1
127.0.0.1:6379> zadd salary 2000 lala
(integer) 1
127.0.0.1:6379> zadd salary 3000 papa
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf
1) "haha"
2) "lala"
3) "papa"

这里是从小到大排序. -inf+inf 指负无穷到正无穷.

对 Zset 进行降序排序

1
2
3
4
5
6
7
8
9
10
127.0.0.1:6379> zadd salary 1000 haha
(integer) 1
127.0.0.1:6379> zadd salary 2000 lala
(integer) 1
127.0.0.1:6379> zadd salary 3000 papa
(integer) 1
127.0.0.1:6379> zrevrange salary +inf -inf
1) "papa"
2) "lala"
3) "haha"

这里是从大到小排序.

移除 Zset 中的指定元素

1
2
127.0.0.1:6379> zrem salary haha
(integer) 1

查看 Zset 的长度

1
2
127.0.0.1:6379> zcard salary
(integer) 3

获取指定区间的元素个数

1
2
127.0.0.1:6379> zcount salary 1000 3000
(integer) 3

三种特殊数据类型

Geospatial

Geospatial 类型用于存储和处理地理空间信息. 如两地的距离, 方圆几里内的人数等.

与 Geospatial 相关的命令都以 geo 开头.

由于 Geospatial 的底层由 Zset 实现, 因此 Zset 命令可以作用于 Geospatial.

向 Geospatial 添加一个地理位置

语法为:

1
127.0.0.1:6379> geoadd key [NX|XX] [CH] longitude latitude member [longitude latitude member ...]

注意添加时需要满足一定的规则:

  • 有效的经度为 -180~180
  • 有效的纬度为 -85.05~85.05

如:

1
2
3
4
5
6
7
8
127.0.0.1:6379> GEOADD china:city 116.40 39.90 beijin
(integer) 1
127.0.0.1:6379> GEOADD china:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> GEOADD china:city 106.50 29.53 chongqin 114.05 22.52 1shengzhen
(integer) 2
127.0.0.1:6379> GEOADD china:city 120.16 30.24 hangzhou 108.96 34.26 xian
(integer) 2

获取某一个 Position 的经度和纬度

1
2
3
127.0.0.1:6379> GEOPOS china:city beijing
1) 1) "116.3999"
1) "39.90000"

获取两地之间的距离

1
127.0.0.1:6379> GEODIST key member1 member2 [M|KM|FT|MI]

以给定的经度纬度为中心, 找出指定半径内的元素

1
127.0.0.1:6379> GEORADIUS key longitude latitude radius M|KM|FT|MI [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC]

如:

1
2
3
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km
1) "chongqin"
2) "xian"

count 可以限制查询的个数.

以给定元素为中心, 找出指定半径内的元素

1
127.0.0.1:6379> GEORADIUSBYMEMBER key member radius M|KM|FT|MI [WITHDIST] [WITHCOORD] [WITHHASH] [COUNT count [ANY]] [ASC|DESC]

如:

1
2
3
127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km
1) "beijing"
2) "xian"

返回一个元素信息的 hash 表示

1
127.0.0.1:6379> GEOHASH key [member [member ...]]

删除某个地理位置

1
2
127.0.0.1:6379> zrem china:city beijing
(integer) 1

Hyperloglog

HyperLogLog 是 Redis 中一种基数估计算法的实现, 用于估计集合中不重复元素的数量. 其内存占用极小. 但可能有 0.81% 的错误率.

所有和 HyperLogLog 相关的命令都以 PF 开头.

向 HyperLogLog 中添加元素

1
127.0.0.1:6379> PFADD key [element [element ...]]

获取 HyperLogLog 的基数估计值

1
127.0.0.1:6379> PFCOUNT key [key ...]

合并两个 HyperLogLog

1
127.0.0.1:6379> PFMERGE destkey [sourcekey [sourcekey ...]]

Bitmap

Bitmap (位图) 是 Redis 中一种特殊的数据类型, 用于存储和操作位级别的数据. 它可以用于表示一系列的开关状态, 标记用户的在线状态, 记录某个事件在时间轴上的发生情况等.

其所有的操作都是通过二进制位来记录.

设置 Bitmap 中的位

1
127.0.0.1:6379> setbit key offset value

value 只有 0 和 1.

获取 Bitmap 中指定偏移量的值

1
127.0.0.1:6379> getbit key offset

统计 Bitmap 中为 1 的数量

1
127.0.0.1:6379> bitcount key [start end [BYTE|BIT]]

事务

Redis 的单条命令能保证原子性, 但事务不保证原子性.

事务实际上就是一组命令的集合. 其中所有的命令都会被序列化, 即按照顺序执行.

主要有三个操作:

  • 开启事务, multi 命令
  • 命令入队
  • 执行事务, exec 命令

也可以放弃事务, 用 discard 命令.

在编写事务时, 如果一条命令语法出错, 所有命令都不会执行.

如果在运行事务时, 一条命令出错, 其他命令仍然会执行.

开启和执行事务

1
2
3
4
5
6
7
8
9
10
11
12
13
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) "v2"
4) OK

放弃事务

1
2
3
4
5
6
7
8
9
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> discard

Redis 持久化

由于 Redis 将数据存储在内存中, 断电会丢失, 因此需要将内存中的数据保存到磁盘以保证持久化.

RDB (Redis DataBase)

RDB 是默认的持久化策略.

RDB 持久化通过将 Redis 数据库中的数据以快照的方式保存到磁盘上的二进制文件中来实现. 这个过程是通过将 Redis 数据库的状态进行序列化, 并定期将序列化的数据写入磁盘来完成的.

Redis 会单独 fork 一个子进程来进行持久化, 先将数据写入到一个临时文件中, 在持久化过程结束后, 再用这个临时文件替换上次持久化好的文件 (默认是 dump.rdb).

其触发条件有:

  • save 命令来手动触发
  • flushall 命令触发
  • shutdown 命令触发

Redis 会搜寻 dump.rdb 的目录可以通过:

1
127.0.0.1:6379> config get dir

来查看.

Redis 找到 dump.rdb 文件则会读取.

AOF (Append Only File)

AOF 会以日志的形式记录每个写操作, 恢复时, 则会将命令全部执行一遍. (只会记录写操作, 没有读操作) 其默认可以向记录文件无限追加.

AOF 的数据文件比 RDB 大, 且修复速度比 RDB 慢. 但在两种持久化同时开启时, 会优先使用 AOF, 因为其保存的数据集更完整.

AOF 默认不开启, 需要修改配置为:

1
2
3
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec

如果 appendonly.aof 文件有问题, 则会导致 redis 无法连接, 可以通过 redis-check-aof 检测和修复 aof 文件:

1
redis-check-aof --fix appendonly.aof

Redis 发布订阅

redis-server 中维护了一个字典, 字典的键就是一个个频道. 而字典的值是一个链表, 保存了所有订阅了这个 channel 的客户端. 而 SUBSCRIBE 命令则是将客户端添加到 channel 的链表中.

订阅一个频道

相当于监听这个频道发送的消息:

1
127.0.0.1:6379> SUBSCRIBE channel [chennel ...]

向一个频道发送信息

1
127.0.0.1:6379> PUBLISH channel message

取消一个频道的订阅

1
127.0.0.1:6379> UNSUBSCRIBE [channel [channel ...]]

Redis 主从复制

主从复制, 指将一台 Redis 服务器的数据, 复制到其他的 Redis 服务器, 前者称为主节点 (master/leader), 后者称为从节点 (slave/follower), 数据只能从主节点复制到从节点.

在 Redis 集群中, master 节点一般用于写, 而 slave 节点用于读.

一个 master 能有多个 slave, 而一个 slave 只能对应一个 master.

默认情况下, Redis 服务都是以 master 启动. 可以在 redis-cli 中获取与主从复制相关的信息:

1
127.0.0.1:6379> info replication

当一个 redis-server 设置为 slave 后, 其不再可写 (此时只有 master 可写), 但是会同步 master 的信息.

Slave 启动且成功连接到 master 后会发送一个 sync 同步命令, master 接到命令后, 会启动后台的存盘进程, 同时收集所有接收到的用于修改数据集的命令, 在后台进程执行完毕之后, master 将传送整个数据文件到 slave.

有几种复制方式:

  • 全量复制, slave 服务在接收到数据库文件数据后, 将其存盘并加载到内存中 (在 slave 刚连接的时候执行)
  • 增量复制, master 将新的所有收集到的修改命令依次传送给 slave (一次全量复制之后执行)

从机配置

redis-cli 中配置为:

1
127.0.0.1:6379> SLAVEOF host port|NO ONE

SLAVEOF NO ONE 表示把自己设置为 master.

或修改配置文件为:

1
replicaof <host> <port>

哨兵模式

哨兵模式 (Sentinel) 即主从切换, 当 master 宕机后, 让一台 slave 会升级为 master (通过哨兵间的投票), 接替进行写操作, 并同步给其他的 slaves.

哨兵是一个独立的进程, 其通过发送命令, 等待 Redis server 响应, 以此监控多个 Redis 实例:

为避免哨兵进程也出现故障, 一般会配置多个:

哨兵之间也会相互监控.

最基本的哨兵配置

sentinel.conf (文件名任意) 中写入:

1
sentinel monitor myredis 127.0.0.1 6379 1
  • sentinel 表明该配置是针对 Redis 哨兵模式
  • monitor 表明要监控某一个 Redis 服务器
  • myredis 为被监控的 Redis 服务器的名称, 可以自定义
  • 1 表明需要哨兵投票的数量, 这里表明只要一个哨兵投票则可认为 Redis master 失效.

然后用:

1
redis-sentinel sentinel.conf

启动一个哨兵.

此时若监控的 redis server 挂掉了, 则会从其 slave 中选举出一个作为新的 master. 如果原 server 恢复了, 则原 server 会降级为 slave.

全部配置

1
2
3
4
5
6
7
8
9
port 26379
dir /tmp
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster
sentinel failover-timeout mymaster 180000
sentinel notification-script mymaster /var/redis/notify.sh
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

Redis 缓存穿透和雪崩

缓存穿透

当用户查询数据时, redis 中没有, 即缓存未命中, 于是向持久化数据库查询, 此时则出现了缓存穿透.

常见的解决方法有:

  • 布隆过滤器
  • 缓存空对象

缓存击穿

指一个 key 被大量请求, 而在这个 key 失效时, 大量的并发请求直接向数据库请求, 即缓存击穿.

常见解决方法:

  • 设置 key 不过期
  • 加互斥锁

缓存雪崩

指所有 redis 服务宕机.

基本使用

官网命令查看

查看所有键值

1
127.0.0.1:6379> keys *

关断 redis

1
2
127.0.0.1:6379> shutdown
not connected>

退出 redis

1
127.0.0.1:6379> exit

Redis 压力测试

使用 redis-benchmark 这个自带的性能测试工具.

常用参数:

  • -h, “hostname”, 指定主机名, 默认为 127.0.0.1
  • -p, “port”, 指定端口, 默认为 6379
  • -s, “socket”, 指定连接的 socket
  • -c, “connections”, 指定并发连接数, 默认为 50
  • -n, “number”, 指定请求数, 默认为 10000

如:

1
redis-benchmark -c 100 -n 100000

输出如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
98.677% <= 1.503 milliseconds (cumulative count 98677)
98.755% <= 1.607 milliseconds (cumulative count 98755)
98.802% <= 1.703 milliseconds (cumulative count 98802)
98.816% <= 1.807 milliseconds (cumulative count 98816)
98.828% <= 1.903 milliseconds (cumulative count 98828)
98.840% <= 2.007 milliseconds (cumulative count 98840)
98.937% <= 2.103 milliseconds (cumulative count 98937)
99.994% <= 3.103 milliseconds (cumulative count 99994)
100.000% <= 4.103 milliseconds (cumulative count 100000)

Summary:
throughput summary: 99601.60 requests per second
latency summary (msec):
avg min p50 p95 p99 max
0.559 0.200 0.479 0.927 2.119 3.263

latency summary 之下的都是每个请求的延时统计, 单位是 ms:

  • avg, 指平均延时
  • min, 指最小延时
  • p50, 指 50% 的请求在这个延时之下
  • p95, 指 95% 的请求在这个延时之下
  • p59, 指 99% 的请求在这个延时之下
  • min, 指最大延时

切换数据库

1
2
127.0.0.1:6379> select 3
OK

即切换到 3 号数据库.

查看当前数据库大小

1
2
127.0.0.1:6379> DBSIZE
(integer) 0

清除当前数据库

1
127.0.0.1:6379> flushdb

清除全部数据库

1
127.0.0.1:6379> flushall

判断某个键是否存在

1
127.0.0.1:6379> EXISTS name

存在则返回非 0 值.

移除某一个键值

1
127.0.0.1:6379> move name 1

这里的 name 是键名, 1 指数据库号.

设置键值对的过期时间以及查看

1
2
3
127.0.0.1:6379> EXPIRE name 10
127.0.0.1:6379> ttl name
(integer 10)

查看一个键值对类型

1
127.0.0.1:6379> type name

清屏

1
127.0.0.1:6379> clear

设置配置以及获取配置

1
2
3
127.0.0.1:6379> config set requirepass "123456"
127.0.0.1:6379> auth 123456
127.0.0.1:6379> config get requirepass

Redis-搭建和使用
http://example.com/2024/03/14/Redis-搭建和使用/
作者
Jie
发布于
2024年3月14日
许可协议