redis的核⼼技术点
总结归纳redis的核⼼技术点如下:
杂七杂⼋
1、redis是基于C语⾔开发、纯内存运⾏的⼀个key-value型数据库,redis是单线程实现的。
2、利⽤队列技术,将并发访问转换为了串⾏访问,减少了传统数据库串⾏控制的开销。
3、redis⽀持的语⾔由:C、C++、java、php、Node.js、GO等。
⼀、redis的五种常⽤数据类型
string list set sorted set hash
⼆、为什么redis是单线程的?为什么redis单线程还可以这么快?
  redis是基于内存进⾏操作的,CPU则不是redis的性能瓶颈,他的性能瓶颈很有可能是机器的内存⼤⼩和⽹络的带宽。能⽤单线程实现,且CPU⼜不是性能瓶颈,⾃然也不会使⽤更⿇烦的多线程实现了。
  ⾄于redis为什么速度这么快呢,主要有⼀下⼏个⽅⾯:
1、完全基于内存,绝⼤部分操作都是对内存进⾏操作,速度⾮常快。数据在内存中以类似hashmap的⽅式存储,⽽hashmap的优势就是查询和操作的时间复杂度都是O(1)。
2、数据结构简单,redis这五种数据结构都是专门进⾏设计的,因此速度更快。
3、采⽤单线程,避免了多进程、多线程之间的切换,不⽤考虑上下⽂切换和竞争,不存在加锁释放锁等操作。
4、使⽤了I/O多路复⽤和⾮阻塞IO的⽅式。
5、redis⾃⼰设计了⼀套VM通信机制,使⽤起来更加快捷。
三、redis的主从复制
优点:主从复制实现了数据的多机备份,对于读操作实现了负载均衡和故障恢复。
redis五种数据结构缺点:⽆法做到写操作负载均衡,集的存储能⼒受到单机的限制。
1、redis的主从复制,能很⼤程度上解决单点故障对整个系统所造成的影响,redis的集关系为:⼀主多从。
2、主节点启动后,从节点可以通过slaveof 主节点IP地址主节点redis端⼝的⽅式来向主节点注册从节点。
3、从节点注册完成后,会⾃动向主节点发送sync命令来全量复制主节点的数据信息。
4、主节点执⾏gbsave命令,将⽣成的快照发送给从节点,从节点进⾏数据同步。
5、上述操作执⾏完后,如果主节点收到新的写⼊操作,主节点将把新的操作发给从节点,从节点将进⾏增量复制,更新⾃⼰的数据信息。
四、redis的哨兵
优点:在主从复制的基础上,哨兵实现了⾃动化的故⾏恢复。
缺点:写操作⽆法时间负载均衡,存储能⼒受到单机的限制。
1、主从集启动。
2、哨兵集启动,监测主从集中的每⼀台redis的状态,检测的⽅式为哨兵向集中每⼀台机器每秒发送⼀个PING指令,如果响应时间超过了预定的范围,则判断该节点下线。
3、如果leader主节点宕机,哨兵能⽴马相应,在剩下的从节点中选出主节点对外服务。
五、当redis数据量急剧增加的时候怎么办?
  我们都知道,redis默认的持久化⽅式是RDB,这种持久化⽅式当数据量⽐较⼤的时候进⾏持久化,将严重影响redis的各种性能。原因:redis在使⽤rdb的⽅式进⾏持久化的时候,会fork⼦进程来完成,⽽fork操作的时间跟数据量是成正相关的,并且fork操作的时候会阻塞主线程。 因此数据量越⼤,RDB持久化时间越长,整个集的综合性能将变得很差,所以我们必须出⼀种办法来解决这种问题。
  解决办法:增加redis实例的个数。在⾯向百万、千万级别的⽤户规模时,横向扩展的redis切⽚集会是⼀个⾮常好的选择。但是我们需要解决两个问题:
数据切⽚后,怎么在多个实例之间存储?
客户端在访问数据的时候,怎么确定需要访问的数据在那台实例上?
1、数据切⽚和实例的对应分布关系
  在Redis 3.0后,官⽅提供了⼀个叫redis cluster的⽅案,来实现切⽚集,其中就规定了数据和实例
的对应关系。具体来说,redis cluster中定义了⼀个叫哈希槽的东西,来处理数据和实例之间的对应关系,⼀个切⽚集⼀共有16384(2^14)个哈希槽,这些哈希槽类似于数据分区,每个键值对会根据他的key,被映射到⼀个哈希槽中。
  具体映射过程如下:⾸先根据key值,按照CRC16算法得出⼀个16bit的值,然后⽤这个值对16384(2^14)取模运算,得到⼀个0~16383之间的值,即得到哈希槽的编号。其次,redis会⾃动把这些哈希槽均匀的分布在集实例上。例如:集⼀共有N台实例,那么每台实例上⼤概有16384/N个哈希槽。当然我们也可以通过参数进⾏指定。
