入门Redis学习总结

记录之前刚学习Redis 的笔记, 主要包括Redis的基本数据结构、Redis 发布订阅机制、Redis 事务、Redis 服务器相关及采用Spring Boot 集成Redis 实现增删改查基本功能

一:常用命令及数据结构

1.Redis 键(key)

# 设置key和value
127.0.0.1:6379> set mykey hello
OK# 获取key对应的内容
127.0.0.1:6379> get mykey
"hello"# 序列化给定 key ,并返回被序列化的值
127.0.0.1:6379> dump mykey
"\x00\x05hello\t\x00\xb3\x80\x8e\xba1\xb2C\xbb"# 判断是否存在某个key是否存在
127.0.0.1:6379> exists mykey
(integer) 1
127.0.0.1:6379> exists mykey1
(integer) 0# 查询所有的key
127.0.0.1:6379> keys *
1) "mykey"
2) "mylist1"
3) "key1"
4) "list"
5) "myList"
6) "mylist"
7) "friend:a"
8) "friend:b"# 设置key的过期时间
127.0.0.1:6379> expire mykey 20
(integer) 1
127.0.0.1:6379> get mykey
"hello"# 以秒为单位,返回给定 key 的剩余生存时间
127.0.0.1:6379> ttl mykey
(integer) -2# 返回 key 所储存的值的类型
127.0.0.1:6379> set mykey hello
OK
127.0.0.1:6379> type mykey
string
127.0.0.1:6379>

2:Redis字符串

# 设置键
127.0.0.1:6379> set mykey hello
OK
127.0.0.1:6379> get key
(nil)
127.0.0.1:6379> get mykey
"hello"# 返回 key 中指定长度的字符串值的子字符
127.0.0.1:6379> getrange mykey 0 4
"hello"
127.0.0.1:6379> getrange mykey 0 2
"hel"# 重新设置key的值,并且返回老的值
127.0.0.1:6379> getset mykey hello&world
"hello"
127.0.0.1:6379># 获取多个key对应的值
127.0.0.1:6379> mget mykey mykey1 mykey2 mykey3 mykey4
1) "hello&world"
2) "java"
3) "spring"
4) "springboot"
5) "mysql"
127.0.0.1:6379># 为指定的 key 设置值及其过期时间,如果存在则修改值,如果不存在则新增并赋值
127.0.0.1:6379> SETEX mykey4 20 spark
OK
127.0.0.1:6379> get mykey4
"spark"
127.0.0.1:6379> SETEX mykey5 20 Hbase
OK
127.0.0.1:6379> get mykey5
"Hbase"# SETNX 命令在指定key不存在时,创建key并设置,当key存在时则不处理-->原生Redis分布式就是采用这个性质
127.0.0.1:6379> exists presto
(integer) 0
127.0.0.1:6379> setnx presto hiveSql
(integer) 1
127.0.0.1:6379> get presto
"hiveSql"
127.0.0.1:6379> setnx presto hiveSql+search
(integer) 0
127.0.0.1:6379> get presto
"hiveSql"
127.0.0.1:6379># 获取指定key值的长度
127.0.0.1:6379> get mykey3
"springboot"
127.0.0.1:6379> strlen mykey3
(integer) 10# 批量设置key和value
127.0.0.1:6379> mset mykey4 kafka mykey5 redis mykey6 nginx mykey7 oracle
OK
# 批量获取key和value
127.0.0.1:6379> mget mykey4 mykey5 mykey6 mykey7
1) "kafka"
2) "redis"
3) "nginx"
4) "oracle"
127.0.0.1:6379># 设置nkey 值为100
127.0.0.1:6379> set nkey 100
OK
127.0.0.1:6379> get nkey
"100"
# 自增1
127.0.0.1:6379> incr nkey
(integer) 101
# 自减1
127.0.0.1:6379> decr nkey
(integer) 100
# 加上一定的数
127.0.0.1:6379> incrby nkey 100
(integer) 200
# 减去一定的数
127.0.0.1:6379> decrby nkey 100
(integer) 100# 给指定的key对应的值后面拼接字符串
127.0.0.1:6379> get mykey7
"oracle"
127.0.0.1:6379> append mykey7 11
(integer) 8
127.0.0.1:6379> get mykey7
"oracle11"
127.0.0.1:6379>

3:Redis 哈希(Hash)

