2024-01-24-redis学习笔记

redis事务

        简介

        Redis事务是一种原子性操作的方法,它允许用户将多个命令打包成一个单独的操作单元,然后将其作为一个整体进行执行。在执行事务期间,Redis会确保其他客户端不会在事务执行过程中修改被事务操作的数据。

使用Redis事务通常需要以下步骤:

  1. MULTI:开始一个事务,之后的所有命令都将被添加到事务队列中。
  2. 执行一系列命令:将需要执行的命令逐个添加到事务队列中。
  3. EXEC:执行事务队列中的所有命令。Redis将按照添加的顺序依次执行这些命令。
  4. 事务执行结束后,Redis会返回一个包含每个命令执行结果的数组。

在事务执行期间,即使某个命令执行失败,其他命令仍然会继续执行。只有在执行EXEC命令时,Redis才会将所有命令作为一个整体提交到服务器进行执行。这样可以确保事务内的所有命令要么全部执行成功,要么全部执行失败。

另外,Redis还提供了WATCH命令来实现乐观锁,以确保在事务执行期间被监视的键没有被其他客户端修改。如果监视的键被修改,事务将中断执行。

总的来说,Redis事务提供了一种简单的方式来执行一系列命令的原子操作,并且可以通过WATCH命令实现乐观锁。然而,需要注意的是,Redis事务并不是严格的ACID事务,它无法满足所有数据库事务的要求。

        悲观锁

        悲观锁是一种常用的并发控制机制,用于解决多个客户端同时对同一资源进行读写操作时可能导致的数据不一致问题。悲观锁的基本思想是,在访问共享资源之前,先获取锁来确保只有一个客户端能够访问该资源,其他客户端需要等待。

        乐观锁

        乐观锁也是一种常用的并发控制机制,它的基本思想是假设所有客户端之间的操作都是互不干扰的,然后通过版本号等方式来检测是否有其他客户端对数据进行了修改。乐观锁的实现通常需要结合Redis的WATCH命令和CAS(Compare-And-Swap)操作来完成。

redis的使用

java操作redis

        创建一个java项目,添加依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.2.0</version>
</dependency>

        之后就可以使用jedis了

        相关API

连接和断开redis

Jedis jedis = new Jedis("localhost", 6379); // 连接本地Redis服务器,默认端口为6379
jedis.auth("password"); // 输入密码(如果设置了密码)
jedis.ping(); // 测试是否连接成功
jedis.close(); // 关闭连接

字符串操作

// 设置和获取字符串类型数据
jedis.set("key", "value");
String value = jedis.get("key");

// 删除字符串类型数据
jedis.del("key");

// 自增和自减操作
jedis.incr("key"); // 自增1
jedis.incrBy("key", 10); // 增加指定值
jedis.decr("key"); // 自减1
jedis.decrBy("key", 10); // 减少指定值

哈希表操作

// 设置和获取哈希表类型数据
jedis.hset("user", "name", "Alice");
String name = jedis.hget("user", "name");

// 获取所有的键值对
Map<String, String> map = jedis.hgetAll("user");

// 删除哈希表中的字段
jedis.hdel("user", "name");

列表类型操作

// 列表尾部添加元素
jedis.rpush("list", "a", "b", "c");

// 获取列表长度
long len = jedis.llen("list");

// 获取指定范围内的元素
List<String> list = jedis.lrange("list", 0, -1);

// 弹出列表中的元素
String element = jedis.lpop("list");

集合类操作

// 添加元素
jedis.sadd("set", "a", "b", "c");

// 获取集合中的元素个数
long count = jedis.scard("set");

// 判断元素是否存在
boolean exist = jedis.sismember("set", "a");

// 随机弹出元素
String element = jedis.spop("set");

redis整合springboot

        首先创建项目,添加相关依赖

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


<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

编写配置文件

#设置的redis的服务器
spring.redis.host=192.168.162.33
#设置连接redis的密码
spring.redis.password=xxx(你的密码)
#端口号
spring.redis.port=6379
#设置reis的索引
spring.redis.database=15 (连接的数据库)

配置设置类

package com.example.demo;


import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;


import java.time.Duration;


@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
  /**
     * 连接池的设置
     *
     * @return
     */
    @Bean
    public JedisPoolConfig getJedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        return jedisPoolConfig;
    }


    /**
     * RedisTemplate
     * @param factory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setConnectionFactory(factory);
        //key序列化方式
        template.setKeySerializer(redisSerializer);
        //value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //value hashmap序列化
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        return template;
    }


    /**
     * 缓存处理
     * @param factory
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }
}

spring-boot-redis

        spring-boot-redis 是一个用于与 Redis 数据库交互的开发框架,它提供了对多种 Redis 客户端库的支持,包括 Jedis。通过 Spring Data Redis,你可以使用 Jedis 提供的功能来操作 Redis 数据库。

以下是spring-boot-redis 针对 Jedis 提供的一些常用功能:

        连接配置:Spring Data Redis 可以通过配置文件或编程方式来配置连接 Redis 服务器所需的参数,如主机名、端口号、密码等。使用 Jedis 作为底层客户端时,需要配置 JedisConnectionFactory bean。               

        数据操作:Spring Data Redis 提供了与 Jedis 相对应的 RedisTemplate 类,可以方便地进行数据操作。通过 RedisTemplate,你可以执行 Jedis 提供的各种命令,如 set、get、hset、hget、lpush、lrange 等。使用 RedisTemplate,你可以更加简洁地操作 Redis 数据库。

操作字符串redisTemplate.opsForValue();
操作hashredisTemplate.opsForHash();
操作listredisTemplate.opsForList();
操作setredisTemplate.opsForSet();
操作有序set redisTemplate.opsForZSet();

        数据序列化:Spring Data Redis 支持将对象序列化为字节流并存储到 Redis 中,以及将存储在 Redis 中的字节流反序列化为对象。默认情况下,Spring Data Redis 使用 JdkSerializationRedisSerializer 进行对象的序列化和反序列化,你也可以根据需要自定义序列化器。

        事务支持:Spring Data Redis 提供了对 Redis 的事务支持。你可以使用 @Transactional 注解来声明一个方法为事务方法,并在方法内执行多个 Redis 操作。当方法执行结束时,Spring Data Redis 会自动将这些操作封装为一个 Redis 事务,并提交或回滚。

自动缓存 @Cacheable

        在配置好配置类之后,就可以使用@Cacheable进行自动缓存,该注释可以使用在类或方法上,使用在类上时,表示整个类的所有方法都需要自动缓存,使用在方法上表示该方法自动缓存,@Cacheable可以传入很多参数

参数

解释

example

value

缓存的名称,在 spring 配置文件中定义,必须指定至少一个

例如:

@Cacheable(value=”mycache”)

@Cacheable(value={”cache1”,”cache2”}

key

缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合

@Cacheable(value=”testcache”,key=”#userName”)

condition

缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存

@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

 

  • 18
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值