2、客户端如何定位数据所在的实例?
  客户端在定位数据的时候,他所处的哈希槽是可以在客户端通过计算得出来的。但是要进⼀步定位到实例,还需要知道哈希槽分布在哪个实例上。
  当集刚开始启动的时候,每个实例只知道⾃⼰分配的哈希槽信息,并不知道其他实例分配的哈希槽信息。那么韦森么客户端可以在访问任意⼀个实例的时候获取所有哈希槽信息呢?这是因为redis实例回把⾃⼰的哈希槽信息发给和它相连的其他实例,来完成哈希槽分配信息的扩散。当所有实例之间完成互通后,每个实例就有所有哈希槽的映射关系了。
  客户端收到哈希槽的消息后,在本地进⾏缓存。客户端在请求键值对信息时,先计算哈希槽的值,然后再根据缓存的映射关系去请求相应的实例。
总结:在⾯对数据增加的时候,虽然增加内存这种纵向扩展的⽅法⽐较简单直接,但是会造成数据库的内存增加⽽导致性能降低。⽽redis 的切⽚集提供的横向扩展模式,也就是使⽤多个实例,并给每个实例配置⼀定数量的哈希槽,数据可以通过键的哈希值映射到哈希槽,再通过哈希槽分散保存在不同的实例上。这样做的好处是扩展性更强,不管有多少数据,切⽚集都能轻松应对。
六、redis的持久化⽅式
1、RDB⽅式,为redis默认开启持久化⽅式。该⽅式每隔⼀定时间进⾏⼀次持久化,输⼊shutdown命令下线的时候,会进⾏⼀次持久化,输⼊bgsave也会进⾏⼀次持久化。
优点:RDB的⽂件紧凑,体积⼩,适合⽹络传输以及全量复制。速度⽐AOF快,对性能影响较⼩。
缺点:兼容性差,需要使⽤特定格式的⽂件,不同版本的RDB⽂件不适⽤。
2、AOF⽅式,为redis默认关闭持久化⽅式。该⽅式默认每秒进⾏⼀次持久化。
优点:兼容性好,数据更安全。
缺点:⽂件⼤,恢复速度慢,对性能影响⼤。
七、redis常见性能问题和解决⽅案
1、Master主节点最好不要做任何持久化⼯作,如果数据⽐较重要,则让某个slave从节点进⾏每秒⼀次的AOF备份策略。
2、为了主从复制的速度以及整个架构的稳定性,所有机器尽量安排在同⼀个局域⽹内。
3、避免在压⼒很⼤的主节点上增加从节点,以免造成主节点意外下线。
⼋、redis的三种删除策略
1、定时删除,在设置健的同时设定定时任务,在规定时刻删除该键。
优点:对内存⽐较友好,能及时清楚不需要的数据,节省空间。
缺点:对cpu不友好,如果同⼀时间过期的键⽐较多,将会⼤量占⽤cpu的使⽤,影响该机器的响应时间和吞吐量。
2、惰性删除,程序不管过期的键,但每次在获取该键信息的时候,进⾏判断看是否过期。过期则删,
否则返回。
优点:对CPU⽐较友好,不会占⽤cpu太多的资源。
缺点:由内存溢出的可能。
3、定期删除:由于定时删除会占⽤太多CPU的时间,影响服务的整体性能;惰性删除会浪费太多内存空间还有内存泄漏的风险,于是出现了⼀种整合折中这两种策略的定期删除策略。
每隔⼀段时间,程序对数据库进⾏⼀次检查,删除⾥⾯过期的键,⾄于检查多少、删多少则由专门的算法根据当前的实际情况进⾏决定,并通过限制删除操作的时长和频率来减少对CPU的影响。
九、缓存穿透、击穿、雪崩
1、缓存穿透:某些请求查询的数据不存在,因此redis中并为缓存。然后⼜去mysql中查询,当然也查不到。⼤量这样的请求穿过redis进⼊mysql造成mysql崩溃的现象叫缓存穿透。
2、缓存击穿:单个热点数据过期被删除,紧接着有⼤量请求访问该数据,于是redis转发到mysql,导致mysql崩溃的现象叫缓存击穿。
3、缓存雪崩:⼀⼤批数据⼏乎同时过期被删除,然后⼜有⼤量请求访问redis,这次的规模⽐缓存击穿的规模更⼤,造成mysql崩溃的现象叫缓存雪崩。
缓存穿透的解决办法:布隆过滤器,擅长在超⼤数据集中查需要的数据是否存在。如果返回不存在,则⼀定会不存在,如果返回存在则有可能存在也有可能不存在。
缓存击穿和缓存雪崩的解决办法:设置热点数据永不过期。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。