道听途说redis Posted 2021-04-07 小时候有好奇心
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了道听途说redis相关的知识,希望对你有一定的参考价值。
数据类型
redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。简略提一下:
日常使用比较多的一种数据类型,就是简单的k/v,但是可能有些小伙伴不知道这种类型的一种用法bitmap(二进制位图)。也就是说,可以在redis内使用bitmap进行位运算来满足一些特殊场景需求,例如用一个bitmap不同位来记录一批用户当日是否登录,一位映射一个用户,这样可以直接使用redis支持的bitmap命令来快速获得一天内这批用户的登录用户数。
在许多业务场景需要使用的数据类型,例如用户不同维度个人信息存储到一个key中使用hashkey区分维度数据,还例如分页查询可以对同一个查询条件为key的不同页面数据做hashkey的区分,这里也不赘述了。
相对上面两种数据类型,接下来的三种的应用可能要少很多,选择哪种数据类型主要还是看业务场景。
list日常使用,主要为了实现数组、栈、队列的数据结构特性。可以结合业务需求选择需要的结构特性。
无序且不重复,一种应用场景可以拿它做发号器,例如抽奖把奖品存入set再根据规则pop出每次抽奖结果。
带分数的有序set,如果要做一个热门排行榜可以使用它,用热门程度做分数redis自动帮你维护排序。
这里非实战,不会搬出整体集群配置,只点出几个关键点。
可以通过设置节点的从属关系实现主从集群,两种设定追随主节点的方式:
在redis-cli客户端命令行操作,redis版本4.0之前用SLAVEOF 4.0之后用REPLICAOF
> REPLICAOF localhost 6379
执行命令后当前节点追随localhost:6379的redis实例节点,当localhost:6379 接收从追随请求时,当前节点成为slave,首次追随主时,主会自动bgsave生成一份dump.rdb落磁盘然后发给从,进而完成首次的数据同步。
-> redis-server ./6381.conf --replicaof 127.0.0.1 6379
当节点6381启动连接上主后,主节点会save一个rdb到磁盘,然后把rdb发给当前节点。当前节点会先flush删了自己所有的旧数据,然后load主给的rdb,进而完成追随后的首次主从数据同步。
主从的集群模式下,主节点会记录所有追随它的从节点,主从间保持通信,进而从挂机时主会得知。主节点为每个从节点维护一个队列记录当前数据同步的offs et 。 从节点挂机重启后,如果要重新追随主节点,则会获得增量数据。需要注意的是,队列的大小有限制。可能会存在从节点重启时,主节点给它维护的队列已有数据被挤出队列,进而造成主从数据不同步的情况。
简单的主从模式还需要注意的一点是,它不具备自动故障转移的功能,也就是说主宕机时,需要人为手动处理,例如在redis-cli客户端 执行命令把当前从节点切换成主:
针对主从模式无法自动故障转移,后来有了哨兵模式,也就是在主从模式基础上,加入特殊的角色
哨兵。哨兵的作用就是在主宕机后,做决策,把某个从节点选出来并切换成主。进而完成主宕机后的自动故障转移。
哨兵的启动需要拥有自己的配置文件告诉它监听哪些集群,某集群主是哪个节点,例如如下配置:
port 26379
sentinel moniter name1 127.0 .0 .1 6379 投票权重值
上面配置了一个哨兵节点的端口是26379,监听的集群叫name1(需要对集群命名的原因实际是哨兵可以监听多个集群,需要通过名字区分,当然这不是重点,实际应用中,一套哨兵只监听单一的一个集群),该被监听集群主节点是127.0.0.1:6379,投票权重值实际是一个数字,是一次决策投票通过的投票数量。
哨兵的存在是对主故障的自动发现处理,则我们需要哨兵本身可以保证一个高可用的状态,因而需要多个哨兵组成哨兵的集群来一起监听集群。多个哨兵就有多个决策,为避免脑裂,正常配置哨兵都是遵守过半原则(可以自行百度),即哨兵个数过半数(n/2+1)的权重值。例如我们要配3台哨兵,则投票权重可以配2,如下:
sentinel moniter name1 127.0 .0 .1 6379 2
看上面对name1集群的选主投票,只需要2个哨兵投票成功既可以切换。
哨兵在启动时,从配置文件可以获知自己需要监听的集群信息(主要是主节点),进而连接上被监听的主,和主节点间通过发布订阅保持联系,会从主节点拉取集群从节点的信息。
以上面的例如来说,3台哨兵,权重设2。当不少于2个哨兵发现主宕机后发起选主,通过对各个从节点数据等信息分析,投出获得不少于2个哨兵投票的从节点,然后再让一个哨兵去对该从节点进行升级主的操作:
切换成功,每个哨兵会自动修改自己的配置文件,把新的主节点信息替换进去(即修改
sentinel
moniter )。
可见,哨兵就是把人工监听主故障和人工切换主节点给完成了。
随着业务量的增加,单主redis已经无法承载越来越大的数据量和并发量,cluster集群的出现可以解决这个问题。cluster集群把单主变成多主,数据分片到多台redis节点上,实现数据分治。流量也被打到多台机器上。再对每个主加上从的配置完成高可用。在这个模式下,cluster集群中的每个主还承担了类似哨兵的工作,即主的自动故障转移。自动故障转移原理和哨兵类似,不赘述。
了解过redis工作原理的朋友都知道redis是单线程的,后来又有人说redis是多线程的。是单线程还是多线程得说明你描述的角度是什么。
在redis6.0之前redis是单线程的,即reids请求在redis内部工作流中是串行的,redis必须完成当前请求的io读取计算处理和返回才可以进行下一条请求的读取处理和返回。因此redis不存在多线程并发的问题。
在6.0开始redis支持了多线程,这个多线程其实是单个工作线程和多个的io线程。当多个请求打到redis,多个io线程同时去读取请求,先读完的请求可以被工作线程执行,当执行完成后,接着执行其他已被io读取完成的请求。执行结果会被io线程处理。也就是说请求的计算过程和别的请求的io处理可以并行。可见每个请求的非io处理过程还是在redis单线程即工作线程中串行执行的。
redis的持久化分rdb和aof,当然可以不开启持久化。rdb是把当前全量数据做一个二进制落盘,aof是记录每一次的redis指令。对rdb和aof的选择,可单独使用也可以混合使用,修改对应的redis配置即可。
单独使用rdb的问题就在于什么时机做一次全量的落盘。单独使用aof,虽然redis对重复写的指令做了抵消合并,整个文件的体量还是会比较大(单纯的一次get执行,在aof中有很多指令记录,如果删除了大量key,可能存在redis的有效数据量很小,但aof会很大)。支持aof和rdb混合使用的版本,开启混合模式后,会把rdb的全量加到aof上,然后追加增量的aof。这种模式可以很好的解决了aof体量大、无用指令过多的问题,还有rdb落盘时机的问题。
缓存穿透
是指查询数据库中不存在的数据,这种数据不存在,正常不会设置无结果的缓存,因为无效入参的量不可估计。如果某块业务必须要解决缓存穿透的问题,则可以考虑布隆过滤器过滤绝大部分无效入参的请求。
缓存击穿
指被热点访问的key,在缓存失效期间大量流量走到数据库的场景。解决击穿的问题,需要对特定的热点key缓存进行特殊处理,例如加分布式锁把流量拦住,只让一个请求访问数据库再写到缓存,这次场景需要考虑分布式锁的实现,要避免死锁,实现比较复杂。是否要对某些key做击穿的处理需要考虑业务需求和流量场景。
缓存雪崩
雪崩的场景是大量的热点key在同一时间都是失效状态,也就是大量key的击穿。遇到这种问题需要考虑:是否需要对缓存预热;是否有大量热点key设置了同一过期时间,是则打乱过期时间。
以上是关于道听途说redis的主要内容,如果未能解决你的问题,请参考以下文章
如何利用redis来进行分布式集群系统的限流设计
jedis连接redis
2022-09-11 mysql列存储引擎-宣讲-第二讲-一条SQL在Tianmu引擎中的运行
redis存储session配制方法
机器学习游学记
Redis实现分布式锁(设计模式应用实战)