# 设置hash表key为field1,值为mysql
127.0.0.1:6379> hset hkey field1 mysql
(integer) 1
127.0.0.1:6379> hset hkey field2 oracle
(integer) 1# 获取hash表的值
127.0.0.1:6379> hget hkey field1
"mysql"# 获取所有的key
127.0.0.1:6379> hkeys hkey
1) "field1"
2) "field2"# 判断hash表中指定key是否存在
127.0.0.1:6379> hexists hkey field3
(integer) 0127.0.0.1:6379> hset hkey field3 spring
(integer) 1
127.0.0.1:6379> hget hkey field3
"spring"# 获取hash表的长度,及hash表的元素个数
127.0.0.1:6379> hlen hkey
(integer) 3# 获取hash表中所有的key
127.0.0.1:6379> hkeys hkey
1) "field1"
2) "field2"
3) "field3"# hash表元素增加指定量
127.0.0.1:6379> hset hkey field4 100
(integer) 1
127.0.0.1:6379> hget hkey field4
"100"
127.0.0.1:6379> hincrby hkey field4 100
(integer) 200# 获取hash表中所有的值
127.0.0.1:6379> hvals hkey
1) "mysql"
2) "oracle"
3) "spring"
4) "200"# 获取hash表中的多个字段的值
127.0.0.1:6379> hmget hkey field1 field2 field3 field4
1) "mysql"
2) "oracle"
3) "spring"
4) "200"# 只有在字段 field 不存在时,设置哈希表字段的值
127.0.0.1:6379> hsetnx hkey field5 springboot
(integer) 1
127.0.0.1:6379> hsetnx hkey field6 springcloud
(integer) 1
127.0.0.1:6379> hsetnx hkey field7 springCloud
(integer) 1
127.0.0.1:6379> hsetnx hkey field6 springCloud
(integer) 0
127.0.0.1:6379>

4:Redis 列表(List)

# push
127.0.0.1:6379> lpush lkey spring springboot mybatis mysql oracle kafka redis hive presto clickhourse es spark hbase flink vue
(integer) 15# 求长度
127.0.0.1:6379> llen lkey
(integer) 15# 根据索引获取元素
127.0.0.1:6379> lindex lkey 0
"vue"
127.0.0.1:6379> lindex key 1
(nil)
127.0.0.1:6379> lindex lkey 1
"flink"
127.0.0.1:6379> lindex lkey 5
"clickhourse"# 获取指定范围索引的值
127.0.0.1:6379> lrange lkey 0 -11) "vue"2) "flink"3) "hbase"4) "spark"5) "es"6) "clickhourse"7) "presto"8) "hive"9) "redis"
10) "kafka"
11) "oracle"
12) "mysql"
13) "mybatis"
14) "springboot"
15) "spring"
127.0.0.1:6379> lrange lkey 0 1
1) "vue"
2) "flink"
127.0.0.1:6379>

5.Redis 集合(Set)

Set 是 String 类型的无序、不可重复的集合

