目录
一、事务
二、乐观锁
三、Jedis
四、Springboot整合Redis
4.1创建springboot项目,勾选对应的依赖
4.2源码分析
4.3配置文件
4.4测试
4.5自定义序列化方式
4.5.1JSON序列化
4.5.2String序列化
事务本质:一组命令的集合,一个事物的所有命令都会被序列化,会按照顺序执行。
Redis事务没有隔离级别的概念。
Redis单条命令保存原子性,但事务不保证原子性。
redis事务流程:
放弃事务:
悲观锁:认为什么时候都会出现问题,无论如何都会加锁
乐观锁:认为什么时候都不会出错,所以不会加锁,更新数据时需要判断一下,在此期间是否有人修改过这个数据。
Redis实施监控:
多线程修改时,使用watch可以当做redis的乐观锁操作
如果监控失败,获取最新值
1.首先在resources
文件夹下写一个配置文件,我的文件名是:redis.properties
,内容如下:
# 自己的ip地址
redis.host=12.16.25.1
# 端口号
redis.port=6379
redis.maxTotal=30
redis.maxIdle=10
2.然后写一个工具类,用来获取jedis对象
public class JedisUtils {
private static JedisPool jp = null;
private static String host = null;
private static int port;
private static int maxTotal;
private static int maxIdle;
static {
ResourceBundle rb = ResourceBundle.getBundle("redis");
JedisPoolConfig jpc = new JedisPoolConfig();
host = rb.getString("redis.host");
port = Integer.parseInt(rb.getString("redis.port"));
maxTotal = Integer.parseInt(rb.getString("redis.maxTotal"));
maxIdle = Integer.parseInt(rb.getString("redis.maxIdle"));
jp = new JedisPool(jpc, host, port);
}
public static Jedis getJedis() {
return jp.getResource();
}
}
3.编码测试
输出PONG则说明连接成功
手写一个事务
主要依赖
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
spring:
redis:
# Redis服务器地址
host: 19.1.5.11
# Redis服务器端口号
port: 6379
# 使用的数据库索引,默认是0
database: 0
# 连接超时时间
timeout: 1800000
# 设置密码
password: "123456"
lettuce:
pool:
# 最大阻塞等待时间,负数表示没有限制
max-wait: -1
# 连接池中的最大空闲连接
max-idle: 5
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中最大连接数,负数表示没有限制
max-active: 20
private RedisTemplate redisTemplate;
@Test
void testOne() {
redisTemplate.opsForValue().set("name","卷心菜");
String name = (String) redisTemplate.opsForValue().get("name");
System.out.println(name); //卷心菜
}
用redis客户端查看时发现乱码,原因是未自定义序列化
定义RedisConfig.java配置类
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
// 创建模板
RedisTemplate 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;
}
}
问题:在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入json结果中,存入Redis,会带来额外的内存开销
为了节省内存空间,我们并不会使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化
方法二:
@Autowired
private StringRedisTemplate redisTemplate;
// JSON工具
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testOne() {
redisTemplate.opsForValue().set("name", "卷心菜");
}
@Test
void testTwo() throws IOException {
Person person = new Person("我是一棵卷心菜", 21);
// 手动序列化
String json = mapper.writeValueAsString(person);
redisTemplate.opsForValue().set("person", json);
String personJson = redisTemplate.opsForValue().get("person");
// 反序列化
Person person1 = mapper.readValue(personJson, Person.class);
System.out.println(person1);
}