记录Java学习——Redis篇

  • Redis中的数据是以键值对形式存储的,且二进制安全
  • Redis中默认不支持中文,都是以二进制存储的
  • 要正常显示中文,在登陆客户端时,使用redis-cli --raw命令登录

一、redis的数据结构

  • redis存储的是:key-value格式的数据,其中key都是字符串,value有5种不同的数据结构
    • 字符串类型 string
    • 哈希类型 hash:map格式
    • 列表类型 list:linkedlist格式;支持重复元素
    • 集合类型 set:不允许重复元素
    • 有序集合类型 sortedset:不允许重复元素,且元素有顺序

1. 通用命令

  • 获取键对应的value的类型:type key
  • 判断:exists key
  • 查看所有键:keys *
  • 查找以xx为结尾的键:keys *xx
  • 删除所有键:flushall
  • 查看一个键的过期时间(time to live):ttl key(最后显示-2表示过期)
  • 设置一个键的过期时间:expire key 时间(秒)
  • 设置一个键值对的过期时间:setex key 时间(秒) value

2. 字符串类型 string

  • 添加:set key value
  • 查看:get key
  • 删除:del key

3. 列表类型 list

元素可以重复

可以添加一个元素到列表的头部(左边)或者尾部(右边)

  • 添加:
    • lpush key value:将元素加入列表左表
    • rpush key value:将元素加入列表右表
  • 查看:
    • lrange key start end:范围获取
  • 删除:
    • lpop key:删除列表最左边的元素,并将元素返回
      • lpop key 2:删除最左边两个元素
    • rpop key:删除列表最右边的元素,并将元素返回
    • ltrim key start end:删除列表中指定范围以外的元素
  • 查看列表元素个数
    • llen key
  • 简单的消息队列
    1. lpush命令从列表头部添加一个元素
    2. rpop命令从列表尾部删除一个元素

4. 集合类型 set

元素不可以重复,

元素不具有顺序

  • 添加:
    • sadd key value
  • 查看:
    • smembers key:获取set元素集合中所有元素
  • 删除:
    • srem key value:删除set集合中的某个元素
  • 判断一个元素是否在集合中
    • sismember key value
  • 运算
    • sinter key [key ...]:返回一个集合的全部成员,该集合是所有给定集合的交集。
    • sunion key [key ...]:返回一个集合的全部成员,该集合是所有给定集合的并集。
    • sdiff key [key ...]: 返回所有给定 key 与第一个 key 的差集

5. 有序集合类型 sortedset

元素不可以重复(但分数可以重复)

元素有顺序

  • 添加:
    • zadd key score value
  • 查看:
    • zrange key start end (withscores):(同时输出分数)
    • zscore key value:查看某个元素的分数
    • zrank key value:查看某个元素的排名(从小到大)
    • zrevrank key value:查看某个元素的排名(从大到小,rev->reverse反转)
  • 删除:
    • zrem key value

6. 哈希类型 hash

字符类型的字段和值的映射表(一个键值对的集合)

适合用来存储对象

  • 添加:hset key field value
  • 查看:
    • hget key field:获取指定的field对应的值
    • hgetall key:获取所有的field和value
  • 删除:hdel key field
  • 判断摸个键值对是否存在:hexists key field
  • 获取哈希中的所有键:hkeys key
  • 获取哈希中的所有键的数量:hlen key

二、发布订阅模式

  • 将消息发送到指定的频道:publish channel(频道名称) message(发布的消息)
  • 订阅频道:subscribe channel [channel ...]
  • 局限性:
    • 消息无法持久化
    • 无法记录历史消息

三、消息队列Stream

Stream是Redis5.0引入的一个新的数据结构,是一个轻量级的消息队列

可以解决发布订阅功能的一些局限性(消息无法持久化、无法记录历史消息)