D:\software\redis>redis-cli.exe -h 127.0.0.1 -p 6379\
# 往Set集合添加元素
127.0.0.1:6379> sadd skey redis
(integer) 1# 查询Set集合中的元素个数
127.0.0.1:6379> scard skey
(integer) 1# 查询Set集合中所有的元素
127.0.0.1:6379> smembers skey
1) "redis"# 往Set集合中批量添加元素
127.0.0.1:6379> sadd skey mysql oracle hive presto spark hadoop kafka spring springboor springCloud mybatis
(integer) 11# 查询Set集合中所有的元素
127.0.0.1:6379> smembers skey1) "redis"2) "spring"3) "hadoop"4) "spark"5) "mybatis"6) "springboor"7) "presto"8) "kafka"9) "springCloud"
10) "hive"
11) "mysql"
12) "oracle"# 往Set集合中添加已经存在的元素,添加失败
127.0.0.1:6379> sadd skey redis
(integer) 0127.0.0.1:6379> smembers skey1) "spring"2) "hadoop"3) "spark"4) "mybatis"5) "springboor"6) "presto"7) "kafka"8) "springCloud"9) "hive"
10) "mysql"
11) "oracle"
12) "redis"# 批量往Set集合添加元素
127.0.0.1:6379> sadd skey1 mysql oracle hive presto spark hadoop kafka spring springboor springCloud mybatis nginx linux
(integer) 13127.0.0.1:6379> smembers skey11) "spring"2) "hadoop"3) "spark"4) "mybatis"5) "springboor"6) "presto"7) "kafka"8) "hive"9) "mysql"
10) "springCloud"
11) "oracle"
12) "linux"
13) "nginx"# 查询差集:在skey集合中存在,但是在skey1集合中不存在的数据
127.0.0.1:6379> sdiff skey skey1
1) "redis"
# 查询差集:在skey1集合中存在,但是在skey集合中不存在的数据
127.0.0.1:6379> sdiff skey1 skey
1) "nginx"
2) "linux"
127.0.0.1:6379> sinter skey skey11) "spring"2) "hadoop"3) "spark"4) "mybatis"5) "springboor"6) "presto"7) "kafka"8) "springCloud"9) "hive"
10) "mysql"
11) "oracle"# 查询集合skey和集合skey1的差集(在skey存在但是在skey1中不存在的数据),并且存在skey3
127.0.0.1:6379> sdiffstore skey3 skey skey1
(integer) 1
127.0.0.1:6379> smembers skey3
1) "redis"# 查询集合skey和集合skey1的交集,并且存在skey4
127.0.0.1:6379> sinterstore skey4 skey skey1
(integer) 11
127.0.0.1:6379> smembers skey41) "hadoop"2) "kafka"3) "presto"4) "spark"5) "springCloud"6) "spring"7) "springboor"8) "mybatis"9) "mysql"
10) "hive"
11) "oracle"# 查询skey4中是否存在元素linux
127.0.0.1:6379> sismember skey4 linux
(integer) 0
127.0.0.1:6379> sismember skey4 kafka
(integer) 1127.0.0.1:6379> smembers skey11) "spring"2) "hadoop"3) "spark"4) "mybatis"5) "springboor"6) "presto"7) "kafka"8) "hive"9) "mysql"
10) "springCloud"
11) "oracle"
12) "linux"
13) "nginx"# 把linux元素从skey1移动到skey4(移动后->返回1,skey1不存在,skey4存在该元素)
127.0.0.1:6379> smove skey1 skey4 linux
(integer) 1127.0.0.1:6379> smembers skey41) "spring"2) "hadoop"3) "spark"4) "springboor"5) "mybatis"6) "presto"7) "kafka"8) "springCloud"9) "mysql"
10) "hive"
11) "oracle"
12) "linux"# srandmember表示从集合中一个或多个随机数
127.0.0.1:6379> srandmember skey4
"linux"
127.0.0.1:6379> srandmember skey4
"springCloud"
127.0.0.1:6379> srandmember skey4
"springboor"
127.0.0.1:6379> srandmember skey4
"mybatis"
127.0.0.1:6379> srandmember skey4
"spark"
127.0.0.1:6379> srandmember skey4
"kafka"
127.0.0.1:6379> srandmember skey4
"springCloud"
127.0.0.1:6379> srandmember skey4
"oracle"127.0.0.1:6379> smembers skey41) "spring"2) "hadoop"3) "spark"4) "springboor"5) "mybatis"6) "presto"7) "kafka"8) "springCloud"9) "mysql"
10) "hive"
11) "oracle"
12) "linux"
127.0.0.1:6379> smembers skey11) "spring"2) "hadoop"3) "spark"4) "mybatis"5) "springboor"6) "presto"7) "kafka"8) "hive"9) "mysql"
10) "springCloud"
11) "oracle"
12) "nginx"# 返回所有给定集合的并集
127.0.0.1:6379> sunion skey1 skey41) "spring"2) "hadoop"3) "spark"4) "springboor"5) "mybatis"6) "presto"7) "kafka"8) "hive"9) "springCloud"
10) "mysql"
11) "oracle"
12) "linux"
13) "nginx"# 移除集合中一个或多个成员
127.0.0.1:6379> srem skey4 springCloud
(integer) 1# 移除并返回集合中的一个随机元素
127.0.0.1:6379> spop skey4
"spark"127.0.0.1:6379> smembers skey41) "spring"2) "hadoop"3) "springboor"4) "mybatis"5) "presto"6) "kafka"7) "mysql"8) "hive"9) "oracle"
10) "linux"
127.0.0.1:6379> spop skey4
"kafka"
127.0.0.1:6379> smembers skey4
1) "spring"
2) "hadoop"
3) "springboor"
4) "mybatis"
5) "presto"
6) "mysql"
7) "hive"
8) "oracle"
9) "linux"
127.0.0.1:6379>

6.Redis 有序集合(sorted set)

sorted set是一个有序、不重复的集合。每个元素都会关联一个double类型的分数,通过分数为集合中的成员进行从小到大进行排序。底层是通过哈希表实现的,添加、删除、查询的时间复杂度都是O(1)

有序集合的元素不可重复,但是分数可以重复

