(仅作为个人学习笔记)
1.什么是Redis?
1.Redis 是用C语言开发的一个开源的高性能键值对( key-value )内存数据库,它是一种 NoSQL 数据库。
2.它是【单进程单线程】的内存数据库,所以说不存在线程安全问题。它可以支持并发 10W QPS(每秒请求数),所以说性能非常优秀。之所以单进程单线程性能还这么好,是因为底层采用了【IO多路复用(NIO思想)】
3.它提供了五种数据类型来存储【值】:字符串类型(string)、散列类型(hash)、列表类型(list)、集合类型(set)、有序集合类型(sortedset、zset)
2.Redis消息模式
队列模式:
使用list类型的lpush和rpop实现消息队列
注意事项:
1.消息接收方如果不知道队列中是否有消息,会一直发送rpop命令,如果这样的话,会每一次都建立一次连接, 这样显然不好。
2.可以使用blpop和brpop命令,它如果从队列中取不出来数据,会一直阻塞,在一定范围内没有取出则返回null、
发布订阅模式:(略)
Redis 可以发布订阅功能,但是只能实现的简单 MQ 功能。
由于 Redis 发布的消息不会被持久化,这就会导致新订阅的客户端将不会收到历史消息。建议使用专业的MQ
3.Redis事务
介绍:
1.Redis 的事务是通过 MULTI 、 EXEC 、 DISCARD 和 WATCH 、UNWATCH这五个命令来完成的。
2.Redis 的单个命令都是原子性的,所以这里需要确保事务性的对象是命令集合。
3.Redis 将命令集合序列化并确保处于同一事务的命令集合连续且不被打断的执行
4.Redis 不支持回滚操作。
4.事务命令:
MULTI:用于标记事务块的开始。
Redis会将后续的命令逐个放入队列中,然后使用EXEC命令原子化地执行这个命令序列。
EXEC:在一个事务中执行所有先前放入队列的命令,然后恢复正常的连接状态
DISCARD: 清除所有先前在一个事务中放入队列的命令,然后恢复正常的连接状态。
WATCH:当某个[事务需要按条件执行]时,就要使用这个命令将给定的[键设置为受监控]的状态。
注意事项:使用该命令可以实现 Redis 的乐观锁。
UNWATCH:清除所有先前为一个事务监控的键。
Redis 不支持事务回滚(为什么呢)
1、大多数事务失败是因为语法错误或者类型错误,这两种错误,在开发阶段都是可以预见的
2、 Redis 为了性能方面就忽略了事务回滚。
(回滚记录历史版本)
5.事务失败处理:
Redis 语法错误:整个事务的命令在队列里都清除
Redis 运行错误:在队列里正确的命令可以执行 (弱事务性)
弱事务性 : 1、在队列里正确的命令可以执行 (非原子操作) 2、不支持回滚
6.Redis乐观锁:
什么是乐观锁:对于数据冲突保持一个很乐观的态度,操作数据不会对操作的数据进行加锁,只有在数据提交的时候进行验证是否冲突。
redis实现乐观锁步骤:
1、利用redis的watch功能,监控这个redisKey的状态值
2、获取redisKey的值
3、创建redis事务
4、给这个key的值+1
5、然后去执行这个事务,如果key的值被修改过则回滚,key不加1
代码演示:
public void watch() {
try {
String watchKeys = "watchKeys";
//初始值 value=1
jedis.set(watchKeys, 1);
//监听key为watchKeys的值
jedis.watch(watchkeys);
//开启事务
Transaction tx = jedis.multi();
//watchKeys自增加一
tx.incr(watchKeys);
//执行事务,如果其他线程对watchKeys中的value进行修改,则该事务将不会执行
//也就是说如果监测到其他线程改变了watchKeys,则这个自增操作就不会执行了
//通过redis事务以及watch命令实现乐观锁
List<Object> exec = tx.exec();
if (exec == null) {
System.out.println("事务未执行");
} else {
System.out.println("事务成功执行,watchKeys的value成功修改");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
jedis.close();
}
}
7.Redis持久化之
Redis的数据都是存储在内存中,为了数据的永久保存,需要把数据同步到硬盘上,这个过程就叫做持久化. Redis的持久化存在有两种方式: rdb方式,aof方式,这两种方式可以单独使用,也可以综合使用.
rdb持久化方式: 是在指定的时间间隔写入硬盘
aof持久化方式:是以日志,记录每一个操作,服务器启动后,根据日志来构建数据.
8.RDB方式(默认)
RDB方式是通过快照完成的,当符合一定条件时Redis会自动将内存中的数据进行
快照并持久化到硬盘。
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件,整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能,如果需要进行大规模的快照,且处于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效.RDB的缺点就是最后一次持久化后的数据可能丢失.
9.AOF方式:
AOF:以日志的形式来记录每个写操作,将redis执行过的所有写指令记录下来(不会记录读指令),只许追加文件但是不可以改写文件,redis启动之初会读取该文件(appendonly.aof)重新构建数据,换而言之:redis重启的话就是根据日志文件的内容将写指令从头到尾执行一次,以完成数据的恢复工作.
AOF重写机制:
AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。
AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename),遍历新进程的内存中数据,每条记录有一条的Set语句。重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似