欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 名人名企 > 【从0到1学Redis】Redis基础篇

【从0到1学Redis】Redis基础篇

2025/3/16 12:18:41 来源:https://blog.csdn.net/shenqibaobao/article/details/146262997  浏览:    关键词:【从0到1学Redis】Redis基础篇

在这里插入图片描述

Redis通用的命令和数据结构

Redis通用命令

KEYS:查看符合模板的所有key,可以使用通配符*(不建议在生产环境设备上使用)
DEL:删除一个指定的key,返回值为一个integer类型的值,表示删除的数量
EXISTS:判断key是否存在,返回值为一个integer类型的值,表示存在的数量
EXPIRE:给一个key设置有效期,有效期到期时该key会被自动删除
TTL:查看一个KEY的剩余有效期,返回值为一个integer类型的值,-1表示永久有效,-2表示不存在或失效,其它表示存活的秒数

Redis常见数据结构

在这里插入图片描述

String类型

string类型的常见命令

SET:添加或者修改已经存在的一个String类型的键值对
GET:根据key获取String类型的value
MSET:批量添加多个String类型的键值对
MGET:根据多个key获取多个String类型的value
INCR:让一个整型的key自增1
INCRBY:让一个整型的key自增并指定步长,例如:incrby num 2 让num值自增2
INCRBYFLOAT:让一个浮点类型的数字自增并指定步长
SETNX:添加一个String类型的键值对,前提是这个key不存在,否则不执行(等价于set + nx)
SETEX:添加一个String类型的键值对,并且指定有效期(等价于set+ex)

关于key的层级关系,我们可以加:来对key进行分层,如下图,最后我们使用图形化工具,就可以看到在heima层的user层下有两个用户1和用户2

127.0.0.1:6379> set heima:user:1 '{"id":1,"name":"wyt"}'
OK
127.0.0.1:6379> set heima:user:2 '{"id":2,"name":"wyt"}'
OK

Hash类型

Hash类型的value类似于Java中的HashMap,它的value就类似一个无序字典

当我们使用String类型来存储对象序列化后的JSON字符串的时候,我们需要修改其中一个字段的值的时候非常不方便
在这里插入图片描述
但是当我们使用hash类型来存储的时候,hash可以将每个对象的每个字段独立存储,方便操作
在这里插入图片描述
hash的常见命令

HSET key field value:添加或者修改hash类型key的field的值
HGET key field:获取一个hash类型key的field的值
HMSET key field1 value1 field2 value2 ...:批量添加多个hash类型key的field的值
HMGET key field1 field2 ...:批量获取多个hash类型key的field的值
HGETALL key:获取一个hash类型的key中的所有的field和value
HKEYS key:获取一个hash类型的key中的所有的field
HVALS:获取一个hash类型的key中的所有的value
HINCRBY:让一个hash类型key的字段值自增并指定步长,例如,hincrby heima:user:4 age -2 (age自减2)
HSETNX:添加一个hash类型的key的field值,前提是这个field不存在,否则不执行

List类型

Redis的List类型与Java中的LinkedList类似,可以看做是一个双向链表结构,既可以支持正向检索也可以支持反向检索。
特点也与LinkedList类似:有序、元素可重复、插入和删除快、查询速度一般。常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等

List常见命令
LPUSH key element ... :向列表左侧插入一个或多个元素
LPOP num:从左侧开始取,取出并移除num个元素,数量不够就返回nil
RPUSH key element ... :向列表右侧插入一个或多个元素
RPOP num:从右侧开始取,取出并移除num个元素,数量不够就返回nil
LRANGE key star end:返回一段角标范围内的所有元素
BLPOP和BRPOP:与LPOP和RPOP类似,只不过在没有元素时等待指定时间,而不是直接返回nil
备注:左边索引为1,右边依次递增

Set类型

Redis的set结构和Java中的HashSet类似,可以看做是一个value为null的HashMap,因为也是一个Hash表,因此也具备HashSet的特点:无序、元素不可重复、查找快、支持交集、并集、差集等功能。可以用于交友列表显示共同好友的功能

Set数据的常见命令:

SADD key member ...:向set中添加一个或多个元素
SREM key member ... : 移除set中的指定元素
SCARD key: 返回set中元素的个数
SISMEMBER key member:判断一个元素是否存在于set中
SMEMBERS:获取set中的所有元素
SINTER key1 key2 ... :求key1与key2的交集
SDIFF key1 key2 ... :求key1与key2的差集
SUNION key1 key2 ...:求key1和key2的并集

SortedSet类型

Redis的SortedSet是一个可排序的set集合,与Java中的TreeSet有些类似,但底层数据结构却差别很大。SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加 hash表。SortedSet具有的特点:可排序元素、不重复、查询速度快。因为SortedSet的可排序特性,经常被用来实现排行榜这样的功能

SortedSet常用命令:

ZADD key score member:添加一个或多个元素到sorted set ,如果已经存在则更新其score值
ZREM key member:删除sorted set中的一个指定元素
ZSCORE key member : 获取sorted set中的指定元素的score值
ZRANK key member:获取sorted set 中的指定元素的排名
ZCARD key:获取sorted set中的元素个数
ZCOUNT key min max:统计score值在给定范围内的所有元素的个数
ZINCRBY key increment member:让sorted set中的指定元素自增,步长为指定的increment值
ZRANGE key min max:按照score排序后,获取指定排名范围内的元素
ZRANGEBYSCORE key min max:按照score排序后,获取指定score范围内的元素
ZDIFF、ZINTER、ZUNION:求差集、交集、并集
注意:所有的排名默认都是升序,如果要降序则在命令的Z后面添加REV即可

其他的数据类型会放在黑马点评实战项目中介绍使用

Redis的Java客户端

在这里插入图片描述