D:\software\redis>redis-cli.exe -h 127.0.0.1 -p 6379# 新建key为C++的sorted set,并往里批量添加元素
127.0.0.1:6379> zadd C++ 99 zhangsan 89 lisi 88 wangwu 79 zhaoliu 60 xiaoqi
(integer) 5# 查询有序集合中的成员数
127.0.0.1:6379> zcard C++
(integer) 5# 查询指定区间分数(min max)的元素个数
127.0.0.1:6379> zcount C++ 90 100
(integer) 1
127.0.0.1:6379> zcount C++ 80 90
(integer) 2
127.0.0.1:6379> zcount C++ 70 80
(integer) 1
127.0.0.1:6379> zcount C++ 60 70
(integer) 1# 给有序集合中某个元素的分数添加上指定的值
127.0.0.1:6379> zincrby C++ 10 xiaoqi
"70"# 查询有序集合中的全部的元素
127.0.0.1:6379> zrange C++ 0 -1
1) "xiaoqi"
2) "zhaoliu"
3) "wangwu"
4) "lisi"
5) "zhangsan"# 查询有序集合中的全部的元素及值
127.0.0.1:6379> zrange C++ 0 -1 WITHSCORES1) "xiaoqi"2) "70"3) "zhaoliu"4) "79"5) "wangwu"6) "88"7) "lisi"8) "89"9) "zhangsan"
10) "99"# 查询有序集合中的指定分数区间对应的元素
127.0.0.1:6379> ZRANGEBYSCORE C++ 90 100
1) "zhangsan"# 查询有序集合中所有的元素,并且按照升序排序
127.0.0.1:6379> ZRANGEBYSCORE C++ -inf +inf
1) "xiaoqi"
2) "zhaoliu"
3) "wangwu"
4) "lisi"
5) "zhangsan"# 查询有序集合中所有的元素及分数,并且按照升序排序
127.0.0.1:6379> ZRANGEBYSCORE C++ -inf +inf WITHSCORES1) "xiaoqi"2) "70"3) "zhaoliu"4) "79"5) "wangwu"6) "88"7) "lisi"8) "89"9) "zhangsan"
10) "99"# 查询有序集合中分数为90以下的元素
127.0.0.1:6379> ZRANGEBYSCORE C++ -inf 90
1) "xiaoqi"
2) "zhaoliu"
3) "wangwu"
4) "lisi"# 查询有序集合中分数为90以下的元素及对应的分数
127.0.0.1:6379> ZRANGEBYSCORE C++ -inf 90 WITHSCORES
1) "xiaoqi"
2) "70"
3) "zhaoliu"
4) "79"
5) "wangwu"
6) "88"
7) "lisi"
8) "89"# 查询有序集合中分数为90以下的元素及对应的分数
127.0.0.1:6379> ZRANGEBYSCORE C++ 70 +inf WITHSCORES1) "xiaoqi"2) "70"3) "zhaoliu"4) "79"5) "wangwu"6) "88"7) "lisi"8) "89"9) "zhangsan"
10) "99"# 查询指定元素在有序集合中的元素排序,不存在会返回nil
127.0.0.1:6379> zrank zkey zhangsan
(nil)
127.0.0.1:6379> zrank C++ zhangsan
(integer) 4
127.0.0.1:6379> zrank C++ xiaoqi
(integer) 0
127.0.0.1:6379> zrank C++ zhaoliu
(integer) 1# 返回有序集中指定分数区间内的元素,分数从高到低排序 ZREVRANGEBYSCORE key max min
127.0.0.1:6379> ZREVRANGEBYSCORE C++ 100 60
1) "zhangsan"
2) "lisi"
3) "wangwu"
4) "zhaoliu"
5) "xiaoqi"# 返回有序集中指定分数区间内的元素及分数,分数从高到低排序 ZREVRANGEBYSCORE key max min
127.0.0.1:6379> ZREVRANGEBYSCORE C++ 100 60 WITHSCORES1) "zhangsan"2) "99"3) "lisi"4) "89"5) "wangwu"6) "88"7) "zhaoliu"8) "79"9) "xiaoqi"
10) "70"# 查询有序集合中所有的元素 按照分数从大到小
127.0.0.1:6379> ZREVRANGEBYSCORE C++ +inf -inf
1) "zhangsan"
2) "lisi"
3) "wangwu"
4) "zhaoliu"
5) "xiaoqi"# 查询有序集合中所有的元素 按照分数从大到小 ZREVRANGEBYSCORE key max min
127.0.0.1:6379> ZREVRANGEBYSCORE C++ 60 80
(empty list or set)127.0.0.1:6379> ZREVRANGEBYSCORE C++ 80 60
1) "zhaoliu"
2) "xiaoqi"# 查询有序集合中所有的元素及对应的分数 按照分数从大到小 ZREVRANGEBYSCORE key max min
127.0.0.1:6379> ZREVRANGEBYSCORE C++ 80 60 WITHSCORES
1) "zhaoliu"
2) "79"
3) "xiaoqi"
4) "70"# 返回有序集合中指定元素在集合中的排名,按照分数降序排序
127.0.0.1:6379> zrevrank C++ zhangsan
(integer) 0
127.0.0.1:6379> zrevrank C++ xiaoqi
(integer) 4# 返回有序集合中指定元素对应的分数
127.0.0.1:6379> zscore C++ zhangsan
"99"# 新建Java 有序集合
127.0.0.1:6379> zadd Java 99 zhangsan 89 lisi 88 wangwu 79 zhaoliu 60 xiaoqi
(integer) 5# 计算两个有序集合的分数值
127.0.0.1:6379> ZINTERSTORE scores 2 C++ Java
(integer) 5
127.0.0.1:6379> zrange scores 0 -1
1) "xiaoqi"
2) "zhaoliu"
3) "wangwu"
4) "lisi"
5) "zhangsan"
# 查询计算分数值后的有序集合
127.0.0.1:6379> zrange scores 0 -1 WITHSCORES1) "xiaoqi"2) "130"3) "zhaoliu"4) "158"5) "wangwu"6) "176"7) "lisi"8) "178"9) "zhangsan"
10) "198"
127.0.0.1:6379>

image-20230619110242159

二:Redis发布与订阅

发布端

D:\software\redis>redis-cli.exe -h 127.0.0.1 -p 6379# 发布消息
127.0.0.1:6379> publish  mychat "start my chat"
(integer) 1127.0.0.1:6379> publish  mychat "hello !"
(integer) 1
127.0.0.1:6379> pubsub channels
1) "mychat"
127.0.0.1:6379> punsubscribe mychat
1) "punsubscribe"
2) "mychat"
3) (integer) 0
127.0.0.1:6379> publish  mychat "hello !"
(integer) 1
127.0.0.1:6379>

