一、认识Redis
1. 数据分类
1. 关系型数据库
采用行和列的表格结构,强调数据之间的关系,如 MySQL Oracle SQLServer DB2。
2. NoSql
不使用传统的关系模型,支持多种数据模型。
2.1 键值对 Redis
2.2 列存储数据库 HBase
2.3 文档数据库 MongoDB
2.4 图形数据库 Neo4j
3. 非关系型数据库的特点
- 数据模型简单,对于一些复杂的key比较容易映射。
- 灵活性更强,高度可扩展,易于处理大规模数据。
- 通常不支持复杂查询。
- 对于数据库的性能要求较高
4. 与关系型数据库的区别
- 数据结构:关系型数据库基于表格,非关系型数据库支持键值对、文档、图形等多种类型。
- 事务处理:关系型数据库支持ACID事务,而非关系型数据库通常采用最终一致性原则。
数据库 | 关系型数据库 | 非关系型数据库 |
优点 | 易于维护 使用简单 复杂操作 | 格式灵活 速度快 成本低 |
缺点 | 读写性能差 固定的表结构 高并发 硬盘I/O | 不提供sql支持 无事务支持 6.X版本以下 |
2. 什么是Redis
Redis是一个开源的高性能键值对存储系统,广泛用于缓存、消息队列、实时数据分析等场景,支持多种数据结构。
Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
单线程 key value存储
定位:
缓存 提高读写速度 减轻对数据库的访问压力
3. Redis的优势
每秒10W读写频率
4. redis安装
二、Redis数据类型
1. String类型
# Redis中的String数据存储类型类似于java中的 Map<String,?>
set key value #存入键值对
get key #根据键取出value
incr key #加1
decr key #减1
setex key timeout value #设置过期时间
timeout #单位是秒
应用场景:
分布式session
计时器
2. Hash类型
# Redis中的Hash数据存储类型类似于java中的 Map<String,Map<String,?>>
hset key hashkey hashvalue #存属性
hget key hashkey #获取属性值
hexists key hashkey #判断是否存在这个属性
hdel key hashkey #用于删除特定哈希(Hash)中的某个属性(field)
使用场景 :
用户信息管理
3. list类型
rpush key value #向列表的右边添加数据
lpush key value #向列表的左边添加数据
lrange key 0 -1 #遍历列表
lpop key #弹出左边的数据
rpop key #弹出右边的数据
使用场景 : 收藏夹
4.zset类型
zadd key score column #存入分数和名称
zrange key 0 -1 #遍历
zrem key column #移除数据
zcard key #获取数据个数
使用场景 : 排行榜
5.set类型
sadd key value #添加元素
smembers key #遍历集合
srem key value #删除某个元素
使用场景:
抽奖 去除重复
三、Redis持久化
1.Redis持久化方案
RDB方案
AOF方案
2.RDB持久化
2.1 RDB
Redis Database Backup file Redis数据备份文件 Redis快照
2.2执行时机
四种情况下执行:
1.执行save命令
2.执行bgsave命令
3.Redis停机
4.触发Rdb条件
1.save命令导致主进程执行RDB,这个过程中出现其他的命令都会被阻塞,只有在数据迁移的时候才进行使用.
2.我们建议使用bgsave 这个命令会独立的开启进程来完成RDB操作,主进程可以继续处理用户的请求,不受影响.
3.Redis停机之前会自动的执行一次save命令,实现RDB。
4.触发条件 redis.conf
save 900 1
save 300 10
save 60 10000
5.参数注意
rdbcompression yes 是否压缩 建议不开启 压缩会消耗cpu
dbfilename dump.rdb rdb文件名
dir ./ 默认当前目录
2.3RDB原理
bgsave 开始的收会进行fork 主进程得到子进程,子进程共享主进程的内存。完成fork操作之后读取内存的数据并写入rdb文件.
本质: 主进程无法直接操作物理内存,它只能操作虚拟内存,所以虚拟内存和物理内存之间就会有一个叫页表的东西,它的主要作用就是完成物理内存和虚拟内存之间的映射关系.
fork 不是把内存中的数据进行了拷贝,而是拷贝的页表--> 拿到内存映射关系
fork采用的是 copy-on-write技术
主进程进行读取操作访问的是共享内存
主进程进行写取操作,会拷贝一份数据,执行写操作。
2.4 总结
1. rdb 方式bgsave的执行流程?
fork主进程得到一个子进程,共享内存空间
子进程读取内存数据并写入rdb文件
用新的rdb文件替换旧的rdb文件
2.rdb什么时候执行?save 60 1000代表什么?
默认是服务停止就执行
60秒内至少执行了1000次就会触发rdb操作
3.rdb缺点?
rdb执行间隔长,两次rdb之间会有数据丢失的风险
fork 子进程 进行压缩 进行数据写入 需要消耗时间
3. AOF
Append Only File 追加文件
redis每次处理一个命令都会记录在aof文件中,它可以看作是日志。
AOF文件默认是关闭的
appendonly no #是否开启aof 默认是关闭
appendfilename "appendonly.aof" #aof文件名称
#appendfsync always 每写一行命令立即记录
appendfsync everysec 写命令先写入缓存区,每间隔一秒再从缓冲区写入到aof文件中
#appendfsync no 由操作决定什么时候写入磁盘中
4. RDB 和 AOF对比
RDB | AOF | |
持久化方式 | 定时对整个内存做快照 | 记录每一次执行的命令 |
数据完整性 | 不完整,两次备份之间可能会丢失数据 | 相对完整,取决于刷盘策略 |
文件大小 | 会有压缩,文件体积小 | 记录命令,文件体积大 |
宕机恢复速度 | 很快 | 慢 |
数据恢复优先级 | 低,数据完整性不如aof | 高,数据完整性更高 |
资源占用 | 高,大量消耗cpu | 低,只进行本地IO |
使用场景 | 可以容忍分钟级别的数据丢失,追求更快的启动速度 | 对数据安全性要求较高时候使用 |
四、Redis集群
4.1单机安装Redis
4.1.1 安装依赖
yum install -y gcc tcl
4.1.2 上传redis-6.2.4.tar.gz压缩包文件到linux的tmp目录下
4.1.3解压缩
tar -xvf redis-6.2.4.tar.gz
进入redis目录
cd redis-6.2.4
运行编译命令
make && make install
不报错就是成功了!!!!
更改redis.conf
bind 0.0.0.0 允许所有的ip地址进行访问
database 1 数据库设置为1 数据库共有16个 0--15
启动redis
redis-server redis.conf
4.2 Reids主从
4.2.1 主从结构
三个实例
IP | PORT | 角色 |
---|---|---|
192.168.135.131 | 7001 | master |
192.168.135.131 | 7002 | slave |
192.168.135.131 | 7003 | slave |
三个实例准备工作
cd /tmp mkdir 7001 7002 7003
修改redis.conf
开启RDBsave 3600 1 save 300 100 save 60 10000
关闭AOF
appendonly no
将刚刚修改的文件拷贝到 7001 7002 7003 中
cp redis-6.2.4/redis.conf 7001 cp redis-6.2.4/redis.conf 7002 cp redis-6.2.4/redis.conf 7003
修改端口
sed -i -e 's/6379/7001/g' -e 's/dir .\//dir \/tmp\/7001\//g' 7001/redis.conf sed -i -e 's/6379/7002/g' -e 's/dir .\//dir \/tmp\/7002\//g' 7002/redis.conf sed -i -e 's/6379/7003/g' -e 's/dir .\//dir \/tmp\/7003\//g' 7003/redis.conf
修改实例ip
replica-announce-ip 192.168.135.131
分别启动三个redis 建议开三个窗口
redis-server /tmp/7001/redis.conf redis-server /tmp/7002/redis.conf redis-server /tmp/7003/redis.conf
开启主从
连接 7002redis-cli -p 7002 slaveof 192.168.135.131 7001 -->告诉7002你的主人是7001
连接 7003
redis-cli -p 7003 slaveof 192.168.135.131 7001 -->告诉7002你的主人是7001
查看集群状态
redis-cli -p 7001 连接master info replication
4.3 Redis哨兵
sentinel 搭建三个
节点 | IP | 端口 |
---|---|---|
s1 | 192.168.135.131 | 27001 |
s2 | 192.168.135.131 | 27002 |
s3 | 192.168.135.131 | 27003 |
准备配置
cd /tmp mkdir s1 s2 s3
在s1目录创建一个sentinel.conf 内容如下:
port 27001 sentinel announce-ip 192.168.135.131 sentinel monitor mymaster 192.168.135.131 7001 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 60000 dir “/tmp/s1”
在s2目录创建一个sentinel.conf 内容如下:
port 27002 sentinel announce-ip 192.168.135.131 sentinel monitor mymaster 192.168.135.131 7001 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 60000 dir “/tmp/s2”
在s3目录创建一个sentinel.conf 内容如下:
port 27003 sentinel announce-ip 192.168.135.131 sentinel monitor mymaster 192.168.135.131 7001 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 60000 dir “/tmp/s3”
启动实例
redis-sentinel s1/sentinel.conf redis-sentinel s2/sentinel.conf redis-sentinel s3/sentinel.conf
让7001 这个直接点 宕机
使用命令:shutdown
观察日志 7002 7003 两个日志中
显示 MASTER MODE enabled 为新的master
4.4Redis分片
小的集群 3个master 做分片的集群准备
IP | PORT | 角色 |
192.168.135.131 | 7001 | master |
192.168.135.131 | 7002 | master |
192.168.135.131 | 7003 | master |
192.168.135.131 | 8001 | slave |
192.168.135.131 | 8002 | slave |
192.168.135.131 | 8003 | slave |
配置实例
cd /tmp rm -rf 7001 7002 7003
在tmp下面放一个redis.conf 文件,内容如下:
#端口 port 6379 #开启集群功能 cluster-enabled yes #集群的名称不需要我们创建由redis自行进行维护 cluster-config-file /tmp/6379/nodes.conf #节点之间心跳的超时时间为5秒 cluster-node-timeout 5000 #持久化目录 dir /tmp/6379 #绑定地址 bind 0.0.0.0 #redis后台运行 daemonize yes #注册实例ip地址 replica-announce-ip 192.168.135.131 #关闭保护模式 protected-mode no #数据库的数量 databases 1 #日志 logfile /tmp/6379/run.log
修改每个目录下面的 redis.conf 文件
将文件分别拷贝到 文件夹中echo 7001 7002 7003 8001 8002 8003 | xargs -t -n 1 cp redis.conf
修改每个目录下面redis.conf 将其中的6379修改为所在目录
printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf
因为设置了后台启动,所以我们可以一次性启动6个服务
printf '%s\n' 7001 7002 7003 8001 8002 8003 | xargs -I{} -t redis-server {}/redis.conf
通过ps查看状态
ps -ef | grep redis
测试 注意了命令有变化
redis-cli -c -p 7001
五、原理部分
5.1 主从集群同步原理
1.全量同步
主从第一次会执行全量同步,将master节点的所有数据拷贝给slave节点,流程
2.增量同步
5.2哨兵集群原理
sentinel是基于心跳机制的检测服务状态,每间隔1秒向集群中的每个实例发送ping命令;
主观下线:
如果某个sentinel节点发现某个节点在规划的时间段内没有响应,就认为主观下线。
客观下线:
如果超过半数的sentinel都认为这个实例主观下线,。这个实例就客观下线。
集群故障回复的原理:
一旦master发生故障,sentinel需要在slave中选择一个作为新的master,选举依据如下:
首先判断slave节点与master节点断开的时间长短,如果超过指定的值(down-after-seconds*10),会派出该slave节点。
接下来查看选举值,值越小优先级越高。如果值一致,offset值越大,说明数据越新。
判断slave运行的id的大小,越小优先级越高。
5.3 分片集群原理
使用场景:
1. 海量数据存储
2. 高并发写
分片集群特征:
集群中有多个master ,每个master保存的数据不一样
每个master可以有多个slave节点
master之间通过 ping命令检测健康状态
插槽 0--- 16383 总数 16384
如何存插槽
通过hash运算 借助 对于 16384 进行取余