入门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) 0


127.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 -1
 1) "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 skey
 1) "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) 0


127.0.0.1:6379> smembers skey
 1) "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) 13

127.0.0.1:6379> smembers skey1
 1) "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 skey1
 1) "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 skey4
 1) "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) 1


127.0.0.1:6379> smembers skey1
 1) "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) 1

127.0.0.1:6379> smembers skey4
 1) "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 skey4
 1) "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 skey1
 1) "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 skey4
 1) "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 skey4
 1) "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 WITHSCORES
 1) "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 WITHSCORES
 1) "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 WITHSCORES
 1) "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 WITHSCORES
 1) "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 WITHSCORES
 1) "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) 1

127.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;

    @BeforeEach
    void setUp() {
        //1.建立连接
        jedis = new Jedis("127.0.0.1", 6379);
        //2.设置密码(如果Reis有设置密码的话,必须手动设置密码,否则无须指定密码)
        // jedis.auth("123456");
        //3.选择库
        jedis.select(0);
    }

    @Test
    void 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);
    }

    @Test
    void 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) {
            //获取所有的key
            Set<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()));
        }
    }

    //执行后
    @AfterEach
    void 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);
        // 设置最长等待时间ms
        jedisPoolConfig.setMaxWaitMillis(200);
        jedisPool = new JedisPool(jedisPoolConfig, "127.0.0.1X", 6379, 1000);
    }

    public static Jedis getJedis() {
        return jedisPool.getResource();
    }
}

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

    @BeforeEach
    void 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.1
      port: 6379
      lettuce:
        pool:
          max-active: 8
          max-idle: 8
          min-idle: 0
          max-wait: 100ms

4.测试:使用RedisTemplate操作Redis

@SpringBootTest
class SpringRedisApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void 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 {

    @Bean
    public 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转成对象

    @Test
    void 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 {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Test
    void 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();

    @Test
    void 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);
    }

    @Test
    void 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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[仅供学习,禁止用于违法]编写一个程序来手动设置Windows的全局代理开或关,实现对所有网络请求拦截和数据包捕获(抓包或VPN的应用)

文章目录 介绍一、实现原理二、通过注册表设置代理2.1 开启代理2.2 关闭代理2.3 添加代理地址2.4 删除代理设置信息 三、代码实战3.1 程序控制代理操作控制3.1.1 开启全局代理3.1.2 添加代理地址3.1.3 关闭代理开关3.1.4 删除代理信息 3.2 拦截所有请求 介绍 有一天突发奇想&am…

Avaya Aura Device Services 任意文件上传漏洞复现

0x01 产品简介 Avaya Aura Device Services是美国Avaya公司的一个应用软件。提供一个管理 Avaya 端点功能。 0x02 漏洞概述 Avaya Aura Device Services 系统PhoneBackup接口处存在任意文件上传漏洞&#xff0c;攻击者可绕过验证上传任意文件获取服务器权限。 0x03 影响范围…

代码随想录算法训练营第四十天|139.单词拆分,多重背包,背包问题

139. 单词拆分 - 力扣&#xff08;LeetCode&#xff09; 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。 注意&#xff1a;不要求字典中出现的单词全部都使用&#xff0c;并且字典中的单词可以重复使用。 示例 1&a…

【C++】输入输出流 ⑤ ( cin 输入流对象 | cin.ignore() 函数 | cin.peek() 函数 | cin.putback() 函数 )

文章目录 一、cin.ignore() 函数1、cin.ignore() 函数简介2、cin.ignore() 函数原型3、代码示例 - cin.ignore() 函数 二、cin.peek() 函数1、cin.peek() 函数简介2、代码示例 - cin.peek() 三、cin.putback() 函数1、cin.putback() 函数简介2、代码示例 - cin.putback() 一、c…

智能优化算法应用:基于粒子群算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于粒子群算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于粒子群算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.粒子群算法4.实验参数设定5.算法结果6.参考文…

IntelliJ IDEA创建一个Maven项目

在IDEA中创建Maven项目&#xff0c;前提是已经安装配置好Maven环境 。 本文主要使用的是IntelliJ IDEA 2022.2.1 (Community Edition) 1.创建一个新project:File>Project 2.修改Maven配置&#xff1a;File>Settings>搜索maven 创建好的工程如下&#xff1a; src/main…

探索 PDM:新一代的 Python 包管理工具

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com PDM&#xff08;Python Development Master&#xff09;是一款新一代的 Python 包管理工具&#xff0c;旨在提供更为现代化、可靠且灵活的解决方案。与传统的 pip 和 Poetry 相比&#xff0c;PDM 在依赖版本管理…