image-20230618202705374

image-20230618202854211

三:Redis 事务

什么是Redis事务?

Redis 事务可以一次执行多个命令,

  • 批量操作在发送EXEC命令前被放入到缓存中;【开始事务】
  • 收到EXEC命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行;【命令入列】
  • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中;【执行事务】

事务案例

image-20230618212724278

D:\software\redis>redis-cli.exe -h 127.0.0.1 -p 6379
# 开启事务
127.0.0.1:6379> multi
OK
# 往List里面批量添加元素,返回QUEUED表示命令存入队列中
127.0.0.1:6379> lpush book C++ Java C Linux Spring SpringBoot Hive Presto
QUEUED# 查询List中所有元素,返回QUEUED表示命令存入队列中
127.0.0.1:6379> lrange book 0 -1
QUEUED# 错误命令演示
127.0.0.1:6379> sadd C++  90 zhangsan 88 lisi 79 wangwu 94 zhaoliu
QUEUED# 执行命令
127.0.0.1:6379> exec# 第一个命令执行成功,往List里面添加了8个元素
1) (integer) 8# 第二个命令执行成功,返回List中的所有数据
2) 1) "Presto"2) "Hive"3) "SpringBoot"4) "Spring"5) "Linux"6) "C"7) "Java"8) "C++"# 第三个命令执行错误
3) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379># 演示取消事务
# 开启事务
127.0.0.1:6379> multi
OK
127.0.0.1:6379> lpush book1 C++ Java C Linux Spring SpringBoot Hive Presto
QUEUED
127.0.0.1:6379> lrange book1 0 -1
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> lrange book1 0 -1
(empty list or set)
127.0.0.1:6379>

事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

四:Redis服务器

# 手动触发异步式重写AOF
127.0.0.1:6379> bgrewriteaof
Background append only file rewriting started# 异步保存当前数据库的数据到磁盘
127.0.0.1:6379> BGSAVE
Background saving started# 获取连接到服务器的客户端连接列表
127.0.0.1:6379> client list
id=9 addr=127.0.0.1:56993 fd=11 name= age=6255 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client# 关闭客户端连接
127.0.0.1:6379> client kill 127.0.0.1:56993
OK
# 之前的连接已经被关闭,CLI 客户端又重新建立了连接,之前端口号是56993 现在是59469
127.0.0.1:6379> client list
id=10 addr=127.0.0.1:59469 fd=10 name= age=0 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client# 获取连接的客户端的名称
127.0.0.1:6379> client getname
(nil)
# 设置连接客户端的名称
127.0.0.1:6379> client setname hello-wordld-connection
OK
127.0.0.1:6379> client getname
"hello-wordld-connection"# 获取Redis命令详情
127.0.0.1:6379> command
# 获取Redis命令总数
127.0.0.1:6379> command count
(integer) 200# 获取Reids 中所有的key
127.0.0.1:6379> dbsize
(integer) 30
127.0.0.1:6379> set k v
OK
127.0.0.1:6379> dbsize
(integer) 31# 切换到1号数据库,dbsize查看1号数据库的key为0
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> dbsize
(integer) 0
# 在1号数据库添加数据
127.0.0.1:6379[1]> set key Java
OK
127.0.0.1:6379[1]> set Key1 C++
OK
127.0.0.1:6379[1]> get key
"Java"
127.0.0.1:6379[1]> get Key1
"C++"
127.0.0.1:6379[1]> dbsize
(integer) 2
# 清空整个 Redis 服务器的数据
127.0.0.1:6379[1]> fluahall
(error) ERR unknown command `fluahall`, with args beginning with:
127.0.0.1:6379[1]> flushall
OK
127.0.0.1:6379[1]> dbsize
(integer) 0# 返回最近一次Redis成功把数据保存到磁盘上的时间,以 UNIX 时间戳格式表示
127.0.0.1:6379[1]> lastsave
(integer) 1687104505# 列出连接客户端
127.0.0.1:6379> client list
id=15 addr=127.0.0.1:61301 fd=13 name= age=68 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client# Slaveof 命令可以将当前服务器转变为指定服务器的从属服务器(slave server)
# 如果当前服务器已经是某个主服务器(master server)的从属服务器,那么执行 SLAVEOF host port 将使当前服务器停止对旧主服务器的同步,丢弃旧数据集,转而开始对新主服务器进行同步
# 对一个从属服务器执行命令 SLAVEOF NO ONE 将使得这个从属服务器关闭复制功能,并从从属服务器转变回主服务器,原来同步所得的数据集不会被丢弃
# 利用『 SLAVEOF NO ONE 不会丢弃同步所得数据集』这个特性,可以在主服务器失败的时候,将从属服务器用作新的主服务器,从而实现无间断运行。
127.0.0.1:6379> SLAVEOF 127.0.0.1 61301
OK
127.0.0.1:6379>

五:Redis GEO

Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,该功能在 Redis 3.2 版本新增。

