Redis入门
Redis 安装
brew install redis
启动 redis server
redis-server
启动 redis 命令行连接
redis-cli
# 退出
quit/exit
redis-insight
redis-insight 下载链接 macos arm64
redis 基本类型
redis 字符串
redis 中的字符串区分大小写
SET key calue
GET key
DEL key
EXISTS key
keys * # 显示键, 以pattern查找,例如 *表示所有, *me表示me结尾的键
flushall #清空所有键, 成功返回 "OK"
SETNX key value 不存在 key 时设置 key 如果存在 key 不做任何操作
127.0.0.1:6379> SETNX k3 雷神
1
127.0.0.1:6379> SETNX k3 雷神
0 ##已存在,返回0
redis 中的内容以二进制存储,所以默认不支持中文
如果希望支持中文,启动时设置参数 --raw 以原始数据格式存储
redis-cli --raw
127.0.0.1:6379> set k1 大神
OK
127.0.0.1:6379> get k1
大神
设置过期时间
查看过期时间 TTL
TTL key
127.0.0.1:6379> TTL k1
-2 ## -2 表示过期
设置过期时间
EXPIRE key time
127.0.0.1:6379> EXPIRE k1 10 # 单位是second秒
1
设置一个具有过期时间的键值对
SETEX key seconds value
127.0.0.1:6379> SETEX k2 50 小神
OK
127.0.0.1:6379> ttl k2
41
redis 列表
LPUSH RPUSH 添加到头部和尾部
LPUSH listname element
在列表的首部添加元素
> LPUSH list1 a b c d e f g
(integer) 7
> LRANGE list1 0 -1
1) "g"
2) "f"
3) "e"
4) "d"
5) "c"
6) "b"
7) "a"
RPUSH listname element
在列表的尾部添加元素
> RPUSH list2 a b c d e f g
(integer) 7
> LRANGE list2 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
6) "f"
7) "g"
LPOP RPOP 从列表的首尾删除元素
LPOP listname count
> LPOP list2 3
1) "a"
2) "b"
3) "c"
RPOP listname count
> RPOP list2 3
1) "g"
2) "f"
3) "e"
LTRIM 修剪列表, 只保留参数范围内的元素
LTRIM key start stop start 与 stop 都是闭区间
> LRANGE list1 0 -1
1) "g"
2) "f"
3) "e"
4) "d"
5) "c"
6) "b"
7) "a"
> LTRIM list1 2 5
"OK"
> LRANGE list1 0 -1
1) "e"
2) "d"
3) "c"
4) "b"
redis 集合 SET
无序集合, 元素不能重复
SEt 相关的命令都是 S 开头
添加元素
SADD key member , 如果存在返回 0
查看所有元素
SMEMBERS key
判断是否存在元素
SISMEMBER key member
删除元素
SREM key member,返回 1 表示成功
> SADD set1 redis mysql java c++
(integer) 4
> SMEMBERS set1
1) "redis"
2) "mysql"
3) "java"
4) "c++"
> SADD set1 redis
(integer) 0
> SISMEMBER set1 redis
(integer) 1
> SISMEMBER set1 python
(integer) 0
> SREM set1 redis
(integer) 1
集合操作
TODO:
SINTER SUNION SDIFF
Sorted SET 有序集合 / ZSET
添加元素
ZADD key score member
显示元素
ZRANGE key start stop
显示元素和分数
ZRANGE key start stop WITHSCORES
> ZADD zset1 100 english 120 math 50 chemis 70 history
(integer) 4
> ZRANGE zset1 0 -1
1) "chemis"
2) "history"
3) "english"
4) "math"
> ZRANGE zset1 0 -1 WITHSCORES
1) "chemis"
2) "50"
3) "history"
4) "70"
5) "english"
6) "100"
7) "math"
8) "120"
查找某个元素的分数
ZSCORE key member
> zscore zset1 math
"120"
查看从小到大的排名:
ZRANK key number
> ZRANK zset1 math
(integer) 3
> zrank zset1 math withscore
1) "3"
2) "120"
从大到小排名:
> ZREVRANK zset1 math
(integer) 0
HASH 键值对集合
设置键值对
HSET key field value
获取键值对
HGET key field
获取全部键值对
HGETALL key
删除键值对
HDEL key field
获取所有 key
HKEYS key
获取所有键值对数量
HLEN key
> HSET person name yue
(integer) 1
> HSET person age 24
(integer) 1
> HGET person name
"yue"
> HGET person age
"24"
> HGETALL person
1) "name"
2) "yue"
3) "age"
4) "24"
> HDEL person age
(integer) 1
发布订阅功能
消息无法持久化, 无法记录历史消息
PUBLISH
创建一个发布频道
PUBLISH channel message
127.0.0.1:6379> publish losto redis
1
SUBSCRIBE
订阅一个频道
SUBSCRIBE channel
SUBSCRIBE losto
subscribe
losto
1
message
losto
redis
STREAMS 消息队列
轻量级的消息队列
创建消息
添加消息
XADD key id field value 消息的 id 格式默认为Timestamp-num,可以手动指定num-num,但必须要保证自增
查看长度
XLEN key
查看所有元素
XRANGED key - +
删除元素
XDEL key id
使用 trim 删除所有消息
XTRIM key MAXLEN 0
> XADD losto * course redis
"1725503802356-0"
> XLEN losto
(integer) 4
> XRANGE losto - +
1) 1) "1725503802356-0"
2) 1) "course"
2) "redis"
2) 1) "1725503807889-0"
2) 1) "course"
2) "git"
3) 1) "1725503810585-0"
2) 1) "course"
2) "c"
4) 1) "1725503947329-0"
2) 1) "math"
2) "100"
> XDEL losto 1725503802356-0
(integer) 1
> XTRIM losto MAXLEN 0
(integer) 4
消费消息
XREAD [COUNT count] [BLOCK milliseconds] STREAMS key index
count 读取数量
block 规定如果没有消息那么阻塞的时间
index 从 0 开始
> XREAD COUNT 3 BLOCK 1000 STREAMS losto 0
1) 1) "losto"
2) 1) 1) "1725504525977-0"
2) 1) "math"
2) "100"
2) 1) "1725504536271-0"
2) 1) "eng"
2) "99"
3) 1) "1725504541915-0"
2) 1) "che"
2) "99"
使用$来获取最新的消息
-
消费者
> XREAD COUNT 3 BLOCK 100000 STREAMS losto $ 1) 1) "losto" 2) 1) 1) "1725505331545-0" 2) 1) "name" 2) "liu" -
生产者
XADD losto * name liu
创建消费者组
XGROUP CREATE key group id
> XGROUP CREATE losto group1 0
"OK"
查看消费者组的信息
> XINFO GROUPS losto
1) 1) "name"
2) "group1"
3) "consumers"
4) "0"
5) "pending"
6) "0"
7) "last-delivered-id"
8) "0-0"
9) "entries-read"
10) "null"
11) "lag"
12) "9"
创建消费者
XGROUP CREATECONSUMER key group consumer
> XGROUP CREATECONSUMER losto group1 consumer3
(integer) 1
使用消费者组读取消息, 参数>表示未被组内消费的起始消息
> XREADGROUP GROUP group1 consumer1 COUNT 2 BLOCK 3000 STREAMS losto >
1) 1) "losto"
2) 1) 1) "1725504525977-0"
2) 1) "math"
2) "100"
2) 1) "1725504536271-0"
2) 1) "eng"
2) "99"
Geospatial
v3.2
添加地理位置
GEOADD key longitude latitude member
> GEOADD city 116 39 beijing
(integer) 1
添加后获取地理位置
GEOPOS key member
GEOPOS city beijing
1) 1) "116.00000113248825073"
2) "38.99999918434559731"
计算地理位置距离
GEODIST key member member
> GEODIST city beijing shanghai KM
"999.2077"
地理位置搜索
GEOSEARCH key FROMMEMBER member BYRADIUS 1000 KM
BYRADIUS 使用圆形范围
BYBOX 使用矩形范围
> GEOSEARCH city FROMMEMBER shanghai BYRADIUS 1000 KM
1) "shanghai"
2) "beijing"
HyperLogLog
集合中的基数: 统计集合中唯一值的数量(做 distinct 处理后的数量)
一般用来处理网站的 UV(Unique Visitors) 浏览者
创建一个 HLL
PFADD key element ...
获得基数
PFCOUNT key
合并
PFMERGE destkey [sourcekey sourcekey]
> PFADD course git c java spring ngnix
(integer) 1
> PFCOUNT course
(integer) 5
> PFADD course2 go c++ java
(integer) 1
> PFMERGE result course course2
"OK"
> PFCOUNT result
(integer) 7
Bitmap 位图
字符串类型扩展
应用场景: 签到情况, 在线状态
设置
SETBIT key offset value
获取
GETBIT key offset
> SETBIT dianzan 0 1
(integer) 0
> SETBIT dianzan 1 0
(integer) 0
> GETBIT dianzan 0
(integer) 1
> GETBIT dianzan 1
(integer) 0
使用字符串命令设置
SET key value
> SET dianzan "\xF0" # 16进制的 11110000
"OK"
获取位图中 1 的个数
BITCOUNT key
> BITCOUNT dianzan
(integer) 4
获取第一次出现 0/1 的位置
BITPOS key bit [start [end]]
Bitfield
将小的整数存储到位图节省内存
设置一个位域
BITFIELD key SET encoding offset value
获取位域的值
BITFIELD key GET encoding offset
增加位域的值
BITFIELD key INCRBY encoding offset incrementvalue
> BITFIELD player:0 SET u8 #0 1
1) "0"
> BITFIELD player:0 GET u8 #0
1) "1"
> BITFIELD player:0 SET u32 #1 100
1) "0"
> BITFIELD player:0 GET u32 #1
1) "100"
> BITFIELD player:0 INCRBY u32 #1 100
1) "200"
> BITFIELD player:0 GET u32 #1
1) "200"
Redis 支持事务
在一次请求中执行多个命令
MULTI
SET
LPUSH
SADD
EXEC/DISCARD
不同于关系型数据库, 没有原子性操作,但保证:
- 发起 EXEC 命令前,所有命令都会被放到队列缓存起来,不会立即执行;
- 收到 EXEC 命令后,事务开始执行,任何一个事务执行失败,其他命令依然会执行;
- 事务执行过程中,其他客户端请求的命令不会被插入到事务执行命令序列中;
> MULTI
"OK"
> SET k1 v1
"QUEUED"
> SET k2 v2
"QUEUED"
> EXEC
1) "OK"
2) "OK"
错误不会影响后续事务
> SET k3 3
"OK"
> set k4 V4
"OK"
> set k5 5
"OK"
> multi
"OK"
> incr k3
"QUEUED"
> incr k4
"QUEUED"
> incr k5
"QUEUED"
> exec
1) "4"
2) "ReplyError: ERR value is not an integer or out of range"
3) "6"
> get k3
"4"
> get k4
"V4"
> get k5
"6"
Redis 持久化
RDB redis database
某个时间点上数据的完整副本
vim redis.conf
macos 下的 redis 配置文件路径:
/opt/homebrew/etc/redis.conf
获取方法:
brew list redis
cat /opt/homebrew/Cellar/redis/7.2.5/homebrew.mxcl.redis.plist
## 得到/opt/homebrew/etc/redis.conf
打开 redis.conf
修改 save <seconds> <changes>
在指定时间有多少次修改才进行一次快照
################################ SNAPSHOTTING ##############################
# Save the DB to disk.
#
# save <seconds> <changes> [<seconds> <changes> ...]
#
# Redis will save the DB if the given number of seconds elapsed and it
# surpassed the given number of write operations against the DB.
#
# Unless specified otherwise, by default Redis will save the DB:
# * After 3600 seconds (an hour) if at least 1 change was performed
# * After 300 seconds (5 minutes) if at least 100 changes were performed
# * After 60 seconds if at least 10000 changes were performed
#
# You can set these explicitly by uncommenting the following line.
#
# save 3600 1 300 100 60 10000
使用save命令手动执行快照会得到dump.rdb文件
将 dump.rdb 文件移动到 redis 安装目录, 重启 redis 会自动加载数据快照
127.0.0.1:6379> save
OK
bgsave 创建一个子进程来进行快照,创建子进程时间内没有办法进行秒级快照
AOF append only file
将 redis 中每个写操作以日志的形式记录, 当重启时执行,在内存中重建 redis 数据库
开启方法:
appendonly no -> appendonly yes
主从复制 Replication
将主节点(master)单向复制到从节点(slave)
一般主节点负责写, 从节点负责读
主节点将自己的数据变化异步方式发送到从节点,从节点更新数据
redis 默认启动的是主节点
查看当前角色:role
> role
1) "master"
2) "0"
3) (empty list or set)
配置所属主节点
命令行(不常用)
replicaof host port
/
slaveof host port(legacy)
配置文件设置从节点
# 1. 复制配置文件
cp /opt/homebrew/etc/redis.conf redis-6380.conf
# 2. 更改配置文件
code redis-6380.conf
# port 6379 -> 6380
# pidfile /opt/homebrew/var/run/redis-6379.pid -> pidfile /opt/homebrew/var/run/redis-6380.pid 防止进程id重复
# dbfilename dump.rdb -> dbfilename dump-6380.rdb 执行save/bgsave时保存的数据库快照名
# # replicaof <masterip> <masterport> -> replicaof 127.0.0.1 6379 端口号指向主节点
# 3.启动
redis-server redis-6380.conf
# 4.连接
redis-cli -p 6380
# 5.查看info
info replication
# 输出如下信息
Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_read_repl_offset:98
slave_repl_offset:98
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:9dfc0f4bc24761c9ac7d9fda79ce252b4b7c14ce
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:98
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:15
repl_backlog_histlen:84
此时主从节点的数据已经同步
哨兵模式
监控:监控集群中各个节点的状态, 通过不断发送命令检查节点正常
通知:发现某个节点出现问题,通过发布订阅模式通知其他节点
自动故障转移: 主当节点不能正常工作, 将其中一个从节点升级主节点, 将其他的从节点指向新的主节点
# 编写 sentinel.conf
vim sentinel.conf
# 添加如下内容:
sentinel monitor master 127.0.0.1 6379 1
# 退出并运行
redis-sentinel sentinel.conf
sentinel
生产环境中会用三个哨兵节点, 选出一个领导来监控其他节点, 当领导停止运行, 会有其他哨兵接替领导位置,保证哨兵节点的高可用性