北京尚学堂2020java_Redis
4.2 AOF
AOF默认是关闭的,需要在配置文件中开启AOF。Redis支持AOF和RDB同时生效。如果同时存在,AOF优先级高于RDB(redis重新启动时会使用AOF进行数据恢复)
RDB记录的是紧凑的数据,AOF记录的是命令。
把配置文件中的appendonly从no改成yes
每秒钟记录一次日志信息
第五节 Redis主从复制
高可用:不是所有全部挂掉,还是可以使用的。
主从:备份安全性
哨兵:可用性(推荐使用哨兵)
集群:安全性&可用性&性能
搭建方式尽量掌握。
主从复制主要在安全上来考量这个问题,只要一个redis,那么可能就存在数据丢失的可能性。主要作为主要redis的一个备份。
5.1 主从优点
增加单一节点健壮性,提升整个集群稳定性
从节点可以对主节点数据备份,提供容灾能力
5.2 一主多从搭建
首先查看redis端口并关闭掉单机版
ps aux | grep redis
bin/redis-cli shutdown
cd /usr/local
mkdir redis-relicas
cp -r redis redis-replica/redis-m
cd redis-replica/redis-m
rm -r dump.rdb
cd ../
cp -r redis-m/ redis-s1/
cp -r redis-m/ redis-s2/
vi redis-m/redis.conf #只需要修改端口即可
vi redis-s1/redis.conf # port 7002 \n replicaof 192.168.2.129 7001
vi redis-s2/redis.conf # port 7003 \n replicaof 192.168.2.129 7001
接下来新建一个shell脚本/usr/local/redis-replicas/startup.sh
cd redis-m/
bin/redis-server redis.conf
cd ../redis-s1/
bin/redis-server redis.conf
cd ../redis-s2/
bin/redis-server redis.conf
赋予执行权限:
chmod 755 startup.sh
然后和客户端建立连接
cd redis-m/
bin/redis-cli -h localhost -p 7001
然后可以登录从节点的客户端来查看文件:
cd /usr/local/redis
bin/redis-cli -p 7002
分别使用7001、7002和7003
第六节 哨兵Sentinel
主从模式下,当主节点宕机后,从节点没办法立刻主节点。
在redis主从默认是只有主具备写的能力,而从只能读。如果主宕机,整个节点不具备写能力。如果这样让一个从变成主,整个节点就可以继续工作。即使之前的主恢复过来也当作这个节点的从即可。
单哨兵:只要发现master宕机了,直接选取另一个master。
多哨兵:达到一定数量哨兵认为master宕机了才会重新选取主节点。
第九节 使用SpringBoot整合SpringDataRedis操作redis
9.1 使用SpringDataRedis进行读写
- 引入依赖
- 配置好连接文件
- 写一个配置器类解析配置文件返回模板
- 在测试类中调用该模板
还是首先要引入一个springboot的依赖,scope为import,type为pom
依赖:1.springboot的核心启动器2.spring-boot-start-data-redis 3.jedis 4.spring-boot-starter-test
spring data redis:底层使用netty实现redis远程访问的框架,性能相对优于jedis。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
21_redis/src/main/resources/application.yml:
spring:
redis:
host: 192.168.2.129
port: 6379
database: 0 # 数据库编号
实现一个配置类21_redis/src/main/java/com/bjsxt/config:
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
// 提供连接工厂
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
}
写好测试类21_redis/src/test/java/com/bjsxt/TestSpringDataRedis.java
/**
* 配置类型 创建一个适用于RedisTemplate对象
*/
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
// 提供连接工厂
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
}
9.2 序列化器
9.2.1默认序列化器
SpringDataRedis默认情况下,做数据访问时,使用的数据序列化方案是JDK序列化方案。
要求:使用SpringDataRedis做持久化的数据,无论是key还是value,都必须可序列化。
- 先写一个User类,属性为username,password,需要序列化(在网络上传递就需要IO流,而使用IO流就必须刷序列化
- 将上面的类的实例化对象放进redis中testSetUser() 保存一个Java对象到redis中
- 取出一下看下数据
9.2.2 JSON序列化
配置key和value的序列化器,默认使用JDK序列化,使用JSON序列化。
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
// 提供连接工厂
redisTemplate.setConnectionFactory(factory);
// 配置key和value的序列化器,不使用默认的JDK序列化,使用JSON序列化
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
// 如果使用hash数据类型,可以提供额外的序列化器
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
return redisTemplate;
}
}
只不过最后拿到的不是com.bjsxt.pojo.User类型的对象,而是linkedHashMap,需要进行转换:
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestSpringDataRedis {
@Autowired
private RedisTemplate<String, Object> template;
@Test
public void get() {
Object value = template.opsForValue().get("key-1");
System.out.println(value.getClass().getName() + " - -" + value);
// 通过模板设置值的反序列化来获得User类型的返回对象
template.setValueSerializer(new Jackson2JsonRedisSerializer<User>(User.class));
value = template.opsForValue().get("user");
System.out.println(value.getClass().getName() + " - -" + value);
}
9.3操作其他数据类型
操作List:
@Test
public void testList() {
// 左增加
template.opsForList().leftPushAll("list-k", "v-1", "v-2", "v-1", "v-3");
// 右增加
template.opsForList().rightPushAll("list-k", "v-100", "v-200", "v-300");
//
List<Object> list = template.opsForList().range("list-k", 0, -1);
System.out.println(list);
}
操作Hash:
@Test
public void testHash() {
// 一个个放入
template.opsForHash().put("hash-k", "hash-field1", "hash-value1");
template.opsForHash().put("hash-k", "hash-field2", "hash-value2");
// 一堆一起放入
Map<Object, Object> hashValues = new HashMap<>();
hashValues.put("map-k1", "map-v1");
hashValues.put("map-k2", "map-v2");
// 查
template.opsForHash().putAll("hash-k", hashValues);
System.out.println(template.opsForHash().get("hash-k", "hash-field1"));
// 用entries最好
Map result = template.opsForHash().entries("hash-k");
System.out.println(result);
}
9.4 泛型序列化器
在配置类那里设置序列化时的使用使用泛型的即可。
使用json来描述每个对象的类型,但反向解析的时候可能会出现classNotFoundException。
// 如果使用hash数据类型,可以提供额外的序列化器
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
//redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
我怎么感觉使用的时候也大同小异:
@Test
public void testGet() {
template.opsForValue().set("k-new",
Arrays.asList(
new User("a", "1"),
new User("b", "2"),
new User("c", "3"),
new User("d", "4")
));
System.out.println(template.opsForValue().get("k-new"));
}
第十节 使用Redis效果
使用redis作为缓存
对db进行增删改查之后需要和redis、solr等缓存进行同步。
要保证数据存储和额外存储的一致。