当前位置:   article > 正文

Redis的简单应用_redis应用之一

redis应用之一
特征:
  • 键值(key-value)型,value支持多种不同数据结构,功能丰富
  • 单线程,每个命令具备原子性
  • 低延迟,速度快(基于内存、IO多路复用、良好的编码)。
  • 支持数据持久化
  • 支持主从集群、分片集群
  • 支持多语言客户端
适用场景:
  • 对数据高并发的读写

  • 海量数据的读写

  • 对数据高可扩展性的

在这里插入图片描述

不适用:

  • 需要事务支持

  • 基于sql的结构化查询存储,处理复杂的关系,需要即席查询。

  • (用不着sql的和用了sql也不行的情况,请考虑用NoSql**)**

常见通用命令
  • redis-benchmark:性能测试工具,可以在自己本子运行,看看自己本子性能如何

  • redis-check-aof:修复有问题的AOF文件

  • redis-check-dump:修复有问题的dump.rdb文件

  • redis-sentinel:Redis集群使用

  • redis-server:Redis服务器启动命令

  • redis-cli:客户端,操作入口

https://redis.io/commands 中可以查看常用的redis命令

  • KEYS:查看符合模板的所有key
  • DEL:删除一个指定的key
  • EXISTS:判断key是否存在
  • EXPIRE:给一个key设置有效期,有效期到期时该key会被自动删除
  • TTL:查看一个KEY的剩余有效期
  • dbsize查看当前数据库的key的数量
  • flushdb清空当前库
  • flushall通杀全部库

通过help [command] 可以查看一个命令的具体用法

key的结构设计

Redis的key允许有多个单词形成层级结构,多个单词之间用’:'隔开,格式如下:

在这里插入图片描述

这个格式并非固定,也可以根据自己的需求来删除或添加词条。

例如我们的项目名称叫 heima,有user和product两种不同类型的数据,我们可以这样定义key:

  • user相关的key:heima:user:1

  • product相关的key:heima:product:1

五大数据类型

String

String类型,也就是字符串类型,是Redis中最简单的存储类型。

其value是字符串,不过根据字符串的格式不同,又可以分为3类:

  • string:普通字符串

  • int:整数类型,可以做自增、自减操作

  • float:浮点类型,可以做自增、自减操作

不管是哪种格式,底层都是字节数组形式存储,只不过是编码方式不同。字符串类型的最大空间不能超过512m

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不存在,否则不执行

  • SETEX:添加一个String类型的键值对,并且指定有效期

Hash类型

又称为散列,value是一个无需字典,类似于Java中的HashMap结构

Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD:

例如:

KEYVALUE
fieldvalue
heima:user:1nameJack
age21
heima:user:2nameRose
age18

hash常见命令

  • HSET key field value:添加或者修改hash类型key的field的值

  • HGET key field:获取一个hash类型key的field的值

  • HMSET:批量添加多个hash类型key的field的值

  • HMGET:批量获取多个hash类型key的field的值

  • HGETALL:获取一个hash类型的key中的所有的field和value

  • HKEYS:获取一个hash类型的key中的所有的field

  • HVALS:获取一个hash类型的key中的所有的value

  • HINCRBY:让一个hash类型key的字段值自增并指定步长

  • HSETNX:添加一个hash类型的key的field值,前提是这个field不存在,否则不执行

List类型

Redis中的List类型与Java中的LinkedList类似,可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索。

特征也与LinkedList类似:

  • 有序

  • 元素可以重复

  • 插入和删除快

  • 查询速度一般
    在这里插入图片描述

常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等。

常见命令

  • LPUSH key element … :向列表左侧插入一个或多个元素

  • LPOP key:移除并返回列表左侧的第一个元素,没有则返回nil

  • RPUSH key element … :向列表右侧插入一个或多个元素

  • RPOP key:移除并返回列表右侧的第一个元素

  • LRANGE key star end:返回一段角标范围内的所有元素

  • BLPOP和BRPOP:与LPOP和RPOP类似,只不过在没有元素时等待指定时间,而不是直接返回nil

Set

