redis第三期(最终篇)
上回,我们搞定了redis相关的数据类型与持久化操作,这次我们就在之前的基础上彻底理解redis包括redis的事务处理,以及使用编程语言交互redis,理解redis的分布式与哨兵、集群等概念并进行实战,本次redis结束后,我们会开启计算机组成原理的学习过程。
当我们需要完成redis来一次完整提交多条redis指令而中间不希望被打扰的时候就需要我们开启事务机制(事务可以理解成统一到最后返回结果)了。对于redis来说,开启和提交事务的指令很简单,如下所示:
multi #使用命令来直接开启事务
当我们输入完成指令的时候,我们就需要进行事务提交了,提交指令如下:
exec #使用命令来提交事务
如果在提交之前我们想要把事务取消掉,那么我们直接执行如下指令:
discard
这样事务就不用回滚了,事务直接在提交之前被取消了。
接下来,我们看redis中的锁机制,如果同时有两个进程都想要修改同一个数据,那么这个时候就需要调用redis中的锁机制。锁机制可以保证同一时间只能执行同一个指令。但是redis中的锁与mysql中的锁确有不同,具体如下。
mysql就是一种悲观锁,何为悲观锁,悲观锁就是时刻认为会有人来抢占资源,禁止一切外来资源,直到释放锁(具有十分强烈的排他性),可以说悲观锁是真正意义上了一把锁。而redis是一种乐观锁,并不会认为有人来抢占它的资源,所以会对数据进行直接操作,在操作时再去验证是否有其他人抢占资源,可以说乐观锁并不是真正意义上了一把锁,它更像是进行判断和校验。
好那么我们接下来再来回顾redis中的锁的应用。redis中有一个watch来监视一个目标,当watch在执行事务之前锁定了一个监视目标时
,如果监视目标发生了修改,那么就取消本次事务的提交。
watch
取消监控,就是unwatch
unwatch
即watch时,不可以修改或者抢占目标资源。
使用网络编程语言java对redis进行操作:我们需要使用Jedis框架来进行Java与Redis数据库之间的交互行为
首先导入依赖:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.0.0</version>
</dependency>
然后我们就可以创建一个专门操作redis的类来进行对redis的操作,下面是一个基本操作:
try (Jedis jedis = new Jedis("localhost",6379)){
//创建一个set数据类型
jedis.set("a","222");
System.out.println(jedis.get("a")); //获取
System.out.println("\n");
//创建一个Hashset数据类型
jedis.hset("b","name","ZhangSan");
jedis.hset("b","age","20");
System.out.println(jedis.hget("b","name")+jedis.hget("b","age"));
System.out.println("\n");
jedis.hgetAll("b").forEach((k,v)-> System.out.println(k+" "+v));
System.out.println("\n");
//创建一个list数据类型
jedis.del("c");
jedis.lpush("c","1111","2222","3333");
jedis.lrange("c",0,-1).forEach(System.out::println);
}
使用SpringBoot来操作redis数据库:
首先,可以在原始界面上添加Nosql中的Redis相关服务,然后按照固定模板去套就行。
不过Spring中对于redis的事务操作机制,由于Spring没有提供专门的Redis事务管理器,所以只能借助JDBC去提供了。需要引入JDBC的相关依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
```
有了相关的事务管理依赖,我们现在就可以借助springboot来发挥redis的事务作用了。
首先我们要在spring的环境下处理事务,我们可以把事务本身当作是一个对象,并且里面有redis相关模板的注入,有事务的开启处理初始化操作,还有整个事务执行流程方法(开启事务,执行事务,提交事务)。 然后我们可以把这个事务对象放到我们的redis测试类中去执行事务(事务处理)
事务对象类:
@Service
public class RedisService {
@Resource
StringRedisTemplate stringRedisTemplate; //redis相关模板对象的注入
//开启事务
@PostConstruct
public void init()
{
stringRedisTemplate.setEnableTransactionSupport(true); //需要开启事务
}
@Transactional //事务
public void test()
{
stringRedisTemplate.multi(); //事务正式开启
stringRedisTemplate.opsForValue().set("m","199937");
stringRedisTemplate.exec(); //提交事务
}
}
redis测试类
@SpringBootTest
public class RedisTest {
@Resource
StringRedisTemplate stringRedisTemplate;
@Resource
RedisService redisService;
@Test
void contextLoads(){
redisService.test(); //处理事务
}
}
当然了,我们可以用json的序列化来代替原来jbdc序列化的方式去存储数据(可以在事务初始化init()方法中执行操作)
redis的主从复制,指的是一台redis服务器中的数据复制到另一台服务器上,前者称之为主节点(Master),后者称之为从节点(Slave),且这种数据复制是单向的,只可以从Master到Slave。分布场景下,就会选择redis服务器的主从模式
一般情况下,写操作就会交给主节点去处理,然后主节点将数据同步到从节点,由从节点来执行读操作。这样就实现了读写分离,提高了性能。当我们遇到了读多写少的情况下,我们甚至可以添加多个从节点来进行负载均衡的操作,缓解每个从节点的压力。