本篇文章是参阅 黑马程序员Redis入门到实战教程,全面透析redis底层原理 整理的二刷笔记 —— 备战 2022秋招 —— 继续加油努力!!!
官方命令地址:Commands | Redis
可以通过下列命令快速查看使用说明
127.0.0.1:6379> help
redis-cli 6.2.6
To get help about Redis commands type:
"help @" to get a list of commands in <group>
"help " for help on
"help " to get a list of possible help topics
"quit" to exit
To set redis-cli preferences:
":set hints" enable online hints
":set nohints" disable online hints
Set your preferences in ~/.redisclirc
1️⃣ KEYS : 查看符合模板的所有 key——不建议在生产环境设备上使用
可以通过 help [command]
可以查看一个命令的具体用法,例如:
127.0.0.1:6379> help KEYS
KEYS pattern
summary: Find all keys matching the given pattern
since: 1.0.0
group: generic
Supported glob-style patterns:
h?llo
matches hello
, hallo
and hxllo
h*llo
matches hllo
and heeeello
h[ae]llo
matches hello
and hallo,
but not hillo
h[^e]llo
matches hallo
, hbllo
, … but not hello
h[a-b]llo
matches hallo
and hbllo
Examples
redis:6379> MSET firstname Jack lastname Stuntman age 35
"OK"
redis:6379> KEYS *name*
1) "firstname"
2) "lastname"
redis:6379> KEYS a??
1) "age"
redis:6379> KEYS *
1) "firstname"
2) "age"
3) "lastname"
redis:6379>
2️⃣ DEL :删除指定的KEY —— 也可以删除多个 KEY
help
127.0.0.1:6379> help DEL
DEL key [key ...]
summary: Delete a key
since: 1.0.0
group: generic
Removes the specified keys. A key is ignored if it does not exist.
Example
redis:6379> SET key1 "Hello"
"OK"
redis:6379> SET key2 "World"
"OK"
redis:6379> DEL key1 key2 key3
(integer) 2
redis:6379>
3️⃣ EXISTS:判断对应的 KEY 是否存在
help
127.0.0.1:6379> help EXISTS
EXISTS key [key ...]
summary: Determine if a key exists
since: 1.0.0
group: generic
The user should be aware that if the same existing key is mentioned in the arguments multiple times, it will be counted multiple times. So if somekey
exists, EXISTS somekey somekey
will return 2.
Example
redis:6379> SET key1 "Hello"
"OK"
redis:6379> EXISTS key1
(integer) 1
redis:6379> EXISTS nosuchkey
(integer) 0
redis:6379> SET key2 "World"
"OK"
redis:6379> EXISTS key1 key2 nosuchkey
(integer) 2
redis:6379>
4️⃣ EXPIRE:给一个 key 设置有效期,有效期到期时该 KEY 会被自动删除
EXPIRE KEY seconds [NX|XX|GT|LT]
help
127.0.0.1:6379> help EXPIRE
EXPIRE key seconds
summary: Set a key's time to live in seconds
since: 1.0.0
group: generic
The EXPIRE
command supports a set of options:
NX
– Set expiry only when the key has no expiryXX
– Set expiry only when the key has an existing expiryGT
– Set expiry only when the new expiry is greater than current oneLT
– Set expiry only when the new expiry is less than current oneExample
redis:6379> SET mykey "Hello"
"OK"
redis:6379> EXPIRE mykey 10
(integer) 1
redis:6379> TTL mykey
(integer) 10
redis:6379> SET mykey "Hello World"
"OK"
redis:6379> TTL mykey
(integer) -1
redis:6379> EXPIRE mykey 10 XX
(integer) 0
redis:6379> TTL mykey
(integer) -1
redis:6379> EXPIRE mykey 10 NX
(integer) 1
redis:6379> TTL mykey
(integer) 10
redis:6379>
5️⃣ TTL:查看一个 KEY 的剩余有效期
help
127.0.0.1:6379> help TTL
TTL key
summary: Get the time to live for a key
since: 1.0.0
group: generic
Starting with Redis 2.8 the return value in case of error changed:
-2
if the key does not exist.-1
if the key exists but has no associated expire.Example
redis:6379> SET mykey "Hello"
"OK"
redis:6379> EXPIRE mykey 10
(integer) 1
redis:6379> TTL mykey
(integer) 10
常用命令
1️⃣ SET:添加或者修改已经存在的一个String类型的键值对
2️⃣ GET:根据 KEY 获取 String 类型的 value
3️⃣ MSET:批量添加多个 String 类型的键值对
4️⃣ MGET:根据多个 KEY 获取多个 String 类型的 value
5️⃣ INCR:让一个整型的 KEY 自增 1
6️⃣ INCRBY:让一个整型的 KEY 自增并指定步长
7️⃣ INCRBYFLOAT:让一个浮点类型的数字自增并指定步长
8️⃣ SETNX:添加一个 String 类型的键值对,前提是这个 KEY 不存在,否则不执行
9️⃣ SETEX:添加一个 String类型的键值对,并且指定有效期
非常用命令
1️⃣ SUBSTR:根据 KEY 获取 String 指定范围的 subString
2️⃣ STRLEN:根据 KEY 获取 String 字符串的长度
3️⃣ GETRANGE:用于获取存储在指定 key 中的子字符串。
4️⃣ GETSET:返回之前的值,在设置新的值。
5️⃣ GETDEL:返回之前的值,然后删除对应的 KEY - VALUE
举个
常用命令
1️⃣ HSET:添加 或者 修改 hash 类型 key 的 field 的值。
HSET key field value [field value ...]
2️⃣ HGET :获取一个 hash 类型 key 的 field 的值。
3️⃣ HMSET:批量添加多个 hash 类型 key 的 field 的值
4️⃣ HMGET:批量获取多个 hash 类型的 key 中的所有的 field 和 value
5️⃣ HGETALL:获取一个 hash 类型的 key 中的所有的 field和value
6️⃣ HKEYS:获取一个 hash 类型的 key 中的所有的 field
7️⃣ HVALS:获取一个 hash 类型的 key 中的所有的 value
8️⃣ HINCRBY:让一个 hash 类型 key 的字段值 自增并指定步长
9️⃣ HSETNX:添加一个 hash 类型的 key 的 field 值,前提是这个 field 不存在,否则不执行。
非常用命令
1️⃣ HDEL :删除指定 hash 类型的key 中的一个或者多个 field
2️⃣ HLEN:获取指定 hash 类型的 key 中的 field 个数
常见命令
1️⃣ LPUSH key element … :向列表的左侧插入一个或者多个元素。
2️⃣ LPOP key:移除并返回列表左侧的第一个元素,没有则返回null。
3️⃣ RPUSH key element … :向列表右侧插入一个或多个元素。
4️⃣ RPOP key :移除并返回列表右侧的第一个元素
5️⃣ LRANGE key start end:返回一段角标范围内的所有元素。
6️⃣ BLPOP 和 BRPOP:与LPOP 和 RPOP 类似,只不过在没有元素时等待指定时间,而不是直接返回 null。
非常用命令
1️⃣ RPOPLPUSH:移除源List中的最后一个元素,将其插入到目标List当中。
help
127.0.0.1:6379> help RPOPLPUSH
RPOPLPUSH source destination
summary: Remove the last element in a list, prepend it to another list and return it
since: 1.2.0
group: list
Example
redis:6379> RPUSH mylist "one"
(integer) 1
redis:6379> RPUSH mylist "two"
(integer) 2
redis:6379> RPUSH mylist "three"
(integer) 3
redis:6379> RPOPLPUSH mylist myotherlist
"three"
redis:6379> LRANGE mylist 0 -1
1) "one"
2) "two"
redis:6379> LRANGE myotherlist 0 -1
1) "three"
课后问题
❓ 如何利用 List 结构模拟一个栈
❓ 如何利用 List 结构模拟一个队列
❓ 如何利用 List 结构模拟一个阻塞队列
常用命令
1️⃣ SADD key member … : 向 set 中添加一个或者多个元素。
2️⃣ SREM key member …:移除 set 中的指定元素。
3️⃣ SCARD key : 返回 set 中元素的个数。
4️⃣ SISMEMBER key member :判断一个元素是否存在于 set 中
5️⃣ SMEMBERS : 显示 set 集合中的所有元素。
常用操作命令
1️⃣ SDIFF key [key] : key 所对应集合元素之差
2️⃣ SDIFFSTORE destination key [key] :和上述命令作用是一样的,不过会创建一个新的键为key的 set 用于存储结果集,如果这个结果集存在则会被覆盖。
3️⃣ SINTER key [key]:用于筛选 交集 集合操作
4️⃣ SINTERSTORE destination key [key] :和上述命令作用是一样的,不过会创建一个新的键为key的 set 用于存储结果集,如果这个结果集存在则会被覆盖。
5️⃣ SSCAN key cursor [MATCH pattern] [COUNT count]:迭代优化返回 set 数据集
将下列数据用 Redis 的 set 集合来存储
127.0.0.1:6379> SADD user:zhangsan:friends lisi wangwu zhaoliu
(integer) 3
127.0.0.1:6379> SMEMBERS user:zhangsan:friends
1) "zhaoliu"
2) "wangwu"
3) "lisi"
127.0.0.1:6379> SADD user:lisi:friends wangwu mazi ergou
(integer) 3
127.0.0.1:6379> SMEMBERS user:lisi:friends
1) "mazi"
2) "wangwu"
3) "ergou"
计算 张三的好友有几人
127.0.0.1:6379> SINTER user:zhangsan:friends user:lisi:friends
1) "wangwu"
计算张三和李四有哪些共同好友
127.0.0.1:6379> SINTER user:zhangsan:friends user:lisi:friends
1) "wangwu"
查询哪些人是张三的好友 却不是 李四的好友
127.0.0.1:6379> SDIFF user:zhangsan:friends user:lisi:friends
1) "zhaoliu"
2) "lisi"
查询张三和李四的好友总共有哪些人
127.0.0.1:6379> SUNION user:zhangsan:friends user:lisi:friends
1) "lisi"
2) "mazi"
3) "ergou"
4) "zhaoliu"
5) "wangwu"
判断李四是否是张三的好友
127.0.0.1:6379> SISMEMBER user:zhangsan:friends lisi
(integer) 1
判断张三是不是李四的好友
127.0.0.1:6379> SISMEMBER user:lisi:friends zhangsan
(integer) 0
将 李四 从张三的好友列表中移除
127.0.0.1:6379> SREM user:zhangsan:friends lisi
(integer) 1
常见命令
1️⃣ ZADD key score member:添加一个或多个元素到 sorted set
2️⃣ ZREM key member:删除 sorted set 中的一个指定元素
3️⃣ ZSCORE key member :获取sorted set 中的指定元素的 score 值
4️⃣ ZRANK key member :获取 sorted set 中指定元素的排名。
5️⃣ ZCARD key :获取 sorted set 中的元素个数
6️⃣ ZCOUNT key min max:统计 score 值在给定范围内的元素个数。
7️⃣ ZINCRBY key increment member:让 sorted set 中的指定元素自增,步长为指定的 increment 值。
8️⃣ ZRANGE key min max:按照 score 排序后,获取指定排名范围内的元素
9️⃣ ZRANGEBYSCORE key min max:按照 score排序后,获取指定 score 范围内的元素。
ZDIFF 、ZINTER、ZUNION:求差集、交集、并集。
注意点:
所有排名默认都是升序,如果要降序则在命令的Z 后面添加REV (reverse)即可
将班级的下列学生得分存入 Redis 的 SortedSet 中:
127.0.0.1:6379> ZADD student 85 Jack 82 Rose 95 Tom 78 Jerry 92 Amy 76 Miles
(integer) 6
127.0.0.1:6379> ZSCAN student 0
1) "0"
2) 1) "Miles"
2) "76"
3) "Jerry"
4) "78"
5) "Rose"
6) "82"
7) "Jack"
8) "85"
9) "Amy"
10) "92"
11) "Tom"
12) "95"
删除 Tom 同学
127.0.0.1:6379> zrem student Tom
(integer) 1
获取 Amy 同学的分数
127.0.0.1:6379> ZSCORE student Amy
"92"
获取 Rose 同学的排名
127.0.0.1:6379> ZREVRANK student Rose
(integer) 2
查询 80 分以下的同学有几个学生
127.0.0.1:6379> ZCOUNT student 0 80
(integer) 2
给 Amy 同学 加 2 分
127.0.0.1:6379> ZINCRBY student 2 Amy
"94"
查出成绩前3名的同学
127.0.0.1:6379> ZREVRANGE student 0 2
1) "Amy"
2) "Jack"
3) "Rose"
查询成绩 80 分以下的所有同学
127.0.0.1:6379> ZRANGEBYSCORE student 0 80
1) "Miles"
2) "Jerry"
Clients | Redis
Jedis
以 Redis 命令作为方法名称,学习成本低,简单实用。但是 Jedis 实例是线程不安全的,多线程环境需要基于连接池来使用。
redis/jedis: Redis Java client designed for performance and ease of use. (github.com)
步骤一:引入相关的依赖
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
<version>3.7.0version>
dependency>
步骤二:建立连接进行测试
/***
* @author: Alascanfu
* @date : Created in 2022/7/3 20:51
* @description: RedisConnection
* @modified By: Alascanfu
**/
public class TestConnection {
private final static String REDIS_HOST = "192.168.56.103";
private final static Integer REDIS_PORT = 6379 ;
public static Jedis getJedisConnection(){
return new Jedis(REDIS_HOST,REDIS_PORT);
}
public static boolean closeJedisConnection(Jedis jedisConnection){
if (jedisConnection != null){
jedisConnection.close();
return true ;
}
throw new RuntimeException("JedisConnection 已经关闭 请勿二次关闭!");
}
public static void main(String[] args) {
// 创建 Redis 连接
Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT);
// 选择 Redis 的库
jedis.select(0);
// 测试 Redis 连接
String ping = jedis.ping();
System.out.println(ping);
}
}
测试String
@Test
public void testString(){
Jedis jedisConnection = getJedisConnection();
String result = jedisConnection.set("name" , "Alascanfu");
System.out.println("result => " + result);
String name = jedisConnection.get("name");
System.out.println("name => " + name);
System.out.println(jedisConnection.del("name") == 0 ? "No" : "Yes");
closeJedisConnection(jedisConnection);
}
测试 hash
@Test
public void testHash(){
Jedis jedisConnection = getJedisConnection();
jedisConnection.hset("www.alascanfu.com:user","name","Alascanfu");
jedisConnection.hset("www.alascanfu.com:user","age","21");
jedisConnection.hset("www.alascanfu.com:user","sex","Man");
Map<String, String> map = jedisConnection.hgetAll("www.alascanfu.com:user");
System.out.println(map);
System.out.println(jedisConnection.del("www.alascanfu.com:user") == 0 ? "No" : "Yes");
closeJedisConnection(jedisConnection);
}
Jedis 本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此我们推荐大家使用 Jedis 连接池代替 Jedis 的连接方式
JedisConnectionFactory
/***
* @author: Alascanfu
* @date : Created in 2022/7/3 21:45
* @description: Jedis Connection Factory
* @modified By: Alascanfu
**/
public class JedisConnectionFactory {
private static final String REDIS_HOST = "192.168.56.103";
private static final Integer REDIS_PORT = 6379 ;
private static final JedisPool jedisPool;
static {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 设置最大连接数
jedisPoolConfig.setMaxTotal(8);
// 设置最大空闲连接数
jedisPoolConfig.setMaxIdle(8);
// 设置最小空闲连接数
jedisPoolConfig.setMinIdle(0);
// 设置最长等待时间
jedisPoolConfig.setMaxWaitMillis(200);
// 创建 jedis 连接池
jedisPool = new JedisPool(jedisPoolConfig,REDIS_HOST,REDIS_PORT,1000);
}
// 通过 Jedis 线程池 获取 Jedis 连接
private static Jedis getJedis(){
return jedisPool.getResource();
}
}
Lettuce
Lettuce 是基于 Netty 实现的,支持同步、异步和响应编程方式,并且是线程安全的。支持 Redis 的哨兵模式、集群模式和管道模式。
Redisson 是 一个基于 Redis 实现的分布式、可伸缩的 Java 数据结构集合。包含了诸如 Map 、Queue 、Lock、Semaphore、AtomicLong 等强大功能。
SpringData Redis 中提供了 RedisTemplate 工具类,其中封装了各种对 Redis 的操作。并将不同类型的操作 API 封装到不同的类型当中
API | 返回值类型 | 说明 |
---|---|---|
redisTemplate.opsForValue() |
ValueOperations | 操作 String 类型数据 |
redisTemplate.opsForHash() |
HashOperations | 操作 Hash 类型数据 |
redisTemplate.opsForList() |
ListOperations | 操作 List 类型数据 |
redisTemplate.opsForSet() |
SetOperations | 操作 Set 类型数据 |
redisTemplate.opsForZSet() |
ZSetOperations | 操作 Sorted Set类型数据 |
redisTemplate |
通用的命令 |
步骤一:引入相关依赖,SpringBoot已经提供了对 SpringDataRedis 的支持了
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-pool2artifactId>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.13.3version>
dependency>
步骤二:配置文件
pom.xml
spring:
redis:
host: 192.168.56.103
port: 6379
lettuce:
pool:
max-idle: 8 # 最大空闲连接
min-idle: 0 # 最小空闲连接
max-active: 8 # 最大连接数
max-wait: 200 # 连接最长等待时间
步骤三:测试
@SpringBootTest
class SpringdataRedisApplicationTests {
@Autowired
private RedisTemplate redisTemplate ;
@Test
public void testString(){
// 写入一条 String 数据
redisTemplate.opsForValue().set("www.alascanfu.com:user","Alascanfu");
// 获取一条 String 数据
String str = (String) redisTemplate.opsForValue().get("www.alascanfu.com:user");
System.out.println(str);
Boolean delete = redisTemplate.delete("www.alascanfu.com:user");
System.out.println(delete);
}
}
SpringDataRedis 的序列化方式
添加配置 RedisConfig
/***
* @author: Alascanfu
* @date : Created in 2022/7/3 22:43
* @description: Redis Config
* @modified By: Alascanfu
**/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String , Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws Exception{
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer
= new GenericJackson2JsonRedisSerializer();
// key 和 hashKey 采用 String 序列化
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setHashKeySerializer(RedisSerializer.string());
// value 和 hashValue 采用 JSON 序列化
redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
return redisTemplate;
}
}
测试
@Test
public void testStringObject(){
redisTemplate.opsForValue().set("user:201901094106",new User(201901094106L,"Alascanfu",21));
User user = (User) redisTemplate.opsForValue().get("user:201901094106");
System.out.println(user);
}
此时就不会出现乱码的错误啦
小付的方法
@Test
public void testStringObject() throws JsonProcessingException {
User alascanfu = new User(201901094106L, "Alascanfu", 21);
String body = objectMapper.writeValueAsString(alascanfu);
redisTemplate.opsForValue().set("user:201901094106",body);
body = (String) redisTemplate.opsForValue().get("user:201901094106");
User user = objectMapper.readValue(body, User.class);
System.out.println(user);
}
老师的方法
/***
* @author: Alascanfu
* @date : Created in 2022/7/3 23:31
* @description: JsonUtil 工具类用于 将后端数据以 Json 方式发送给所需方,
* 以及将获取的Json 数据转换为 对应的类型
* @modified By: Alascanfu
**/
@Slf4j
@Component
public class JsonUtil {
@Autowired
private static ObjectMapper objectMapper ;
public static String toJson(Object object){
try {
objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null ;
}
public static Object FromJsonTo(String body , Class classType){
try {
return objectMapper.readValue(body,classType);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null ;
}
}