点云 ros PointCloud2格式与livox CustomMsg格式介绍

点云 ros PointCloud2格式与livox CustomMsg格式介绍 PointCloud2 点云格式livox CustomMsg 点云格式 PointCloud2 点云格式 PointCloud2 是ros的一种点云格式 具体官方数据 http://docs.ros.org/en/jade/api/sensor_msgs/html/msg/PointCloud2.html std_msgs/Header header…

Qt/C++音视频开发57-切换音视频轨道/切换节目流/分别切换音频视频轨道

一、前言 对各种音视频文件格式的支持&#xff0c;是一个播放器的基础功能。一般的音视频文件只有1路流&#xff0c;比如音频文件只有1路音频流&#xff0c;视频文件只有1路音频1路视频流&#xff0c;实践过程中发现&#xff0c;还有一种ts格式的文件&#xff0c;可能有多路流…

基于SSM的成绩管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

qt:QMessageBox的常见用法

头文件&#xff1a;#include <QMessageBox> Infomation消息对话框 初始化格式&#xff1a; QMessageBox * msgBox new QMessageBox(QMessageBox::Information, "我是标题", "我是提示文字", 按钮); 按钮可以是以下取值&#xff0c;会在按键上显示…

C++中STL的容器vector

文章目录 什么是vectorvector与普通顺序表不同的点 vector的成员函数operatoroperator[]begin与end与iteratorsize()capacityresizeemptyreservepush_backpop_backinserteraseswapclear成员变量 总结 什么是vector vector&#xff1a;是数据结构里面的顺序表&#xff0c;开辟一…

JVM类加载器ClassLoader的源码分析

1、ClassLoader与现有类加载器的关系 ClassLoader与现有类加载器的关系&#xff1a; ClassLoader是一个抽象类。如果我们给定了一个类的二进制名称&#xff0c;类加载器应尝试去定位或生成构成定义类的数据。一种典型的策略是将给定的二进制名称转换为文件名&#xff0c;然后去…

LeetCode Hot100 39.组合总数

题目&#xff1a; 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。 candidates 中的 同一个 数字可以 无限…

[报错]记录IDEA远程开发报错:java: Cannot run program.....

报错内容 IDEA在进行远程开发的时候报错&#xff0c;内容如下&#xff1a; java: Cannot run program "/usr/lib/jvm/java-1.8.0-openjdk-amd64/bin/java" (in directory "/home/jim/.cache/JetBrains/RemoteDev-IU/_home_jim_DevCodes_Github_zfile/compile-…

空中消防员:无人机森林防火应用全面升级

森林是生态系统的重要组成部分&#xff0c;也是人类得以生存的关键。我国森林面积广大&#xff0c;存在火灾频发的困境。提升森林火灾防控能力是维护生态平衡、保护资源和保障人民生命安全的必要步骤。随着无人机技术的发展&#xff0c;其在无人机森林防火中的应用为传统巡查工…

【EI会议征稿中】第三届网络安全、人工智能与数字经济国际学术会议(CSAIDE 2024)

第三届网络安全、人工智能与数字经济国际学术会议&#xff08;CSAIDE 2024&#xff09; 2024 3rd International Conference on Cyber Security, Artificial Intelligence and Digital Economy 第二届网络安全、人工智能与数字经济国际学术会议&#xff08;CSAIDE 2023&…

SpringBoot中的YAML配置文件和日志

与其明天开始&#xff0c;不如现在行动&#xff01; 文章目录 YAML配置文件1 基本语法2 语法细节 日志1 简介2 格式3 级别4 日志保存 &#x1f48e;总结 YAML配置文件 SpringBoot集中化管理配置&#xff1a;application.properties 问题&#xff1a;配置多了以后难阅读和修i该&…

链表OJ—相交链表

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 1、相交链表的题目&#xff1a; 方法讲解&#xff1a; 图文解析&#xff1a; 代码实现&#xff1a; 总结 前言 世上有两种耀眼的光芒&#xff0c;一种是正在升…

电脑中环境变量的设置方法

环境变量是在操作系统中一个具有特定名字的对象&#xff0c;它包含了一个或者多个应用程序所将使用到的信息。例如Windows和DOS操作系统中的path环境变量&#xff0c;当要求系统运行一个程序而没有告诉它程序所在的完整路径时&#xff0c;系统除了在当前目录下面寻找此程序外&a…