1. 集合

  • 添加
    • xadd key * field value
      • *表示自动生成一个消息id,可自己制定,格式:如1-0、2-0
      • 第一个整数表示一个时间戳,第二个整数表示一个序列号
      • *自动会保证id是递增的,手动需要保证id递增
  • 查看
    • xlen key:查看Stream中消息的数量
    • xrange key - +:查看所有的消息
    • xread COUNT 2 BLOCK 1000 STREAMS key 0
      • 一次读取2条消息
      • block表示没有消息就阻塞1000毫秒(1秒)
      • streams后面指定消息队列,0表示从头开始读取,1表示从第二条消息开始读取,如果超出消息数量,就会阻塞1秒,返回nil。要获取从现在开始,以后最新的消息,则streams后指定$
  • 删除
    • xdel key id:删除id的消息
    • xreim key MAXLENS 0:删除所有的消息

2. 消费者组

  • 创建
    • xgroup create key 组名称 id
  • 添加
    • xgroup createconsumer 组名称 消费者名
  • 查看
    • xinfo groups key:查看组信息
    • xreadgroup group 组名称 消费者名称 COUNT 2 BLOCK 3000 key >
      • 一次读取两条消息
      • 消息名 >:从这个消息中读取最新消息

四、持久化

  • redis是一个内存数据库,当redis服务器重启,获取电脑重启,数据会丢失,我们可以将redis内存中的数据持久化保存到硬盘的文件中

redis持久化机制:

1.1. RDB

默认方式,不需要进行配置,默认就是用这种机制

  • 在一定的间隔时间中,检测key变化情况,然后持久化数据
    • 编辑redis.windows.conf文件
      #  after 900 sec (15 min) if at least 1 key changed
      save 900 1
      #  after 300 sec (5 min) if at least 10 keys changed
      save 300 10
      #  after 60 sec if at least 10000 keys changed
      save 60 10000
  • 重新启动redis服务器,并指定配置文件名称
    redis-server.exe redis.windows.conf

1.2. AOF

日志记录的方式,可以记录每一条命令的操作。可以每一次命令操作后,持久化数据

  • 编辑redis.windows.conf文件
    • appendonly no(关闭aof)--> appendonly yes(开启aof)
    • appendfsync always:每一次操作都进行持久化
    • appendfsync everysec:每隔一秒进行一次持久化
    • appendfsync no:不进行持久化

五、Java客户端 Jedis

https://redis.io/clients

  1. Jedis:以Redis命令作为方法名称,学习成本低,简单实用。但Jedis实例线程不安全,多线程环境下需要连接池来使用。
  2. Lettuce:基于Netty实现,支持同步、异步和响应式编程方式,且线程安全。支持Redis的哨兵模式、集群模式和管道模式。
  3. Redisson:基于Redis实现的分布式、可伸缩的Java数据结构集合,包含了诸如Map、Queue、Lock、Semaphore、AtomicLong等强大功能。

1. 使用步骤:

  1. 下载Jedis的jar包 :https://github.com/redis/jedis
  2. 使用
    1. 获取链接
      Jedis jedis = new Jedis("localhost", 6379);
      Jedis jedis = new Jedis();//如果使用空参构造,默认值“localhost”,6379
    2. 设置密码:jedis.auth("123123");
    3. 选择库:jedis.select(0);
    4. 插入数据:String result = jedis.set("name","张三");
    5. 获取数据:String name = jedis.get("name");
    6. 释放资源:
if(jedis != null){
    jedis.close();
}

2. Jedis操作各种redis中的数据结构

2.1. 字符串类型string

  • set(key, value)
  • get(key)
  • setex(key, second, value)
    可以使用setex()方法存储可以指定过期时间的key value
           如jedis.setex("activecode",20,hehe);//将active:hehe键值对存入redis,并且20秒后自动删除该键值对。

2.2. 哈希类型hash

map格式

  • hset(key, filed, value)
  • hget(key, filed)
  • hgetAll(key)

2.3. 列表类型list

linkedlist格式。支持重复元素

  • lpush(key, ...strings)/rpush(key, ...strings) //...string是指后面多个数据
  • lpop(key)/rpop(key)
  • lrange(start, end):范围获取

