一、概述
Redis是什么
Redis能干什么
特性
二、基础知识
redis默认有16个数据库,默认使用第0个数据库
可以使用select来切换
select [num]
清除数据库
flushdb 清空当前数据库
flushall 清空所有数据
redis是单线程 明白Redis是很快的,官方表示,Redis是基于内存操作,CPU不是Redis性能瓶颈,Redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程了!所有就使用了单线程了!
redis的中文网,可在其中查询命令的含义 redis.cn/
五种基本类型,三种特殊类型
String List Set Hash Zset
bitmaps hyperloglogs geospatial
三、Linux下安装redis
1、官网下载压缩包
2、将压缩包传进linux中
3、解压
tar -zxvf [name]
4、配置基本的环境
yum install gcc-c++ c++的环境安装
make 下载很多的环境
5、redis的默认安装路径在usr/local/bin
6、将conf文件拷贝到bin目录下,方便操作
7、修改conf文件,使其后台启动
8、启动服务
9、连接客户端
注:若设置有密码,需要使用 auth [password] 指令来连接客户端
10、关闭
四、基本命令
开启服务
redis-server ? '?'表示conf文件的路径
redis-cli -p 6379 连接客户端
auth [password] 输入密码
退出服务
shutdown 关闭连接
exit 退出
设置与查看数据
set [key] [value] 设置键值对
key * 查看当前所有键
exists [key] 查看该key下有几个value
get [key] 获取value
type [key] 查看该key是什么类型
设置过期时间
expire [key] [time] 设置该键值对的过期时间,秒为单位
ttl [key] 查看当前key的剩余时间
五、类型概述
一、String(字符串)
二、List
在redis中,可以将list玩成 栈、队列、阻塞队列
所有的list命令都是以l开头
lpush 将一个或多个值插入到列表头部(左)
rpush 将一个或多个值插入到列表尾部(右)
lrange [x,y] 获取区间内的数据
lpop [key] 从列表头部(左)移除
rpop [key] 从列表尾部(右)移除
lindex [key] [index] 获取该下标处的值
llen [key] 获取该key的长度
lrem [key] [count] [value] 移除count个该key下指定的vlaue(可以存在重复的value)
ltrim key start stop 截取指定区间的数据
rpoplpush list newlist 移除列表最后一个元素并将其添加到新的列表中
三、Set
set中是无序不可重复
set的指令都是以s开头
sadd [key] [value]
smembers [key]
sismember [key] [value]
srem [key] [value] 移除
四、Hash
map集合,key-map,此时这个值是一个map集合
指令由h开头
hgetall [key] 获取所有的数据(会将map的k-y一并查出)
hdel [key] [map-key] 删除某个数据
五、Zset(有序集合)
在set基础上增加了一个值,set k1 v1, zset k1 score1 v1
六、Geospatial
官网为:www.redis.net.cn/order/3685.…
geoadd# 将指定的地理空间位置(纬度、经度、名称)添加到指定的key中
geopos# 从key里返回所有给定位置元素的位置(经度和纬度)
geodist# 返回两个给定位置之间的距离
georadius# 以给定的经纬度为中心, 找出某一半径内的元素
GEORADIUSBYMEMBER
六、事务
Redis单条命令是保证原子性的,但是事务不保证原子性
原子性:要么同时成功要么同时失败
reids事务本质 一组命令的集合!一个事务中的所有命令都会被序列化,在执行过程中,按照顺序执行!
一致性、顺序性、排他性!
redis事务没有隔离级别的概念
所有命令在事务中,并没有直接被执行,只有发起执行命令时,才会被执行
正常执行事务
- 开启事务(multi)
- 命令入队()
- 执行事务(exec)
放弃事务
编译型异常(代码有问题,命令有错),事务所有命令都不会执行
运行时异常(1 / 0),若事务队列存在语法错误,那么执行时,其他命令正常执行,错误命令抛出异常
监控
悲观锁
- 认为什么时候都会出现问题,故而什么时候都加锁
乐观锁
- 认为什么时候都不会出现问题,故而什么时候都不加锁;更新数据时判断在此期间是否有人修改过该数据
- 获取version
- 更新时比较version以此来判断是否加锁
redis监控测试 正常情况
在执行watch监视一个对象时,另一个线程修改该监视对象的值,事务便会执行失败(watch可充当乐观锁操作)
七、redis.conf详解
单位
配置文件的单位对大小写不敏感
包含
可以包含多个配置文件
网络
通用
如果守护进程为yes,便需要一个pid文件
日志的类型
日志的文件名
默认数据库数量
快照
持久化,在规定时间内,执行了多少次操作,则会持久化到文件 .rdb .aof
redis是内存数据库,若没有持久化,便断电即失
security
八、持久化 RDB(redis database) AOF(append only file)
redis是内存型数据库,若不将其数据保存到磁盘,一旦服务器出现问题,服务器中的数据也会消失,所以redis需要持久化功能!!!
一、RDB(redis database)
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里。
Redis会单独创建( fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的。这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。我们默认的就是RDB,一般情况下不需要修改这个配置!
rdb保存的文件是dump.rdb
rdb触发机制
- save规则满足的情况下,会自动触发rdb规则
- 执行flushall命令时,会触发rdb规则
- 退出redis时,会产生rdb文件 备份就自动生成一个dump.rdb
如何恢复rdb文件
- 只需将rdb文件放在redis启动目录下即可,redis启动时会自动检查dump.rdb,恢复其中的数据
- 查看需要存的位置
rdb它自己的默认配置几乎已经够用,但依旧需要学习
优点
- 适合大规模的数据恢复
- 如果对数据完整性要求不高
缺点
- 需要一定的时间间隔进行操作,如果reids宕机,最后一次修改的数据便没有了
- fork进程的时候,会占用一定的内存空间
二、AOF(append only file)
将所有的命令都记录下来,history,恢复的时候将该文件执行一遍。
以日志的形式来记录每个写操作,将Redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
aof保存的文件是appendonly.aof
默认是不开启的,需要手动开启
当aof文件出现问题或被改变时
redis-check-aof --fix 执行该命令来修复
优点
- 每一次修改都同步,文件完整性更好
- 默认每秒同步一次,可能会丢失一部分数据
- 从不同步,效率最高
缺点
- 相对数据文件来说,aof远远大于rdb,修复速度比rdb慢
- aof运行效率也比rdb慢,所有reids默认配置是rdb持久化
九、redis主从复制
1、概念
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点。Master以写为主,Slave以读为主
默认情况下,每台Redis服务器都是主节点;
且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
2、主从复制的作用
-
数据冗余∶主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
-
故障恢复︰当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
-
负载均衡︰在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
-
高可用(集群)基石︰除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
3、为什么使用主从复制
一般来说,要将Redis运用于工程项目中,只使用一台Redis是万万不能的(存在宕机),原因如下∶
- 从结构上,单个Redis服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大;
- 从容量上,单个Redis服务器内存容量有限,就算一台Redis服务器内存容量为256G,也不能将所有内存用作Redis存储内存,一般来说,单台Redis最大使用内存不应该超过20G。
电商网站上的商品,一般都是一次上传,无数次浏览的,说专业点也就是"多读少写"。对于这种场景,我们可以使如下这种架构(主库负责写操作,从库负责读操作)︰
主从复制,读写分离!80%的情况下都是在进行读操作!减缓服务器的压力!
架构中经常使用!一主二从!只要在公司中,主从复制就是必须要使用的,因为在真实的项目中不可能单机使用Redis !
4、配置(测试:单机多集群,一主二从)
一般情况下只需要配置从库即可,因为每个redis服务器默认为主库
复制3个配置文件,然后修改对应的信息
- 端口
- pid名字
- log文件名字
- dump.rdb名字(备份文件)
通过命令配置从机
通过命令来配置,只是暂时存在,关机即消失
slaveof [host] [port] 认主机,参数为主机的ip与端口
通过改变配置文件来配置从机 这种配置可以永久存在
5、细节
主机可以写(增删改),从机不能写只能读(查询)!主机中的所有信息和数据,都会自动被从机保存!
测试︰主机断开连接,从机依旧连接到主机的,但是没有写操作,这个时候,主机如果回来了,从机依旧可以直接获取到主机写的信息!
如果是使用命令行,来配置的主从,这个时候如果重启了,就会变回主机!只要变为从机,立马就会从主机中获取值!
6、若主机断开
如果主机断开了连接,我们可以使用 SLAVEOF no one 让自己变成主机!其他的节点就可以手动连接到最新的这个主节点(手动)
如果这个时候主机修复了,只能重新连接!之前的从机连接失效
7、哨兵模式(自动选举主机)
主从切换技术的方法是: 当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。Redis从2.8开始正式提供了Sentinel (哨兵)架构来解决这个问题。
谋朝篡位的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
这里的哨兵有两个作用
- 通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
- 当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。
然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover故障转移操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。
测试
(一主二从)
- 配置哨兵配置文件 sentinel.conf
后面的这个数字1,代表主机挂了,slave投票看让谁接替成为主机,票数最多的,就会成为主机 !
- 启动哨兵
如果Master节点断开了,这个时候就会从从机中随机选择一个服务器!(这里面有一个投票算法!)
规则
如果主机此时回来了,只能归并到新的主机下,当做从机,这就是哨兵模式的规则!
哨兵模式的优缺点
优点︰
- 哨兵集群,基于主从复制模式,所有的主从配置优点,它全有
- 主从可以切换,故障可以转移,系统的可用性就会更好
- 哨兵模式就是主从模式的升级,手动到自动,更加健壮! 缺点︰
- Redis不好啊在线扩容的,集群容量一旦到达上限,在线扩容就十分麻烦!
- 实现哨兵模式的配置其实是很麻烦的,里面有很多选择!
十、redis缓存穿透和雪崩(面试高频、工作常用)
服务器的高可用
Redis缓存的使用,极大的提升了应用程序的性能和效率,特别是数据查询方面。但同时,它也带来了一些问题。其中,最要害的问题,就是数据的一致性问题,从严格意义上讲,这个问题无解。如果对数据的一致性要求很高,那么就不能使用缓存。 另外的一些典型问题就是,缓存穿透、缓存雪崩和缓存击穿。目前,业界也都有比较流行的解决方案。
1、缓存穿透
概念
缓存穿透的概念很简单,用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库,这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
解决方案
- 布隆过滤器 布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力﹔
- 缓存空对象 当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源;
但是这种方法会存在两个问题︰
1、如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键;
2、即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。
2、缓存击穿
概念
这里需要注意和缓存穿透的区别,缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存 ,直接请求数据库,就像在一个屏障上凿开了一个洞 当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导使数据库瞬间压力过大。
解决方案
1、设置热点数据永不过期
从缓存层面来看,没有设置过期时间,所以不会出现热点key过期后产生的问题。
2、加互斥锁
分布式锁∶ 使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。
3、缓存雪崩
概念
缓存雪崩,是指在某一个时间段,缓存集中过期失效,redis宕机
产生雪崩的原因之一,比如在写本文的时候,马上就要到双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。
其实集中过期,倒不是非常致命,比较致命的缓存雪崩,是缓存服务器某个节点宕机或断网。因为自然形成的缓存雪崩,一定是在某个时间段集中创建缓存,这个时候,数据库也是可以顶住压力的。无非就是对数据库产生周期性的压力而已。而缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。
解决方案
1、redis的高可用
这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建的集群。
2、限流降级
这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待
3、数据预热
数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。