Redis基础(理论)
文章目录
是什么:
Redis是key-value数据库(NoSQL一种),Redis数据操作主要在内存,两者(mysql,redis)并不是相互替换和竞争关系,而是共用和配合使用
能干什么:
1.分布式缓存,挡在mysql数据库之前
2.内存存储和持久化(RDB+AOF)支持支持异步内存同步中的数据写在磁盘中,同时不影响继续服务
3.高可用架构搭配(单机,主从,哨兵,集群)
4.缓存穿透,击穿,雪崩
5.分布式锁
6.队列
优势:
1.性能极高:redis最高的读的速度是110000次/秒,写的速度是81000次/秒
2.redis数据类型丰富,不仅仅支持key-value类型的数据,还支持list,set,zset,hash,hyperloglog,streams等数据结构的存储
3.redis支持数据持久化,可以将内存中的数据存放在磁盘中,重启时重新加载在内存中
4.redis支持数据备份,既master-slave模式的数据备份
redis的10大数据类型
1.string:是redis的基础数据类型,一个key对应一个value,是二进制安全的,就是说可以包含任何数据,比如图片,序列化等,string最大存放512M输出
2.list(列表):是简单的字符串列表,按照插入数据的顺序排序,可以添加一个元素到list的头部(左边)或尾部(右边),redis中的list实际上维护的就是一个双端链表(最多包含2的32次方-1)
3.hash(哈希表):是string类型的field和value的映射表,特别适用于存储对象(最多包含2的32次方-1)
4.set:是string类型的无序列表,具有唯一性,和无序性(也就意味着列表中的元素都是唯一的),redis中的set集合是通过哈希表来实现的,所以查询,添加,删除的复杂度都是O(1),(最多包含2的32次方-1)
5.zset(有序列表):和set类型一样,不同的是在每个元素的前面都会关联着一个double类型的分数,redis也就是通过分数对zset中的元素进行排序,zset的元素是唯一的,但是分数确可以重复的
6.GEO:主要用于存储地理位置信息,并对存储信息进行操作,包括添加地理位置的坐标,获取地理位置的坐标,计算两个位置之间的距离,
7.Hyperloglog:是用来做基数统计的,Hyperloglog的优势就是,在输入数据或者体积非常庞大是,计算基数所需的空间总是固定的且很小,每个Hyperloglog的键只需要12kb的内存,就可以计算2的64次方个不同的元素的基数,和元素越多耗费内存越多的集合形成鲜明对比,但是Hyperloglog只是通过输入元素来计算基数,不会像集合一样存储元素本身,所以Hyperloglog不能像集合一样获取到元素的
8.bitmap(位图):bitmap由很多个小格子组成只能存放0和1,用来判断Y/N状态,也就是说bitmap由0和1状态表现的二进制位的bit数组
9.bitfield(位域):通过bitfield命令可以一次性操作多个比特位域(值连续的几个比特位),他会执行一系列操作并返回一个响应数组,,这个数组中的元素对应参数列表中的相应操作的执行结果
10.streams:主要用于消息队列(MQ,Message Queue),redis本身是有一个redis的订阅与发布(pub/sub)来实现消息队列的功能,但是他的缺点是无法持久化,如果redis出现网络断开,或者是宕机,信息就会丢失,而streams就是pub,sub的补充版streams支持序列化和主备复制功能,可以让任何客户端任何时刻访问数据,并能记住每个客户端的位置,还能保证信息不丢失
redis键(key)
keys *:查看当前库所有的key
exists key:判断某个key是否存在
type key:查看key是什么类型的
del key:删除指定的key的数据
unlink key:非阻塞删除,仅仅将keys从keyspace元数据中删除,真正的删除会在后面异步删除
ttl key:查看还有多少秒过期,-1代表永不过期,-2表示已经过期
expire key 秒数:为指定key指定过期时间
move key dbindex(0-15):将当前的数据库的key移动到指定的数据库中
select dbindex 切换数据库【0-15】 ,默认6
dbsize:查看当前数据库key的数量
flushdb :清空当前数据库
flushall:清空所有库
redis持久化
持久化双雄:RDB和AOF
RDB(Redis DataBase):
1.在指定时间间隔,执行数据集的时间点的快照
2.能做什么:在指定时间间隔将内存中的数据集快照写入磁盘,他恢复是从磁盘快照文件直接读取到内存中
3.redis中的RDB在保存快照是全量快照(把内存中的数据全部快照保存在磁盘中)
4…RDB保存的是dump.rdb文件
RDB优势:
1.适合大规模的数据恢复
2.按照业务定时备份
3.对数据完整性和一致性要求不高
4.RDB文件在内存中的加载速度要比AOF快
RDB缺点:
1.在一定间隔时间做一次备份,如果redis服务器在这个时候宕机,就会丢失从当前至最近一次备份之间的数据会丢失
2.内存数据全量同步,如果数据量非常大的回到是I/O严重影响服务器性能
3.RDB依赖于主进程的fork,在大的数据集中,可能会造成服务请求瞬间延迟,fork在备份的时候数据会在内存中复制一份,大致2倍的膨胀性
AOF(Append Only File):
1.以日志的形式来记录每个写操作,将redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取日志文件重新执行语句
2.默认情况下,AOF是关闭的,在配置文件中appendonly yes(开启AOF功能)
3.AOF保存的是appendonly.aof文件
AOF缓冲区三种写回策略:
1.Always:同步写会,每执行一个增,删,改命令执行完立刻同步到日志文件中
2.everysec:每秒写回,每个写命令执行完,只会先把日志写到AOP文件的内存缓存区,每隔1秒把缓冲区的内容写到磁盘
3.no:操作系统控制的写回,每个写操作命令执行先把日志写到AOF文件的缓冲区中有操作系统决定何时把缓冲区内容写会磁盘
AOF优势:
1.更好的保存数据不丢失,性能更高,可做紧急恢复
AOF劣势:
1.相同的数据集的数据而言AOF远远比RDB文件大,恢复速度慢于RDB(AOF都是以一条条的执行命令写入在aof文件中重启时需要一条条的执行)
同时开启RDB和AOF功能:
1.当redis恢复数据的时候,优先载入AOF文件来恢复原始的数据
2.因为通常AOF文件保存的数据集要比RDB文件保存的完整
3.当RDB数据不实时,同时使用两者是服务器重启时仍然只会找AOF文件(那为什么不直接只开AOF呢?原因是:RDB更适合用于备份数据库,留着RDB作为一个万一的手段)
关闭RDB和AOF功能:
RDB:save “”(关闭RDB)
AOF:appendonly no (禁用AOF)
Redis事务
redis事务是什么:
1.可以一次执行多个命令,本质就是一组命令的集合,一个事务中的所有命令都会序列化的,按照顺序的串行化命令不能让其他的命令插入其中
redis能干什么:
一个队列中,一次性,顺序性,排他性的执行一系列命令
Redis中的事务和Mysql中的事务有很大的不同:
1.单独的隔离操作:
redis事务仅仅是保证事务里的操作会被连续的独占执行,redis命令执行是单线程架构的,在执行事务内所有的指令是不可能在去同时执行其他用户的请求
2.没有隔离级别的概念:
因为事务提交前任何命令都不会被实际执行
3.不保证原子性:
redis中的事务不保证原子性,也就是不保证所有的指令同时执行成功或者失败,只有决定是否执行全部指令的能力,没有执行到一半回滚的能力
4.排他性
redis会保证一个事务内的命令依次执行,而不会被其他命令插入
redis事务的使用
1.正常执行 MULTI EXEC
2.放弃事务:MULTI DISCARD
watch监控:
redis使用watch来提供乐观锁定的
悲观锁:每次拿数据的时候都认为别人会修改,所以每次都会把要修改的元素加上锁,别人要想拿到这个数据就需要获取到这个锁才能修改值
乐观锁:每次拿数据的时候都不会认为别人会修改,所以每次都不会给修改的元素加上锁,但是更新的时候会判断此期间有没有别的人去修改这个元素(策略就是:提交版本必须大于记录当前版本才能执行更新)
要先监控在开启multi,保证key的变动在同一个事物内,当redis事物提交时他会先判断被监控的的key是否有被改动,有被改动在事物中对key修改的命令就会失败
总结redis的事务:
开启:以MULTI开始一个事务
入队:将多个命令入队到事务中,接到这些命令不会立刻被执行,而会放到等待执行的队列当中
执行:由EXEC命令触发事务
redis管道
用于解决:优化频繁命令往返造成的性能瓶颈
redis管道是什么:
批处理命令变种优化措施,类似redis原生命令mget,mset
Pipeline与原生批量命令对比:
1.原生批量命令是原子性的(mset,mget),pipeline是非原子性的
2.原生批量命令一次只能执行一类命令,而pipeline支持批量执行不同的命令
3.原生的批量命令是有redis服务器实现的,而pipeline需要服务器与客户端共同完成
pipeline与实务对比:
1.事务具有原子性,管道不具有原子性
2.管道一次将多条命令发到服务器,事务是一条条发的,事务只有接受到exec命令后才会执行,管道不会,执行事务时会阻塞其他命令的执行,而pipeline不会
pipeline的注意事项
1.pipeline缓冲的指令只是会依次执行,不保证原子性,如果执行到异常也会继续执行后续命令
2.使用pipeline组装的命令个数不能太多,不然数据量过大客户端堵塞的时间可能太久,同时服务器也被迫回复一个队列答复,占用很多的内存
redis的发布与订阅
reids的发布与订阅是什么:
是一种通信模式发送者(PUBLISH)发送消息,订阅者(SUBSCRIBE)接受信息可以实现进程之间的信息传递
redis的发布与订阅能干嘛:
redis客户端可以订阅任意数据的频道,类似我们微信关注多个公众号
总结:
Redis可以实现消息中间件MQ的功能,通过发布订阅实现消息的引导和分流。不推荐使用该功能,
专业的事情交给专业的中间件处理,redis就做好分布式缓存功能
redis复制(replica)
是什么:
就是主从复制,master以写为主(能读能写),slave以读为主(只能读不能写)
当master数据变化的时候,自动将新的数据异步同步到其他slave的数据库中
能做什么:
1.读写分离
2.容灾恢复
3.数据别分
4.水平扩容支支撑高并发
基本配置和使用:
配置:在master中要配置requirepass(密码)参数,那么slave中就要配置masterauth来设置效验密码,否则master会拒绝slave的请求
基本命令:
info replication: 可以查看复制节点的主从关系和配置信息
master端:replication 主库ip 主库端口:开启主从(一半写入配置文件内)
slave端:slaveof 主库ip 主库端口:每次与master断开之后,都需要重新连接,除非你配置进redis.conf文件,如果该数据库已经是某个主数据库的从数据库,那么会停止和原主数据库的同步关系转而和新的主数据库同步,重新建立主从
slaveof no one :使当前数据库停止与其数据库同步,自己变成主数据库,自立为王
主从复制的工作原理,流程:
1.slave启动,同步初请
slave启动成功连接到master后会发送一个sync命令
slave首次全新连接master,一次完全同步将被自动执行,slave自身原有的数据会被master数据覆盖清除
2.首次连接,全量复制
master节点收到sync命令后会开始在后台保存快照,同时将收集到的用于修改的命令都缓存起来,master节点执行RDB持久化后
master就会把RDB快照文件和缓存的命令发送到slave,以完成第一次的同步
slave端接收到数据库文件后把文件放在缓存中,从而实现复制
3.心跳持续,保持通讯
设置保持通讯心跳包的秒数(repl-ping-replica-period 10)
4.进入平稳,增量复制
master接受到修改命令后会自动依次传给slave,完成同步
5.从机下线,重连续传
master发现slave回来后只会把slave下线之后的数据更新到slave数据库中(并不会重新把全部的数据重新复制给slave)
主从复制缺点
1.复制延时,信号衰减
2.默认情况下master宕机后从机会一直等待master主机的归来,并不会重新选举一个主机
哨兵
是什么:
检查master主机是否还存活中,如果发现master已经不存活就会投票选举新的master
能干什么:
1.主从监控
监控主从redis是否正常运行
2.消息通知
哨兵可以将故障转移的结果发送给客户端
3.故障转移
如果哨兵发现master异常,则会进行主从切换,将slave中选举出新的master
4.配置中心
客户端通过哨兵连接来获取当前redis服务的主节点地址
基本使用
一半redis的哨兵个数都是3个及以上(单数)因为选举master的时候都是通过各个哨兵的头条来选举
修改自己哨兵的配置文件(
bind 0.0.0.0
daemonize yes
protected-mode no
port 26379
logfile "/myredis/sentinel26379.log"
pidfile /var/run/redis-sentinel26379.pid
dir /myredis
sentinel monitor mymaster 192.168.111.169 6379 2
sentinel auth-pass mymaster 111111
根据自己实际情况修改上面模板)
启动原有的redis主从,启动redis哨兵
把原有的master关掉这个redis服务,哨兵投票选举出新的master之前的slave会直接与新的master建立主从关系
流程和选举原理
流程:
当一个主从配置中的master失效之后,哨兵就会选举出新的master用于取代旧的master工作,之前与旧master建立连接的slave会重新与新的master建立建立(一般建议哨兵的个数采取奇数台,防止一台哨兵与master无法连接时会误操作)
选举原理:
SDown(主观下线):就是单个哨兵发现master主机已经掉线了,判断master主机主观下线的过程(在哨兵上发送ping命令给master主机发现master没有回复,就达到SDown的条件)
ODown(客观下线):需要一定数量的哨兵票数,多个哨兵打成一直意见才能认为一个master客观上已经下线
选举出领导者哨兵(选出兵王):当主节点被判断客观下线以后,各个哨兵节点会进行协商,先选举出一个领导者(兵王),被选出的兵王进行故障转移(通过Raft算法获取兵王)
兵王选举新的master的流程:
一个哨兵发现master下线后达到主观下线的要求后,然后那个哨兵就会通告给其他的哨兵让他们去ping master主机发现都ping不通后打成客观下线的要求,然后其他本来跟着旧master的从服务器就会执行slaveof no one,然后通过哨兵的投票选举选出新的master,然后在从机在重新指定成为新master的从机,当旧的master回归,新的master并不会重新变成slave,而是变成新的master的slave
哨兵使用的建议:
1.哨兵节点的数量应为多个,哨兵本身也是集群,保证高可用
2.一般哨兵的个数都是奇数个
3.各个哨兵的配置都应该一致
4.如果哨兵节点部署在Docker容器里面,要特别注意端口的正确映射
5.哨兵集群+主从复制,确保数据0丢失
集群
是什么
redis集群是一个提供在多个redis节点间共享数据的程序集,redis集群可以支持多个master
能做什么
一、redis集群支持多个master,每个master又可以挂载多个 slave
1.读写分离
2.支持数据的高可用
3.支持海量的数据的读写操作
二、.由于cluster自带哨兵的故障转移机制,内置高可用的支持,无需再去使用哨兵功能
三、客户端与redis的节点连接,不在需要连接集群中的所有节点,只需要连接任意一个集群上的可用节点即可
四、槽位slot负责分配到各个物理服务器节点,由对应的集群来维护节点,插槽和数据之间的关系
集群算法-分片-插槽slot
1.redis集群的槽位slot
redis集群没有使用一致性hash,而是引入了哈希槽的概念,redis集群有16384个哈希槽,每个key通过crc16算法的效验对16384取模来决定放在哪个槽,集群中的每个节点负责一部分的哈希槽
2.redis集群的分片
使用redis集群时我们会将存储的数据分布在不同的redis服务器上,这就被称为分片,简单来说就是,集群中的每个redis实例都可以被称为整个数据的一个分片
我们如何找到相应的key:我们对key进行crc16算法处理并通过对从分片取模,使用确定性哈希函数,这意味着给定的key将多次始终映射到一个分片,我们就可以读取到特定key的位置
槽位slot和分片这两个的优势
方便扩容和缩容和数据分派查找
slot槽位映射,一般有三种解决方案
1.哈希取余分区
当redis集群发生变化时之前存入的数据就会重新计算hash值在放在对应的redis主机上
2.一致性哈希算法分区
能做什么:当redis集群的服务器台数发生变动时,尽力减少对客户端到服务器的映射的关系
三个步骤
1.构建一致性哈希环
一致性哈希算法必然有个hash函数并按照算法产生hash值,这个算法的所有可能哈希值会构成一个全量集,这个集合可以成为一个hash空间(0,2的32次方-1),这是一个线性空间,在算法中逻辑的把这个线性空间收尾相连,在逻辑上形成一个哈希环,整个空间按顺时针方向组织
2.redis服务器ip节点映射
将集群中各个ip节点映射到环上的某个位置,经过ip地址的哈希函数计算(hash(ip)),使用ip地址哈希后在环空间的位置
3.key落到服务器的落键规则
当我们需要存储一个kv键值对时,首先计算key的hash值,然后通过hash算法算出key在环上对应的位置,然后从此位置沿环顺时针行走,遇到的第一台redis服务器它就把这个键值对存储到该节点上
为什么redis集群的最大槽位数是16384个?(crc16算法其实可以产生2的16次方65535个哈希槽但是为什么只用16384个呢)
一、如果槽位为65535,发送心跳信息的消息头就达到了8k,发送的心跳包就过于庞大
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。 当槽位为65536时,这块的大小是: 65536÷8÷1024=8kb
当槽位为16384时,这块的大小是:16384÷8÷1024=2kb
二、redis的集群主节点数量基本不可能超过1000个
集群的节点越多,发送心跳包的个数就越多,就会导致网络拥堵(所以作者不建议redis集群的服务器个数超过1000台,redis集群服务器台数做多16384台)
三、槽位越小,节点少的情况下,压缩比高,容易传输
redis主节点的配置信息中它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输的过程中都会对bitmap进行压缩,bitmap的填充率=slots/N(N表示节点数),如果redis服务器的节点很少,hash槽位比较多的时候他的压缩率就比较低
redis集群不保证强一致性,这意味着在特定的条件下,redis集群可能会丢掉一些被系统收到的写入请求命令!!!