2.4. 集合类型set

不允许重复元素

  • sadd

2.5. 有序集合类型sortedset

不允许重复元素,且元素有顺序

  • zadd

3. Jedis连接池

  • Jedis线程不安全,频繁创建和销毁连接有性能损耗,因此使用Jedis连接池代替Jedis的直连方式。
  • 使用Jedis连接池,Jedis.close()的操作就会归还,而不是销毁。
public class JedisConnectFactory{
    private static final JedisPool jedisPool;

    static{
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        //最大连接
        jedisPoolConfig.setMaxTotal(8);
        //最大空闲连接
        jedisPoolConfig.setMaxIdle(8);
        //最小空闲连接
        jedisPoolConfig.setMinIdle(8);
        //设置最长等待时间,ms
        jedisPoolConfig.setMaxWaitMillis(1000);

        jedisPool = new JedisPool(jedisPoolConfig, localhost, 6379, 1000,"123123");
    }
    //获取Jedis对象
    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
}

六、SpringDataRedis

  • SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis
  • 官网地址:https://spring.io/project/spring-data-redis
  • 提供了对不同Redis客户端的整合(Lettuce和Jedis)
  • 提供了RedisTemplate统一API来操作Redis
  • 支持Redis的发布订阅模式
  • 支持Redis哨兵和Redis集群
  • 支持基于Lettuce的响应式编程
  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化和反序列化
  • 支持基于Redis的JDKCollection实现

API

返回值类型

说明

redisTemplate.opsForValue()

ValueOperations

操作String类型数据

redisTemplate.opsForHahs()

HashOperations

操作Hash类型数据

redisTemplate.opsForList()

ListOperations

操作List类型数据

redisTemplate.opsForSet()

SetOperations

操作Set类型数据

redisTemplate.opsForZSet()

ZSetOperations

操作SortedSet类型数据

redisTemplate

通用的命令

1. SpringDataRedis简单应用

1.1. 依赖

<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. 配置文件

spring:
    redis:
        host: 127.0.0.1
        port: 6379
        password: 123123
        lettuce:
            pool:
                max-active: 8	# 最大连接
                max-idle: 8		# 最大空闲连接
                min-idle: 0		# 最小空闲连接
                max-wait: 100	# 连接等待时间,ms

1.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);
    }
}

2. SpringDataRedis的序列化方式

2.1. 自定义

  • RedisTemplate可以接收任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,默认采用JDK序列化,得到的结果如:\xAC\xED\x00\x05t\x00\x06\xE6\x9d\x8E\xE5\x98\x98
    • 缺点:可读性差、内存占用较大
  • 自定义RedisTemplate,修改RedisTemplate的序列化器为GenericJackson2JsonRedisSerializer
    • 缺点:占用额外内存空间,会记录类的字节码
/*没有引入SpringMVC,需引入Jackson依赖*/
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>
@Configuration
public class RedisConfig {

    //Redis连接工厂不需要创建,SpringBoot会自动创建,只需要@Bean注入一下就可以了
    @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;
    }
}

2.2. StringRedisTemplate

  • RedisTemplate会自动把对象序列化成JSON,和反序列化为对象
  • 尽管JSON序列化方式可以满足需求,但在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入JSON中,存入Redis,带来额外的内存开销
  • 为了节省内存空间,不会使用JSON序列化处理value,统一使用String序列化器,要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化
  • Spring默认提供了一个StringRedisTemplate类,它的key和value的序列化方式默认就是String方式,省去了定义RedisTemplate的过程
    • 省去了自定义过程
    • 缺点:每次读写,需要手动的把对象、JSON序列化和反序列化
@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.writerValueAsString(user);
    //写入数据
    stringRedisTemplate.opsForValue().set("user:200", json);


    //读取数据
    String val = stringRedisTemplate.opsForValue().get("user:200");
    //反序列化
    User user1 = mapper.readValue(val, User.class);
    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值