Redis的Set结构与Java中的HashSet类似,可以看做是一个value为null的HashMap。因为也是一个hash表,因此具备与HashSet类似的特征:

  • 无序
  • 元素不可重复
  • 查找快
  • 支持交集、并集、差集等功能

常见命令

  • SADD key member … :向set中添加一个或多个元素
  • SREM key member … : 移除set中的指定元素
  • SCARD key: 返回set中元素的个数
  • SISMEMBER key member:判断一个元素是否存在于set中
  • SMEMBERS:获取set中的所有元素
  • lSADD key member … :向set中添加一个或多个元素
  • SREM key member … : 移除set中的指定元素
  • SCARD key: 返回set中元素的个数
  • SISMEMBER key member:判断一个元素是否存在于set中
  • SMEMBERS:获取set中的所有元素
  • SINTER key1 key2 … :求key1与key2的交集
SorterSet(Zset)

Redis的SortedSet是一个可排序的set集合,与Java中的TreeSet有些类似,但底层数据结构却差别很大。SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加 hash表。

  1. hash,hash的作用就是关联元素value和权重score,保障元素value的唯一性,可以通过元素value找到相应的score值。

  2. 跳跃表,跳跃表的目的在于给元素value排序,根据score的范围获取元素列表。

跳跃表:

​ 有序集合在生活中比较常见,例如根据成绩对学生排名,根据得分对玩家排名等。对于有序集合的底层实现,可以用数组、平衡树、链表等。数组不便元素的插入、删除;平衡树或红黑树虽然效率高但结构复杂;链表查询需要遍历所有效率低。Redis采用的是跳跃表。跳跃表效率堪比红黑树,实现远比红黑树简单。

2、实例

对比有序链表和跳跃表,从链表中查询出51

(1) 有序链表

在这里插入图片描述

要查找值为51的元素,需要从第一个元素开始依次查找、比较才能找到。共需要6次比较。

(2) 跳跃表

在这里插入图片描述

从第2层开始,1节点比51节点小,向后比较。

21节点比51节点小,继续向后比较,后面就是NULL了,所以从21节点向下到第1层

在第1层,41节点比51节点小,继续向后,61节点比51节点大,所以从41向下

在第0层,51节点为要查找的节点,节点被找到,共查找4次。

从此可以看出跳跃表比有序链表效率要高

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即可

基于jedis在Java中操作redis

Jedis的官网地址: https://github.com/redis/jedis

使用步骤

Jedis使用的基本步骤:

1.引入依赖

2.创建Jedis对象,建立连接

3.使用Jedis,方法名与Redis命令一致