Redis GEO 操作方法有:

  • geoadd:添加地理位置的坐标。
  • geopos:获取地理位置的坐标。
  • geodist:计算两个位置之间的距离。
  • georadius:根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。
  • georadiusbymember:根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。
  • geohash:返回一个或多个位置对象的 geohash 值。

六:Redis客户端

1.Jedis

优点

  • 以Redis命令作为方法的名称,学习成本低,简单使用,提供了比较全面的Redis命令支持;

缺点:

  • Jedis实例是线程不安全的,同步阻塞IO,不支持异步,多线程环境下需要基于连接池来使用;

使用案例

(1)创建项目,引入依赖

    <dependencies><!-- Jedis --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.7.1</version><scope>test</scope></dependency></dependencies>

(2)编写测试代码

public class JedisTest {private Jedis jedis;@BeforeEachvoid setUp() {//1.建立连接jedis = new Jedis("127.0.0.1", 6379);//2.设置密码(如果Reis有设置密码的话,必须手动设置密码,否则无须指定密码)// jedis.auth("123456");//3.选择库jedis.select(0);}@Testvoid testString() {//存入String key = "k1";String value = "张三";String result = jedis.set(key, value);System.out.println("result=" + result);//读取String name = jedis.get(key);System.out.println("name=" + name);}@Testvoid testHash() {Map<String, String> map = new HashMap<>();map.put("k", "C++");map.put("k1", "Java");map.put("k2", "C");map.put("k3", "Spring");map.put("k4", "SpringBoot");String key = "tech";Long result = jedis.hset(key, map);if (result != 0) {//获取所有的keySet<String> hkeys = jedis.hkeys(key);System.out.println("获取所有的key=" + hkeys.toString());//获取hash表的值List<String> hvals = jedis.hvals(key);System.out.println("获取hash表的值=" + Arrays.toString(hvals.toArray()));//获取hash表长度Long hlen = jedis.hlen(key);System.out.println("获取hash表长度,len=" + hlen);//获取hash表中多个字段的值List<String> hmget = jedis.hmget(key, "k", "k1", "k2", "k3");System.out.println("获取hash表中多个字段的值=" + Arrays.toString(hmget.toArray()));}}//执行后@AfterEachvoid tearDown() {if (null != jedis) {jedis.close();}}
}

上述代码在多线程场景下会出现线程安全问题,可以采用Jedis的线程池处理

// 定义工具类
public class JedisConnectionFactory {private static final JedisPool jedisPool;static {JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();// 最大连接jedisPoolConfig.setMaxTotal(8);// 最大空闲连接jedisPoolConfig.setMaxIdle(8);//最小空闲连接jedisPoolConfig.setMinIdle(0);// 设置最长等待时间msjedisPoolConfig.setMaxWaitMillis(200);jedisPool = new JedisPool(jedisPoolConfig, "127.0.0.1X", 6379, 1000);}public static Jedis getJedis() {return jedisPool.getResource();}
}

对于上述代码改造,只需要把创建连接的方式调整成从连接吃里面获取即可

    @BeforeEachvoid setUp() {jedis = JedisConnectionFactory.getJedis();jedis.select(0);}

2.Lettuce

优点:

  • Lettuce是基于Netty实现的,支持同步、异步和响应式编程方式,并且是线程安全的。支持Redis的哨兵模式、集群模式和管道模式。

缺点:

  • API更抽象,学习成本高

3.Redisson

优点

  • Redisson是一个基于Redis实现的分布式、可伸缩的Java数据结构集合。包含了诸如Map、Queue、Lock、 Semaphore、AtomicLong等强大功能。

缺点:

  • API更抽象,学习成本高

七:SpringBoot 整合Redis

1.创建SpringBoot 项目

image-20230621003211858

image-20230621003318693

2.引入依赖(完整pom文件)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.7</version><relativePath/></parent><groupId>com.example</groupId><artifactId>spring-redis</artifactId><version>0.0.1-SNAPSHOT</version><name>spring-redis</name><description>spring-redis</description><properties><java.version>8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--common-pool--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!--Jackson依赖--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

3.配置文件

application.yaml

spring:data:redis:host: 127.0.0.1port: 6379lettuce:pool:max-active: 8max-idle: 8min-idle: 0max-wait: 100ms

4.测试:使用RedisTemplate操作Redis

@SpringBootTest
class SpringRedisApplicationTests {@Autowiredprivate RedisTemplate redisTemplate;@Testvoid testString() {redisTemplate.opsForValue().set("zhangsan", "张三");Object zhangsan = redisTemplate.opsForValue().get("zhangsan");System.out.println("name = " + zhangsan);}}

image-20230621004442225

八:Redis 序列化器

image-20230621005407823

image-20230621005722140

RedisSerializer又包含以下几个序列化器:

image-20230621005808396

我们可以自定义Redis 序列化器,具体如下:

@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){// 创建RedisTemplate对象RedisTemplate<String, Object> template = new RedisTemplate<>();// 设置连接工厂template.setConnectionFactory(connectionFactory);// 创建JSON序列化工具GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();// 设置Key的序列化template.setKeySerializer(RedisSerializer.string());template.setHashKeySerializer(RedisSerializer.string());// 设置Value的序列化template.setValueSerializer(jsonRedisSerializer);template.setHashValueSerializer(jsonRedisSerializer);// 返回return template;}
}

使用自定义序列化器后,就能解决上述不规则的字节形式

image-20230621010946734

存储对象时,自定义的Redis序列化器也会自动把对象转成JSON后存储,反序列化时可以把JSON转成对象

