1. redis应用场景
1. 缓存
作为Key-Value形态的内存数据库,Redis 最先会被想到的应用场景便是作为数据缓存。而使用 Redis 缓存数据非常简单,只需要通过string类型将序列化后的对象存起来即可,不过也有一些需要注意的地方:
必须保证不同对象的 key 不会重复,并且使 key 尽量短,一般使用类名(表名)加主键拼接而成。
选择一个优秀的序列化方式也很重要,目的是提高序列化的效率和减少内存占用。
缓存内容与数据库的一致性,这里一般有两种做法:
只在数据库查询后将对象放入缓存,如果对象发生了修改或删除操作,直接清除对应缓存(或设为过期)。
在数据库新增和查询后将对象放入缓存,修改后更新缓存,删除后清除对应缓存(或设为过期)。2. 数据共享分布式
String 类型,因为 Redis 是分布式的独立服务,可以在多个应用之间共享
例如:分布式Session
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>1
2
3
43、分布式锁
如今都是分布式的环境下java自带的单体锁已经不适用的。在 Redis 2.6.12 版本开始,string的set命令增加了一些参数:
EX:设置键的过期时间(单位为秒)
PX:设置键的过期时间(单位为毫秒)
NX :只在键不存在时,才对键进行设置操作。 SET key value NX 效果等同于 SETNX key value 。
XX :只在键已经存在时,才对键进行设置操作。
由于这个操作是原子性的,可以简单地以此实现一个分布式的锁,例如:
set lock_key locked NX EX 1
1
如果这个操作返回false,说明 key 的添加不成功,也就是当前有人在占用这把锁。而如果返回true,则说明得了锁,便可以继续进行操作,并且在操作后通过del命令释放掉锁。并且即使程序因为某些原因并没有释放锁,由于设置了过期时间,该锁也会在 1 秒后自动释放,不会影响到其他程序的运行。
推荐使用 redisson 第三方库实现分布式锁。
参考 java分布式锁终极解决方案之 redisson
4、全局IDint类型,incrby,利用原子性
incrby userid 1000
分库分表的场景,一次性拿一段
5、计数器int类型,incr方法
例如:文章的阅读量、微博点赞数、允许一定的延迟,先写入Redis再定时同步到数据库
计数功能应该是最适合 Redis 的使用场景之一了,因为它高频率读写的特征可以完全发挥 Redis 作为内存数据库的高效。在 Redis 的数据结构中,string、hash和sorted set都提供了incr方法用于原子性的自增操作,下面举例说明一下它们各自的使用场景:
如果应用需要显示每天的注册用户数,便可以使用string作为计数器,设定一个名为REGISTERED_COUNT_TODAY的 key,并在初始化时给它设置一个到凌晨 0 点的过期时间,每当用户注册成功后便使用incr命令使该 key 增长 1,同时当每天凌晨 0 点后,这个计数器都会因为 key 过期使值清零。
每条微博都有点赞数、评论数、转发数和浏览数四条属性,这时用hash进行计数会更好,将该计数器的 key 设为weibo:weibo_id,hash的 field 为like_number、comment_number、forward_number和view_number,在对应操作后通过hincrby使hash 中的 field 自增。
如果应用有一个发帖排行榜的功能,便选择sorted set吧,将集合的 key 设为POST_RANK。当用户发帖后,使用zincrby将该用户 id 的 score 增长 1。sorted set会重新进行排序,用户所在排行榜的位置也就会得到实时的更新。6、限流
int类型,incr方法
以访问者的ip和其他信息作为key,访问一次增加一次计数,超过次数则返回false
7、位统计String类型的bitcount(1.6.6的bitmap数据结构介绍)
字符是以8位二进制存储的
set k1 a
setbit k1 6 1
setbit k1 7 0
get k1
/* 6 7 代表的a的二进制位的修改
a 对应的ASCII码是97,转换为二进制数据是01100001
b 对应的ASCII码是98,转换为二进制数据是01100010因为bit非常节省空间(1 MB=8388608 bit),可以用来做大数据量的统计。
*/1
2
3
4
5
6
7
8
9
10参考 使用Redis的bitmaps统计用户留存率、活跃用户
用户日活月活怎么统计 - Redis HyperLogLog 详解
8. 时间轴(Timeline)list作为双向链表,不光可以作为队列使用。如果将它用作栈便可以成为一个公用的时间轴。当用户发完微博后,都通过lpush将它存放在一个 key 为LATEST_WEIBO的list中,之后便可以通过lrange取出当前最新的微博。
9. 消息队列Redis 中list的数据结构实现是双向链表,所以可以非常便捷的应用于消息队列(生产者 / 消费者模型)。消息的生产者只需要通过lpush将消息放入 list,消费者便可以通过rpop取出该消息,并且可以保证消息的有序性。如果需要实现带有优先级的消息队列也可以选择sorted set。而pub/sub功能也可以用作发布者 / 订阅者模型的消息。无论使用何种方式,由于 Redis 拥有持久化功能,也不需要担心由于服务器故障导致消息丢失的情况。
List提供了两个阻塞的弹出操作:blpop/brpop,可以设置超时时间
blpop:blpop key1 timeout 移除并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
brpop:brpop key1 timeout 移除并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。上面的操作。其实就是java的阻塞队列。学习的东西越多。学习成本越低
队列:先进先除:rpush blpop,左头右尾,右边进入队列,左边出队列
栈:先进后出:rpush brpop10、抽奖
利用set结构的无序性,通过 Spop( Redis Spop 命令用于移除集合中的指定 key 的一个或多个随机元素,移除后会返回移除的元素。 ) 随机获得值
2.redis的持久化
什么是持久化: 把内存中的数据保存到磁盘的过程---就是持久化。防止数据丢失。
2.1redis的持久化方式
1.第一种: RDB---快照模式---在一定时间间隔内,对当前redis内存中的数据进行拍照存储。
2.第二种: AOF---日志追加---每次执行的写命令,都会通过一个函数write记录到日志中。
2.2 RDB快照存储
1. 什么时候触发RDB模式?
三种方式: save bgsave 通过配置文件
默认保存的文件名称: dump.rdb
2.save和bgsave的区别
1)save模式
该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止
执行完成时候如果存在老的RDB文件,就把新的替代掉旧的。我们的客户端可能都是几万或者是几十万,这种方式显然不可取。
2)bgsave模式
执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体流程如下:
bgsave
3)自动触发
需要指定配置文件---一般不建议改---采用默认值----底层自动执行bgsave命令
2.3rdb数据恢复
只需要把dump.rbd文件放入按照目录,当redis服务启动时,会读取dump.rdb文件 并加载到内存中。
2.4 AOF持久化
它会把每个写命令通过write函数记录到日志文件中。默认改持久化没有开启。需要修改配置文件来开启aof模式。
2.5 RDB和AOF的优缺点
(1)RDB的优点
数据恢复速度快。
(2)缺点
数据完整性差-
(1)AOF的优点
数据完整性比较强----最多丢失最后一条写命令
(2)缺点
数据恢复速度比较慢---因为它需要把日志文件中所有的命令执行一遍
如果两则同时开启:
默认恢复数据时采用的时AOF.
3.redis的集群
3.1 为什莫使用集群
(1)单个redis存在不稳定性。当redis服务宕机了,就没有可用的服务了。 (推荐学习:Redis视频教程)
(2)单个redis的读写能力是有限的。
总结:redis集群是为了强化redis的读写能力。
redis主从复制,主从复制模型中,有多个redis节点。其中,有且仅有一个为主节点Master。从节点Slave可以有多个 可以减少单机的压力,解决单机故障问题。 。
只要网络连接正常,Master会一直将自己的数据更新同步给Slaves,保持主从同步。
3.2第一种集群方式--主从模式
配置主从模式---配从不配主。
模拟: 一台linux系统,启动三台redis服务.依靠端口号:6380主节点 6381从节点 6382从节点
2.修改配置
bind 0.0.0.0 -::1
# 关闭保护模式
protected-mode no
port 6380 | 6381 | 6382
dbfilename dump6380.rdb | dump6381.rdb | dump6382.rdb
appendfilename "appendonly6380.aof"
启动这三台服务器
查看三个redis的角色
得出全部都是各自主节点 无从节点
3.2.1配置主从关系---从节点
slaveof 主节点ip 主节点port
3.2.2 往主节点添加数据 使用从节点读取数据
思考:
如果主节点挂掉--从节点是否可以上位。---不会。
如果新增一个小弟--该小弟是否可以把之前的数据同步过来。----可以
小弟是否可以进行写操作------只负责读操作不能负责写操作
主节点是否可以进行写操作和读操作。-----> 可以负责读写操作。
3.3 第二种集群模式 ---- 哨兵模式
3.3.1 什么是哨兵模式
Sentinel(哨兵)是用于监控Redis集群中Master状态的工具,是Redis高可用解决方案,哨兵可以监视一个或者多个redis master服务,以及这些master服务的所有从服务。 某个master服务宕机后,会把这个master下的某个从服务升级为master来替代已宕机的master继续工作。
(顺带提一句,即使后来之前的master重启服务,也不会变回master了,而是作为slave从服务)
3.3.2 创建哨兵
1) 修改配置文件 sentinel.conf文件
2) 开启哨兵
redis-sentinel sentinel.conf
shutdown 关闭哨兵模式
3.3.3 演示挂点主节点
如果原来的主节点回来---它需要变成从节点。
3.3.4哨兵的优缺点
优点:
对节点进行监控,来完成自动的故障发现与转移
缺点:
特别是在主从切换的瞬间存在访问瞬断的情况,等待时间比较长,至少十来秒不可用。
哨兵模式只有一个主节点对外提供服务,没法支持很高的并发
单个主节点内存也不宜设置得过大,否则会导致持久化文件过大,影响数据恢复或主从同步的效率。与主从相比,哨兵仅解决了手动切换主从节点问题,至于其他的问题,基本上仍然存在。
哨兵的主要问题还是由于中心架构,仅存在一个master节点引起的,写的效率太低。
3.4第三种模式--- 集群模式 去中心化
主从模式实现了数据的热备份,哨兵模式实现了redis的高可用。但是有一个问题,这两种模式都没有解决,这两种模式都只能有一个master节点负责写操作,在高并发的写操作场景,master节点就会成为性能瓶颈。
redis的集群模式中可以实现多个节点同时提供写操作,redis集群模式采用无中心结构,每个节点都保存数据,节点之间互相连接从而知道整个集群状态。
如图所示集群模式其实就是多个主从复制的结构组合起来的,每一个主从复制结构可以看成一个节点,那么上面的Cluster集群中就有三个节点。
3.4.1 准备配置器
准备: 6台redis服务。---6个服务中不能有数据。
7001
7002
7003=============主节点
7004
7005
7006=====从节点
修改配置文件: 都需要改
bind 0.0.0.0
port 7001
daemonize yes
# 打开aof 持久化
appendonly yes
# 开启集群
cluster-enabled yes
# 集群的配置文件,该文件自动生成
cluster-config-file nodes-7001.conf
# 集群的超时时间
cluster-node-timeout 5000
3.4.2开启redis
3.4.3 为这6台redis配置主从关系
redis-cli --cluster create --cluster-replicas 1 192.168.26.129:7001 192.168.26.129:7002 192.168.26.129:7003 192.168.26.129:7004 192.168.26.129:7005 192.168.26.129:7006
-- --cluster-replicas 1: 从节点的个数
验证
redis-cli -c -h 127.0.0.1 -p 7001