这里我们平常只用Jedis

Jedis的使用

首先是Maven坐标

 <!--jedis依赖--><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version></dependency><!--junit依赖--><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.7.0</version><scope>test</scope></dependency>

练手

public class test {private Jedis jedis;@BeforeEachpublic void init() {jedis = new Jedis("localhost", 6379);   // 初始加载,先连接Redisjedis.select(0);                        // 选择仓库}@Testpublic void testString() {String result = jedis.set("name", "wyt");System.out.println(result);System.out.println(jedis.get("name"));}@Testpublic void testHashMap() {jedis.hset("user:1","name","jeck");jedis.hset("user:1","age","12");Map<String, String> stringStringMap = jedis.hgetAll("user:1");System.out.println(stringStringMap);}@AfterEachpublic void destroy() {if (jedis != null) {jedis.close();              // 测试结束关闭连接防止内存泄漏}}}

连接池

在平常我们一般不会使用直接连接的方式,而是使用连接池,那么什么是连接池呢,就是在一个容器内,放置了许多连接,多少个连接我们可以进行定义。下面是一些配置名。

  • 最小连接:最小连接数是连接池一直保持的数据连接,可以理解为即使没有连接请求,也会有这么多连接对象存在
  • 最大连接:最大连接数是连接池能申请的最大连接数。如果数据连接请求超过此数,后面的数据连接请求将被加入到等待队列中
  • 最小空闲连接:连接池用于预留的连接对象,当空闲连接小于最小空闲连接时,会另外创建连接,直到空闲连接等于或大于最小空闲连接(一般都会设置为0)
  • 最大空闲连接:连接池用于限制空闲连接对象,当空闲连接大于最大空闲连接时,会将多余的空闲连接销毁
  • 最大等待时间:当连接时间超过了最大等待连接时间,就会放弃等待然后直接抛异常

配置文件

public class JedisConnectionFactory {public static final JedisPool jedisPool;static {JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();// 最大连接数jedisPoolConfig.setMaxTotal(10);// 最大空闲数jedisPoolConfig.setMaxIdle(10);// 最小空闲连接jedisPoolConfig.setMinIdle(0);// 最多等待1000毫秒jedisPoolConfig.setMaxWaitMillis(1000);jedisPool = new JedisPool(jedisPoolConfig, "127.0.0.1", 6379,1000);}public static Jedis getJedis() {return jedisPool.getResource();}
}

SpringBoot整合Redis

这里我们使用Spring Data Redis

在这里插入图片描述
Maven坐标

<dependencies>// Spring Data Redis<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</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>// 连接池<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency>
</dependencies>

~~~~     那么我们为什么非要用连接池呢,首先redis是单线程的,但是当我多个同时连接redis时是不是要排队吗?然后执行命令,和我们执行单个全局连接直接去一个执行redis指令,感觉差不多吗?此言差异,虽然redis是单线程的,但这并不表示使用连接池不能提高效率,只是不能通过多线程的方式提高效率。
~~~~      redis连接池单连接的效能提高很多,要了解为什么redis连接池能够这么大幅的提高性能,就要了解单连接的性能瓶颈在哪里?单线程不是redis的性能瓶颈,对redis而言,有两个性能所在,一个是计算机执行命令的速度,另一个是网络通信性。很显然,执行命令速度不是redis的性能瓶颈,通信才是其瓶颈。据我所知,redis每秒可执行10万次,因此,对于客户端将若干条命令传输给redis服务,命令执行时间和通信时间大概是比等于0,将设以1s举例,几条命令传输时间为40ms,而每秒可执行10万条命令,那么这些命令只是花费1ms来执行,其他39ms时间无事可做,等待下一个命令的到来,其中的间隙,造成redis的闲置。
~~~~      综上,要提高redis的性能,可以降低单位时间内的通信成本,那么连接池就是一个不错的选择。客户端使用连接词+多线程方案,使得redis服务闲置时间降低,极大的提高了服务效率。

配置文件

spring.application.name: SpringBoot_Redis
spring:data:redis:host: 127.0.0.1port: 6379lettuce:pool:max-active: 8max-idle: 8min-idle: 0max-wait: 1000

RedisTemplate的序列化方式

API
在这里插入图片描述

RedisTemplate是SpringDataRedis封装的一个对象,类似于JDBCTemplate,都是一个用来操作数据库中数据的工具类。
RedisTemplate底层默认使用的是JDK序列化器,JDK序列化器是采用ObjectOutputStream实现的,这种实现方式存在缺点:存入的数据可读性差、内存占用较大。

这时候我们可以自定义序列化方式

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

key 用字符串的方式存储,value用json的格式存储
但是以这样的形式存储的对象,占用内存很大,每一次存储都带着@Class

在这里插入图片描述

StringRedisTemplate序列化方式

为了节省内存空间,就不能使用JSON序列化器来处理Value,而是统一使用String序列化器,这样就只能存String类型的key和value,而面对Object类型的value时,就手动完成对象的序列化和反序列化。那么是不是需要我们去重新定义一个RedisTemplate呢?答案是No,Spring默认提供了一个StringRedisTemplate类,它的key和value都默认是采用String序列化的方式

@Test
void testStringRedisTemplate2() throws JsonProcessingException {User user = new User("wyt",12);String json = mapper.writeValueAsString(user);stringRedisTemplate.opsForValue().set("user:101",json);String jsonUser = stringRedisTemplate.opsForValue().get("user:101");User o = mapper.readValue(jsonUser,User.class);System.out.println(o);
}@Test
void testStringRedisTemplate3() throws JsonProcessingException {stringRedisTemplate.opsForHash().put("user:102","name","谷歌");stringRedisTemplate.opsForHash().put("user:102","age","12");Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("user:102");System.out.println(entries);
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词