    @Testvoid testSaveUser() {// 写入数据redisTemplate.opsForValue().set("user:100", new User("李四", 18));// 获取数据User o = (User) redisTemplate.opsForValue().get("user:100");System.out.println("o = " + o);}

image-20230621011117609

执行成功可以查看到此时存储的是JSON格式的数据

image-20230621011136095

尽管JSON的序列化方式可以满足我们的需求,但依然存在一些问题,如图

image-20230621011445305

为了在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入json结果中,存入Redis,会带来额外的内存开销。

StringRedisTemplate

image-20230621011639787

使用StringRedisTemplate解决上述出现的问题,具体如下:

@SpringBootTest
class RedisStringTests {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testvoid testString() {// 写入一条String数据stringRedisTemplate.opsForValue().set("k3", "老六");// 获取string数据Object name = stringRedisTemplate.opsForValue().get("k3");System.out.println("k3 = " + name);}private static final ObjectMapper mapper = new ObjectMapper();@Testvoid testSaveUser() throws JsonProcessingException {// 创建对象User user = new User("王五", 19);// 手动序列化String json = mapper.writeValueAsString(user);// 写入数据stringRedisTemplate.opsForValue().set("user:200", json);// 获取数据String jsonUser = stringRedisTemplate.opsForValue().get("user:200");// 手动反序列化User user1 = mapper.readValue(jsonUser, User.class);System.out.println("user1 = " + user1);}@Testvoid testHash() {stringRedisTemplate.opsForHash().put("user:400", "name", "王五");stringRedisTemplate.opsForHash().put("user:400", "age", "19");Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("user:400");System.out.println("entries = " + entries);}
}

image-20230621012332647

此时只存对象的类型,不会存储对象所在类的类型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/210292.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解释AI决策,这10个强大的 Python 库记得收藏!

本文整理了10个常用于可解释AI的Python库&#xff0c;方便我们更好的理解AI模型的决策。 什么是XAI&#xff1f; XAI&#xff08;Explainable AI&#xff09;的目标是为模型的行为和决策提供合理的解释&#xff0c;这有助于增加信任、提供问责制和模型决策的透明度。XAI 不仅…

《深入浅出进阶篇》洛谷P3197 越狱——集合

洛谷P3197 越狱 题目大意&#xff1a; 监狱有 n 个房间&#xff0c;每个房间关押一个犯人&#xff0c;有 m 种宗教&#xff0c;每个犯人会信仰其中一种。如果相邻房间的犯人的宗教相同&#xff0c;就可能发生越狱&#xff0c;求有多少种状态可能发生越狱。 答案对100,003 取模。…

Temu卖家如何获取流量?Temu新手卖家流量来源哪里?——站斧浏览器

流量对于每个平台来说都是很重要的&#xff0c;那么Temu卖家如何获取流量&#xff1f;流量来源哪里&#xff1f; Temu卖家如何获取流量&#xff1f; 1、优化产品标题和描述&#xff1a;在Temu平台上&#xff0c;买家通常通过搜索关键词来寻找他们感兴趣的产品。因此&#xff…

【数电笔记】58-同步D触发器

目录 说明&#xff1a; 1. 电路组成 2. 逻辑功能 3. 特性表、特性方程 4. 状态转移图 例题 5. 同步D触发器的特点 6. 集成同步D触发器&#xff1a;74LS375 74LS375内部原理 说明&#xff1a; 笔记配套视频来源&#xff1a;B站本系列笔记并未记录所有章节&#xff0c;…

Web 开发的 20 个实用网站

Web 开发的 20 个实用网站 作为一名前端开发工程师&#xff0c;我们一定使用过很多工具来提高自己的工作效率。它们可以是网站、文档或 JavaScript 库。 本文将分享30个有趣的网站。 JavaScript正则表达式可视化工具 https://jex.im/regulex/#!flags&re%5E(a%7Cb)*%3F%…

★102. 二叉树的层序遍历

102. 二叉树的层序遍历 很巧妙的&#xff0c;又学习了一种层次遍历的方法&#xff0c;就是说根据当前的队列的长度去遍历&#xff0c;遍历的当前队列的长度就是该层次的节点个数。 /*** Definition for a binary tree node.* public class TreeNode {* int val;* Tr…

AIGC专题报告:AIGC助力大规模对象存储服务OSS的能效提升

今天分享的AIGC系列深度研究报告&#xff1a;《AIGC专题报告&#xff1a;AIGC助力大规模对象存储服务OSS的能效提升》。 &#xff08;报告出品方&#xff1a;全球软件开发大会&#xff09; 报告共计&#xff1a;18页 结合AI的智能运维助力能效提升 场景1&#xff1a;通过 AI…

Python 网络爬虫(三):XPath 基础知识

《Python入门核心技术》专栏总目录・点这里 文章目录 1. XPath简介2. XPath语法2.1 选择节点2.2 路径分隔符2.3 谓语2.4 节点关系2.5 运算符3. 节点3.1 元素节点(Element Node)3.2 属性节点(Attribute Node)

前端vue3——实现二次元人物拼图校验

文章目录 ⭐前言⭐vue3拖拽实现拼图&#x1f496; 思路分解&#x1f496; 布局结构&#x1f496; 拖拽函数&#x1f496; 校验函数&#x1f496; inscode整体代码 ⭐运行效果&#x1f496; 随机顺序&#x1f496; 拖拽中&#x1f496; 校验失败&#x1f496; 校验通过 ⭐总结⭐…

苍穹外卖项目笔记(8)— 缓存商品、购物车功能

前言 代码链接&#xff1a; Echo0701/take-out⁤ (github.com) 1 缓存菜品 1.1 问题说明 【注】很多时候系统性能的瓶颈就在于数据库这端 1.2 实现思路 通过 Redis 来缓存数据&#xff0c;减少数据库查询操作 【注】Redis 基于内存来保存数据的&#xff0c;访问 Redis 数据…

LeetCode208.实现Trie(前缀树)

我一开始想题目叫前缀树&#xff0c;是要用树吗&#xff1f;但是不知道用树怎么写&#xff0c;然后我就花了10多分钟&#xff0c;用了HashMap解了。map的key是word&#xff0c;value是一个放了word的所有前缀的set&#xff0c;这样search方法就非常简单了&#xff0c;只要看has…

Leetcode—2048.下一个更大的数值平衡数【中等】

2023每日刷题&#xff08;五十四&#xff09; Leetcode—2048.下一个更大的数值平衡数 实现代码 class Solution { public:int nextBeautifulNumber(int n) {for(int x n 1; ; x) {vector<int> cnt(10, 0);for(int y x; y > 0; y / 10) {cnt[y%10];}bool ok tru…

TP5上传图片压缩尺寸

图片上传&#xff0c;最简单的就是&#xff0c; 方法一&#xff1a; 修改上传限制&#xff0c;不让上传大于多少多少的图片 改一下size即可&#xff0c;默认单位是B换算成M还需要除以两次1024 方法二&#xff1a; 对上传的图片进行缩放&#xff0c;此办法网上找了不少的代码…

HCIP —— BGP 基础 (下)

BGP 的状态机 --- 建立对等体之间的TCP会话&#xff1a;指定建立对等体的对象 六种状态机 Idle状态 Idle 等待状态&#xff08;相当于OSPF的down状态&#xff09;--- 采用TCP单播建邻 Idle 状态下&#xff0c;启动BGP协议后必须指定建立对等体的目标之后&#xff0c;才能进入…

数据结构 | 查漏补缺之哈希表、最短路径、二叉树与森林的转换

哈希表是什么&#xff1f; 或者说 设图采用邻接表的存储结构&#xff0c;写对图的删除顶点和删除边的算法步骤 删除边 删除点 最短路径问题 参考博文 迪杰斯特拉(Dijkstra)算法_dijkstra算法-CSDN博客 Dijkstra(迪杰斯特拉&#xff09;算法 定义一个点为源点&#xff0c;算源…

5G+AI开花结果,助力智慧安检落地

“请带包的乘客过机安检&#xff01;”&#xff0c;深圳地铁、腾讯共同打造的5GAI智慧安检辅助系统亮相福田枢纽站&#xff0c;进一步解放了人力&#xff0c;提高安检效率&#xff0c;为交通安全保驾护航&#xff0c;让智慧出行成为现实。 传统的安检设备均为人工肉眼辨识&…

2023年9月13日 Go生态洞察:WASI支持在Go中的实现

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

21、命令执行

文章目录 一、命令执行概述1.1 基本定义1.2 原理1.3 两个条件1.4 命令执行漏洞产生的原因1.5 管道符号和通用命令符 二、远程命令执行2.1 远程命令执行相关函数2.2 远程命令执行漏洞的利用 三、系统命令执行3.1 相关函数3.2 系统命令执行漏洞利用 四、命令执行漏洞防御 一、命令…

阿里云生态离线数仓

1. 大数据开发治理平台 DataWorks 功能齐全&#xff1a;10多年大数据建设沉淀完整的平台&#xff0c;覆盖数据开发治理的全生命周期 简单易用&#xff1a;全图形化界面&#xff0c;SQL为主的数据开发方式 安全稳定&#xff1a;双11日千万级任务稳定调度&#x…

一:C语言常见概念

一&#xff1a;C语言常见概念 1.认识C语言&#xff1a; ​ C语言是人和计算机交流的语言 ​ C语言是一门面向过程的语言&#xff0c;而C&#xff0c;Java&#xff0c;Python等是一门面向对象的语言 ​ 软件开发&#xff08;项目&#xff09;&#xff1a;面向过程面向对象 …