4.释放资源

  1. 导入依赖

    <**dependency**> <**groupId**>redis.clients</**groupId**> <**artifactId**>jedis</**artifactId**> <**version**>3.7.0</**version**> </**dependency**>

  2. 建立连接

    @BeforeEach
    void setUp(){
    	//建立连接
        jedis = new Jedis("192.168.150.101", 6379);
        //设置密码
        jedis.auth("123321");
        //选择库
        jedis.select(0);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  3. 测试string

    @Test
    void testString(){
    	// 插入数据,方法名称就是redis命令名称,非常简单
    	String result = jedis.set("name", "张三");
    	System.out.println("result = " + result); 
    	// 获取数据
    	String name = jedis.get("name");
    	System.out.println("name = " + name);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  4. 释放资源

    @AfterEach
    void tearDown(){
    	//释放资源
    	if(jedis != null){
    		jedis.close();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

jedis连接池

Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此我们推荐使用Jedis连接池代替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, "192.168.150.101", 6379,
                                  1000, "123321");
    }
    // 获取Jedis对象
    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

SpringDataRedis

简介:

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis,

官网地址:https://spring.io/projects/spring-data-redis

  • 提供了对不同Redis客户端的整合(Lettuce和Jedis)

  • 提供了RedisTemplate统一API来操作Redis

  • 支持Redis的发布订阅模型

  • 支持Redis哨兵和Redis集群

  • 支持基于Lettuce的响应式编程

  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化

  • 支持基于Redis的JDKCollection实现

不同数据类型对应的操作api
API返回值类型说明
redisTemplate.opsForValue()ValueOperations操作String类型数据
redisTemplate.opsForHash()HashOperations操作Hash类型数据
redisTemplate.opsForList()ListOperations操作List类型数据
redisTemplate.opsForSet()SetOperations操作Set类型数据
redisTemplate.opsForZSet()ZSetOperations操作SortedSet类型数据
redisTemplate通用的命令
使用步骤

1.引入spring-boot-starter-data-redis依赖

2.在application.yml配置Redis信息

3.注入RedisTemplate

  1. 引入依赖

    <!--Redis依赖-->
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!--连接池依赖-->
    <dependency>
    	<groupId>org.apache.commons</groupId>
    	<artifactId>commons-pool2</artifactId>
    </dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  2. 配置文件

    spring:
    	redis:
        	host: 192.168.150.101
        	port: 6379
        	password: 123321
            lettuce:
            	pool:
            	max-active: 8 # 最大连接
                max-idle: 8 # 最大空闲连接
                min-idle: 0 # 最小空闲连接
                max-wait: 100 # 连接等待时间
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  3. 注入并测试

    @SpringBootTest
    public class RedisTest {
        @Autowired
        private RedisTemplate redisTemplate;
        @Test
        void testString() { 
            // 插入一条string类型数据
            redisTemplate.opsForValue().set("name", "李四");
            // 读取一条string类型数据
            Object name = redisTemplate.opsForValue().get("name");
            System.out.println("name = " + name);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
序列化方式

RedisTemplate可以接收任意Object作为值写入Redis,但是写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:

在这里插入图片描述

他的可读性差、内存占用较大

可以通过定义工厂中的RedisTemplate的序列方式

@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException 
{
	// 创建Template
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
    // 设置连接工厂
    redisTemplate.setConnectionFactory(redisConnectionFactory);
    // 设置序列化工具
    GenericJackson2JsonRedisSerializer jsonRedisSerializer = 
					new GenericJackson2JsonRedisSerializer();
    // key和 hashKey采用 string序列化
    redisTemplate.setKeySerializer(RedisSerializer.string()); 
    redisTemplate.setHashKeySerializer(RedisSerializer.string());
    // value和 hashValue采用 JSON序列化
    redisTemplate.setValueSerializer(jsonRedisSerializer);
    redisTemplate.setHashValueSerializer(jsonRedisSerializer);
    return redisTemplate;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

使用 @Configuration 注解将 RedisConfig 类定义为配置类,使用 @Bean 注解将 redisTemplate 方法注册为 Bean 对象。

在上面配置类的方法中,创建了一个 JSON 序列化工具叫作 GenericJackson2JsonRedisSerializer(),这个类需要一个 Jackson 依赖,因此还需要在 pom 文件中引入依赖:

<!--Jackson 依赖-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

但是为了在反序列化的过程中,得知对象的类型,但是如图在存储时将class类型写入了redis,造成了额外的内存浪费

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gBP7bOhz-1655105675341)(C:\Users\86186\AppData\Roaming\Typora\typora-user-images\image-20220612145354131.png)]

StringRedisTemple进行序列化

Spring默认提供了一个StringRedisTemplate类,它的key和value的序列化方式默认就是String方式。省去了我们自定义RedisTemplate的过程:

  • 为了节省内存空间,我们并不会使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。
  • 但是当需要存储Java对象时,手动完成对象的序列化和反序列化。
@Autowired
private StringRedisTemplate stringRedisTemplate;
// JSON工具
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testStringTemplate() throws JsonProcessingException {
	// 准备对象
	User user = new User("虎哥", 18);
    // 手动序列化
    String json = mapper.writeValueAsString(user);
    // 写入一条数据到redis
    stringRedisTemplate.opsForValue().set("user:200", json); 
    // 读取数据
    String val = stringRedisTemplate.opsForValue().get("user:200");
    // 反序列化
    User user1 = mapper.readValue(val, User.class);    System.out.println("user1 = " + user1);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/682827
推荐阅读
相关标签
  

闽ICP备14008679号