精华内容
下载资源
问答
  • redis为什么需要实现读写分离master持久化对于主从架构的安全保障的意义`redis replication`最基本的原理redis主从架构的核心原理主从复制的断点续传无磁盘化复制过期key处理复制的完整流程数据同步相关的核心机制...
    • redis为什么需要实现读写分离
    • master持久化对于主从架构的安全保障的意义
    • `redis replication`最基本的原理
    • redis主从架构的核心原理
      • 主从复制的断点续传
      • 无磁盘化复制
      • 过期key处理
      • 复制的完整流程
      • 数据同步相关的核心机制
      • 全量复制(耗时)
      • 增量复制(异常情况)
      • heartbeat
      • 异步复制
    • 总结
    • 特别感谢

    redis为什么需要实现读写分离

    redis高并发与分布式系统的高并发之间的关系:
    大量使用redis技术的分布式系统,它的高并发能力与redis的高并发密切相关,因此要向提升分布式系统的高并发能力,就要提升redis在高并发场景下的性能。

    如果我们生产环境中使用的redis是单机的,那么redis的整体性能一定是有瓶颈的。因此,我们说redis支撑高并发的瓶颈在于单机,那么如果redis要支撑10万+的并发,应该怎么破呢?

    首先需要明白一个事实,单机的redis要想支撑超过10万+的QPS,是不太可能的,正常情况下单机的QPS在几万级别。

    要想支撑10万+的QPS,我们可以通过基于一主多从的读写分离架构来实现,一台机器作为master,其他机器作为slave,写请求只通过master,slave用来接收读请求。项目中使用到redis的场景,一般是读多写少的,因此我们可以用多个slave来缓解读请求压力,达到支撑10万+读QPS的目的。

    需要说明的是,redis主从架构实现了读写分离,缓解了单机的读请求压力,提升了整个redis的读QPS。如果我们需要实现更高的读QPS,就可以加一些slave节点,所以我们说redis主从架构其实是可支持水平扩展的读高并发架构

    接下来,我们就来分析一下redis主从架构(redis replication)的相关原理。

    master持久化对于主从架构的安全保障的意义

    在正式讲解主从架构的原理之前,我们先聊一下master持久化对于主从架构的安全保障。

    如果采用了主从架构,那么建议必须开启master node的持久化
    不建议用slave node作为master node的数据热备,因为那样的话,如果你关掉master的持久化,可能在master宕机重启的时候数据是空的,然后可能一经过复制,slave node数据也丢了。

    我们设想一个场景,master关闭了RDB和AOF持久化,那么此时master中的数据全部在内存中;此时,master宕机重启后,本地磁盘中是没有数据可以恢复的,就会直接认为本地数据为空的,那么就会将空的数据集同步给slave,那么slave的数据会被全部清空,造成slave数据百分百丢失。

    因此我们一定要注意:master节点,必须要使用持久化机制

    其次,master的各种备份方案,也是要做的,万一说本地的所有文件丢失了,我们还可以从备份中挑选一份rdb去恢复master,这样才能确保master启动的时候,是有数据的。

    redis replication最基本的原理

    780e68d9d3d8e725adf66f071e8abc5e.png
    1. redis采用异步方式复制数据到slave节点,不过redis 2.8开始,slave node会周期性地确认自己每次复制的数据量
    2. 一个master node可以配置多个slave node
    3. slave node也可以连接其他的slave node
    4. slave node做复制的时候,是不会block master node的正常工作的(异步)
    5. slave node在做复制的时候,也不会block对自己的查询操作,它会用旧的数据集来提供服务; 但是复制完成的时候,需要删除旧数据集,加载新数据集,这个时候就会暂停对外服务
    6. slave node主要用来进行横向扩容,做读写分离,扩容的slave node可以提高读的吞吐量

    redis主从架构的核心原理

    当启动一个slave node的时候,它会发送一个PSYNC命令给master node。

    如果这是slave node重新连接master node,那么master node仅仅会复制给slave部分缺少的数据; 否则如果是slave node第一次连接master node,那么会触发一次full resynchronization(全量复制)

    开始full resynchronization的时候,master会启动一个后台线程,开始生成一份RDB快照文件,同时还会将从客户端收到的所有写命令缓存在内存中。RDB文件生成完毕之后,master会将这个RDB发送给slave,slave会先写入本地磁盘,然后再从本地磁盘加载到内存中。然后master会将内存中缓存的写命令发送给slave,slave也会同步这些数据。

    slave node如果跟master node有网络故障,断开了连接,会自动重连。master如果发现有多个slave node都来重新连接,仅仅会启动一个rdb save操作,用一份数据服务所有slave node。

    主从复制的断点续传

    从redis 2.8开始,就支持主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制一份。

    master node会在内存中常见一个backlog,master和slave都会保存一个replica offset还有一个master id,offset就是保存在backlog中的。如果master和slave网络连接断掉了,slave会让master从上次的replica offset开始继续复制。

    但是如果没有找到对应的offset,那么就会执行一次resynchronization

    无磁盘化复制

    master在内存中直接创建rdb,然后发送给slave,不会在自己本地落地磁盘。

    repl-diskless-sync repl-diskless-sync-delay,等待一定时长再开始复制,因为要等更多slave重新连接过来。

    过期key处理

    slave不会过期key,只会等待master过期key。如果master过期了一个key,或者通过LRU淘汰了一个key,那么会模拟一条del命令发送给slave。

    复制的完整流程

    d65fb04436fa9ab1dc9167d0452cf0a1.png
    1. slave node启动,仅仅保存master node的信息,包括master node的host和ip,但是复制流程没开始
      master host和ip是在redis.conf里面的slaveof配置的
    2. slave node内部有个定时任务,每秒检查是否有新的master node要连接和复制,如果发现,就跟master node建立socket网络连接
    3. slave node发送ping命令给master node
    4. 口令认证,如果master设置了requirepass,那么slave node必须发送masterauth的口令过去进行认证
    5. master node第一次执行全量复制,将所有数据发给slave node
    6. master node后续持续将写命令,异步复制给slave node

    数据同步相关的核心机制

    这里指的是第一次slave连接master的时候,执行的全量复制细节
    1. master和slave都会维护一个offset
      master会在自身不断累加offset,slave也会在自身不断累加offset slave每秒都会上报自己的offset给master,同时master也会保存每个slave的offset
      这个倒不是说特定就用在全量复制的,主要是master和slave都要知道各自的数据的offset,才能知道互相之间的数据不一致的情况。
    2. backlog(备份日志)
    • master node有一个backlog,默认是1MB大小
    • master node给slave node复制数据时,也会将数据在backlog中同步写一份
    • backlog主要是用来做全量复制中断后的增量复制
    1. master run id
      info server,可以看到master run id 如果根据host+ip定位master node,是不靠谱的,如果master node重启或者数据出现了变化,slave node应该根据不同的run id区分,run id不同就做全量复制 如果需要不更改run id重启redis,可以使用redis-cli debug reload命令只要master的run id变化了,slave就执行一次全量复制
    2. psync
      从节点使用psync从master node进行复制,psync runid offset master node会根据自身的情况返回响应信息,可能是FULLRESYNC runid offset触发全量复制,可能是CONTINUE触发增量复制

    全量复制(耗时)

    1cdaba79f113b0485df995f8839be9df.png
    1. master执行bgsave,在本地生成一份rdb快照文件
    2. master node将rdb快照文件发送给salve node,如果rdb复制时间超过60秒(repl-timeout),那么slave node就会认为复制失败,可以适当调节大这个参数
    3. 对于千兆网卡的机器,一般每秒传输100MB,6G文件,很可能超过60s
    4. master node在生成rdb时,会将所有新的写命令缓存在内存中在slave node保存了rdb之后,再将新的写命令复制给slave node
    5. client-output-buffer-limit slave 256MB 64MB 60,如果在复制期间,内存缓冲区持续消耗超过64MB,或者一次性超过256MB,那么停止复制,复制失败
    6. slave node接收到rdb之后,清空自己的旧数据,然后重新加载rdb到自己的内存中,同时基于旧的数据版本对外提供服务
    7. 如果slave node开启了AOF,那么会立即执行BGREWRITEAOF,重写AOF
    rdb生成、rdb通过网络拷贝、slave旧数据的清理、slave aof rewrite,很耗费时间
    如果复制的数据量在4G~6G之间,那么很可能全量复制时间消耗到1分半到2分钟

    增量复制(异常情况)

    1. 如果全量复制过程中,master-slave网络连接断掉,那么slave重新连接master时,会触发增量复制
    2. master直接从自己的backlog中获取部分丢失的数据,发送给slave node,默认backlog就是1MB
    3. master就是根据slave发送的psync中的offset来从backlog中获取数据的

    heartbeat

    主从节点互相都会发送heartbeat信息

    master默认每隔10秒发送一次heartbeat,salve node每隔1秒发送一个heartbeat

    异步复制

    master每次接收到写命令之后,先在内部写入数据,然后异步发送给slave node。

    总结

    本文先从为什么redis需要实现读写分离来阐述,引出了主从架构实现的读写分离,然后对redis的主从同步原理做了详细的说明,并配合了一些图片方便读者来理解,希望读者看完可以有所收获,谢谢大家!

    特别感谢

    感谢中华石杉老师的讲解,让我对redis的主从同步有了比较深入的理解,谢谢您大白话式的讲解,真的太好了。

    展开全文
  • Redis架构原理及应用实践一:数据基本类型stringhashlistsetZset二:Redis使用场景1.会话缓存(Session Cache)2.队列3.全页缓存4.排行榜/计数器三:Redis高可用架构1.持久化RDBAOF四: Redis高并发及热key解决之道1....

    简介
    Redis 是完全开源免费的,遵守BSD协议,是一个灵活的高性能key-value数据结构存储,可以用来作为数据库,缓存和消息队列。 Redis 比其他key – value 缓存产品有以下三个特点: Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载到内存使用。

    一:数据基本类型

    Redis 支持 5 中数据类型:string(字符串),hash(哈希),list(列表),set(集合),zset(sorted set:有序集合)。每种数据类型的具体命令请参考Redis 命令参考

    string

    string 是 redis 最基本的数据类型。一个 key 对应一个 value。string 是二进制安全的。也就是说 redis 的 string 可以包含任何数据。比如 jpg 图片或者序列化的对象。string 类型是 redis 最基本的数据类型,string 类型的值最大能存储 512 MB。

    hash

    Redis hash 是一个键值对(key - value)集合。Redis hash 是一个 string 类型的 key 和 value 的映射表,hash 特别适合用于存储对象。并且可以像数据库中一样只对某一项属性值进行存储、读取、修改等操作。

    list

    Redis 列表是简单的字符串列表,按照插入顺序排序。我们可以网列表的左边或者右边添加元素。 list 就是一个简单的字符串集合,和 Java 中的 list 相差不大,区别就是这里的 list 存放的是字符串。list 内的元素是可重复的。可以做消息队列或最新消息排行等功能。

    set

    redis 的 set 是字符串类型的无序集合。集合是通过哈希表实现的,因此添加、删除、查找的复杂度都是 O(1)。redis 的 set 是一个 key 对应着多个字符串类型的 value,也是一个字符串类型的集合,和 redis 的 list 不同的是 set 中的字符串集合元素不能重复,但是 list 可以。利用唯一性,可以统计访问网站的所有独立 ip。

    Zset

    redis zset 和 set 一样都是字符串类型元素的集合,并且集合内的元素不能重复。不同的是 zset 每个元素都会关联一个 double 类型的分数。redis 通过分数来为集合中的成员进行从小到大的排序。zset 的元素是唯一的,但是分数(score)却可以重复。可用作排行榜等场景。


    二:Redis使用场景

    1.会话缓存(Session Cache)

    最常用的一种使用Redis的情景是会话缓存(session cache)。用Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化,Memcached几乎用的很少了。

    2.队列

    Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作,这种功能往往被其他消息中间件取代。

    3.全页缓存

    大型互联网公司都会使用Redis作为缓存存储数据,提升页面相应速度。即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降。这种情况往往是那种发布发布数据不做修改的,可以考虑全页面缓存

    4.排行榜/计数器

    Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单。一般排名的时候,会用到


    三:Redis高可用架构

    1.持久化

    Redis 是内存型数据库,为了保证数据在断电后不会丢失,需要将内存中的数据持久化到硬盘上。Redis提供了两种持久化的方式,分别是RDB(Redis DataBase)和AOF(Append Only File)。

    RDB

    简而言之,就是在不同的时间点,将redis存储的数据生成快照并存储到磁盘等介质上,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本。如果系统发生故障,将会丢失最后一次创建快照之后的数据。如果数据量大,保存快照的时间会很长。

    AOF

    换了一个角度来实现持久化,那就是将redis执行过的所有写指令记录下来,在下次redis重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了。将写命令添加到 AOF 文件(append only file)末尾。

    使用 AOF 持久化需要设置同步选项,从而确保写命令同步到磁盘文件上的时机。这是因为对文件进行写入并不会马上将内容同步到磁盘上,而是先存储到缓冲区,然后由操作系统决定什么时候同步到磁盘。选项同步频率always每个写命令都同步,eyerysec每秒同步一次,no让操作系统来决定何时同步,always 选项会严重减低服务器的性能,everysec 选项比较合适,可以保证系统崩溃时只会丢失一秒左右的数据,并且 Redis 每秒执行一次同步对服务器几乎没有任何影响。no 选项并不能给服务器性能带来多大的提升,而且会增加系统崩溃时数据丢失的数量。随着服务器写请求的增多,AOF 文件会越来越大。Redis 提供了一种将 AOF 重写的特性,能够去除 AOF 文件中的冗余写命令。

    其实RDB和AOF两种方式也可以同时使用,在这种情况下,如果redis重启的话,则会优先采用AOF方式来进行数据恢复,这是因为AOF方式的数据恢复完整度更高。如果你没有数据持久化的需求,也完全可以关闭RDB和AOF方式,这样的话,redis将变成一个纯内存数据库。


    四: Redis高并发及热key解决之道

    1.并发设置key及分布式锁

    Redis是一种单线程机制的nosql数据库,基于key-value,数据可持久化落盘。由于单线程所以Redis本身并没有锁的概念,多个客户端连接并不存在竞争关系,但是利用jedis等客户端对Redis进行并发访问时会出现问题。比如多客户端同时并发写一个key,一个key的值是1,本来按顺序修改为2,3,4,最后是4,但是顺序变成了4,3,2,最后变成了2。使用分布式锁防止并发设置Key的原理及代码见:使用Redis实现分布式锁及其优化,另外一种方式是使用消息队列,把并行读写进行串行化。

    2.热key问题

    热key问题说来也很简单,就是瞬间有几十万的请求去访问redis上某个固定的key,从而压垮缓存服务的情情况。其实生活中也是有不少这样的例子。比如XX明星结婚。那么关于XX明星的Key就会瞬间增大,就会出现热数据问题。那么如何发现热KEY呢:

    1.凭借业务经验,进行预估哪些是热key

    2.在客户端进行收集

    3.在Proxy层做收集

    4.用redis自带命令(monitor命令、hotkeys参数)

    5.自己抓包评估

    解决方案:

    1.利用二级缓存,比如利用ehcache,或者一个HashMap都可以。在你发现热key以后,把热key加载到系统的JVM中。

    2.备份热key,不要让key走到同一台redis上。我们把这个key,在多个redis上都存一份。可以用HOTKEY加上一个随机数(N,集群分片数)组成一个新key。

    3.热点数据尽量不要设置过期时间,在数据变更时同步写缓存,防止高并发下重建缓存的资源损耗。可以用setnx做分布式锁保证只有一个线程在重建缓存,其他线程等待重建缓存的线程执行完,重新从缓存获取数据即可。

    3.缓存穿透

    缓存穿透是指查询一个根本不存在的数据,缓存层和存储层都不会命中,但是出于容错的考虑,如果从存储层查不到数据则不写入缓存层。缓存穿透将导致不存在的数据每次请求都要到存储层去查询,失去了缓存保护后端存储的意义。造成缓存穿透的基本有两个。第一,业务自身代码或者数据出现问题,第二,一些恶意攻击、爬虫等造成大量空命中,下面我们来看一下如何解决缓存穿透问题。解决缓存穿透的两种方案:
    缓存穿透是指查询一个根本不存在的数据,缓存层和存储层都不会命中,但是出于容错的考虑,如果从存储层查不到数据则不写入缓存层。缓存穿透将导致不存在的数据每次请求都要到存储层去查询,失去了缓存保护后端存储的意义。造成缓存穿透的基本有两个。第一,业务自身代码或者数据出现问题,第二,一些恶意攻击、爬虫等造成大量空命中,下面我们来看一下如何解决缓存穿透问题。解决缓存穿透的两种方案:

    1)缓存空对象

    缓存空对象会有两个问题:

    第一,空值做了缓存,意味着缓存层中存了更多的键,需要更多的内存空间 ( 如果是攻击,问题更严重 ),比较有效的方法是针对这类数据设置一个较短的过期时间,让其自动剔除。

    第二,缓存层和存储层的数据会有一段时间窗口的不一致,可能会对业务有一定影响。例如过期时间设置为 5 分钟,如果此时存储层添加了这个数据,那此段时间就会出现缓存层和存储层数据的不一致,此时可以利用消息系统或者其他方式清除掉缓存层中的空对象。

    c2)布隆过滤器拦截

    如下图所示,在访问缓存层和存储层之前,将存在的 key 用布隆过滤器提前保存起来,做第一层拦截。如果布隆过滤器认为该用户 ID 不存在,那么就不会访问存储层,在一定程度保护了存储层。有关布隆过滤器的相关知识,可以参考: 布隆过滤器,可以利用 Redis 的 Bitmaps 实现布隆过滤器,GitHub 上已经开源了类似的方案,读者可以进行参考:redis bitmaps实现布隆过滤器


    五:缓存雪崩

    数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。
    可以从以下几个方面防止缓存雪崩:

    1)保证缓存层服务高可用性

    和飞机都有多个引擎一样,如果缓存层设计成高可用的,即使个别节点、个别机器、甚至是机房宕掉,依然可以提供服务,例如前面介绍过的 Redis Sentinel 和 Redis Cluster 都实现了高可用。

    2)Redis备份和快速预热

    Redis备份保证master出问题切换为slave迅速能够承担线上实际流量,快速预热保证缓存及时被写入缓存,防止穿透到库。

    3)依赖隔离组件为后端限流并降级

    无论是缓存层还是存储层都会有出错的概率,可以将它们视同为资源。作为并发量较大的系统,假如有一个资源不可用,可能会造成线程全部 hang 在这个资源上,造成整个系统不可用。降级在高并发系统中是非常正常的:比如推荐服务中,如果个性化推荐服务不可用,可以降级补充热点数据,不至于造成前端页面是开天窗。

    在实际项目中,我们需要对重要的资源 ( 例如 Redis、 MySQL、 Hbase、外部接口 ) 都进行隔离,让每种资源都单独运行在自己的线程池中,即使个别资源出现了问题,对其他服务没有影响。但是线程池如何管理,比如如何关闭资源池,开启资源池,资源池阀值管理,这些做起来还是相当复杂的,这里推荐一个 Java 依赖隔离工具Hystrix(https://github.com/Netflix/Hystrix)。

    4)提前演练

    在项目上线前,演练缓存层宕掉后,应用以及后端的负载情况以及可能出现的问题,在此基础上做一些预案设定。

    总结
    项目中使用redis很平常, 一般使用集群就够用了,数据量大一点,防止缓存穿透,用二级缓存ehcache也就差不多了,布隆过滤器目前还没尝试过,暂且先记一笔

    展开全文
  • Redis架构原理与搭建

    2019-03-08 16:05:21
    1、Replication+Sentinel架构 ...通知:当被监控的某个redis服务器出现问题,Sentinel通过API脚本向管理员或者其他的应用程序发送通知。 自动故障转移:当主节点不能正常工作时,Sentinel会开始一...

    1、Replication+Sentinel架构

    这套架构使用的是社区版本推出的原生高可用解决方案,其架构图如下!
    在这里插入图片描述
    这里Sentinel的作用有三个:
    监控:Sentinel 会不断的检查主服务器和从服务器是否正常运行。
    通知:当被监控的某个redis服务器出现问题,Sentinel通过API脚本向管理员或者其他的应用程序发送通知。
    自动故障转移:当主节点不能正常工作时,Sentinel会开始一次自动的故障转移操作,它会将与失效主节点是主从关系 的其中一个从节点升级为新的主节点,并且将其他的从节点指向新的主节点。
    工作原理就是,当Master宕机的时候,Sentinel会选举出新的Master,并根据Sentinel中client-reconfig-script脚本配置的内容,去动态修改VIP(虚拟IP),将VIP(虚拟IP)指向新的Master。我们的客户端就连向指定的VIP即可!
    故障发生后的转移情况,可以理解为下图
    在这里插入图片描述
    缺陷:
    (1)主从切换的过程中会丢数据
    (2)Redis只能单点写,不能水平扩容

    2、Proxy+Replication+Sentinel架构

    这里的Proxy目前有两种选择:Codis和Twemproxy。我经历这套架构的时间为2015年,当时我好像咨询过我的主管为啥不用Codis和Redis官网的Redis Cluster。原因有二:

    据说是因为Codis开源的比较晚,考虑到更换组件的成本问题。毕竟本来运行好好的东西,你再去换组件,风险是很大的。
    Redis Cluster在2015年还是试用版,不保证会遇到什么问题,因此不敢尝试。
    所以我没接触过Codis,之前一直用的是Twemproxy作为Proxy。
    这里以Twemproxy为例说明,如下图所示
    在这里插入图片描述
    工作原理如下
    前端使用Twemproxy+KeepAlived做代理,将其后端的多台Redis实例分片进行统一管理与分配
    每一个分片节点的Slave都是Master的副本且只读
    Sentinel持续不断的监控每个分片节点的Master,当Master出现故障且不可用状态时,Sentinel会通知/启动自动故障转移等动作
    Sentinel 可以在发生故障转移动作后触发相应脚本(通过 client-reconfig-script 参数配置 ),脚本获取到最新的Master来修改Twemproxy配置
    缺陷:
    (1)部署结构超级复杂
    (2)可扩展性差,进行扩缩容需要手动干预
    (3)运维不方便

    3、Redis Cluster架构

    我经历这套架构的时间为2017年,在这个时间Redis Cluster已经很成熟了!你们在网上能查到的大部分缺点,在我接触到的时候基本已经解决!
    比如没有完善的运维工具?可以参照一下搜狐出的CacheCloud。
    比如没有公司在生产用过?我接触到的时候,百度贴吧,美团等大厂都用过了。
    比如没有Release版?我接触到的时候距离Redis Cluster发布Release版已经很久。
    而且毕竟是官网出的,肯定会一直维护、更新下去,未来必定会更加成熟、稳定。换句话说,Redis不倒,Redis Cluster就不会放弃维护。所以,我推荐还是这套架构!
    如下图所示
    在这里插入图片描述
    工作原理如下
    客户端与Redis节点直连,不需要中间Proxy层,直接连接任意一个Master节点
    根据公式HASH_SLOT=CRC16(key) mod 16384,计算出映射到哪个分片上,然后Redis会去相应的节点进行操作
    具有如下优点:
    (1)无需Sentinel哨兵监控,如果Master挂了,Redis Cluster内部自动将Slave切换Master
    (2)可以进行水平扩容
    (3)支持自动化迁移,当出现某个Slave宕机了,那么就只有Master了,这时候的高可用性就无法很好的保证了,万一master也宕机了,咋办呢? 针对这种情况,如果说其他Master有多余的Slave ,集群自动把多余的Slave迁移到没有Slave的Master 中。
    缺点:
    (1)批量操作是个坑
    (2)资源隔离性较差,容易出现相互影响的情况。
    Redis Cluster架构比较是官网提供的架构方案,具体的官网文档地址如下:https://redis.io/topics/cluster-tutorial

    出处: http://rjzheng.cnblogs.com/

    展开全文
  • Redis架构原理(转载)

    2020-04-29 11:13:38
    Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库 它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash...

    基础概念

    Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库
    它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步以保证数据备份。

    设计思想
    无论从设计还是源码,Redis都尽量做到简单,其中运用到的原理也通俗易懂。
    Redis非常精细地考虑了压缩数据、减少内存碎片等问题
    Redis本质上是一个数据结构服务器(data structures server),以高效的方式实现了多种现成的数据结构,它没有MySQL那样的索引机制,因为其内建一个基于hash的字典
    Redis采用单线程的设计带来的好处是,极大简化了数据结构和算法的实现。相反,Redis通过异步IO和pipelining等机制来实现高速的并发访问。
    Redis一使用dict基础数据结构,解决了算法中的查找问题并且实现了快速响应时间

    系统组成
    网络模型
    Redis是典型的基于Reactor的事件驱动模型,是高效的单进程单线程框架,整体分为接受请求处理器、响应处理器和应答处理器三个同步模块,每一个请求都是要经历这三个部分。
    Redis集成了libevent/epoll/kqueue/select等多种事件管理机制,可以根据操作系统 版本自由选择合适的管理机制,其中libevent是最优选择的机制。
    Redis的网络模型有着所有事件驱动模型的优点,高效低耗。但是面对耗时较长的 操作的时候,同样无法处理请求,只能等到事件处理完毕才能响应,比如删除redis 中全量的key-value,整个操作时间较长,操作期间所有的请求都无法响应。所以了解清楚网络模型有助于在业务中扬长避短,减少长耗时的请求,尽可能多一些简单的短耗时请求发挥异步模型的最大的威力,事实上在Redis的设计中也多次体现这一点

    数据类型
    Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
    Ø String 是Redis最基本的数据类型,一个键最大能存储512MB。String类型是 二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或 者序列化的对象,一个key对应一个value。
    Ø Hash Redis hash是一个键值(key=>value)对集合,是string类型的field和value 的映射表,hash 特别适合用于存储对象。每个 hash 可以 存储 232 -1 键值对(40多亿)
    Ø List Redis List列表是简单的字符串列表,按照插入顺序排序。你可以添加一 个元素到列表的头部(左边)或者尾部(右边),列表最多可存储 232 - 1 元素(4294967295, 每个列表可存储40多亿)。
    Ø Set Redis的Set是string类型的无序集合。
    集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
    根据集合内元素的唯一性,第二次插入的相同元素将被忽略。
    集合中最大的成员数为 232 - 1(4294967295, 每个集合可存储40多亿个 成员)。
    Sadd:命令添加一个string元素到,key对应的set集合中,成功返回1,如果 元素已经在集合中返回0,key对应的set不存在返回错误。
    Ø Zset Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
    不同的是每个元素都会关联一个double类型的分数。redis正是通过分数 来为集合中的成员进行从小到大的排序,zset的成员是唯一的,但分数 (score)却可以重复。

    架构图

    在这里插入图片描述

    各功能模块说明:

    File Event: 处理文件事件(在多个客户端中实现多路复用,接受它们发来的命令请求(读事 件),并将命令的执行结果返回给客户端(写事件))

    Time Event: 时间事件(更新统计信息,清理过期数据,附属节点同步,定期持久化等)

    AOF: 命令日志的数据持久化

    RDB:实际的数据持久化

    Lua Environment : Lua 脚本的运行环境. 为了让 Lua 环境符合 Redis 脚本功能的需求, Redis 对 Lua 环境进行了一系列的修改, 包括添加函数库、更换随机函数、 保护全局变量, 等等

    Command table(命令表):在执行命令时,根据字符来查找相应命令的实现函数。

    Share Objects(对象共享):主要存储常见的值:a.各种命令常见的返回值,例如返回值OK、 ERROR、WRONGTYPE等字符;b. 小于 redis.h/REDIS_SHARED_INTEGERS (默认1000)的所有整数。通过预分配的一些常见的值对象,并在多个数据结构 之间共享对象,程序避免了重复分配的麻烦。也就是说,这些常见的值在内存 中只有一份。

    Databases:Redis数据库是真正存储数据的地方。当然,数据库本身也是存储在内存中的。 (结构图见1.2.3.2数据库内存数据结构图)

    在这里插入图片描述

    核心原理

    Redis的单线程和高性能
    Redis 单线程为什么还能这么快?
    因为它所有的数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换性能损耗问题。正因为 Redis 是单线程,所以要小心使用 Redis 指令,对于那些耗时的指令(比如keys),一定要谨慎使用,一不小心就可能会导致 Redis 卡顿。
    Redis 单线程如何处理那么多的并发客户端连接?
    Redis的IO多路复用:redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。
    Nginx也是采用IO多路复用原理解决C10K问题

    在这里插入图片描述

    持久化
    RDB快照(snapshot)
    在默认情况下, Redis 将数据库快照保存在名字为 dump.rdb 的二进制文件中。
    你可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。
    比如说, 以下设置会让 Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动保存一次数据集:

    # save 60 1000
    

    AOF(append-only file)
    快照功能并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化,将修改的每一条指令记录进文件
    你可以通过修改配置文件来打开 AOF 功能:

    # appendonly yes
    

    从现在开始, 每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾。
    这样的话, 当 Redis 重新启时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。
    你可以配置 Redis 多久才将数据 fsync 到磁盘一次。
    有三个选项:
    每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全。
    每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
    从不 fsync :将数据交给操作系统来处理。更快,也更不安全的选择。
    推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。

    Redis 4.0 混合持久化
    重启 Redis 时,我们很少使用 rdb 来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 rdb 来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。 Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。AOF在重写(aof文件里可能有太多没用指令,所以aof会定期根据内存的最新数据生成aof文件)时将 rdb文件的内容和增量的 AOF 日志文件存在一起,AOF根据配置规则在后台自动重写,也可以人为执行命令bgrewriteaof重写AOF。这里的 AOF 日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小。 于是在 Redis 重启的时候,可以先加载 rdb 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,重启效率因此大幅得到提升。

    开启混合持久化:

    # aof-use-rdb-preamble yes
    

    混合持久化aof文件结构

    在这里插入图片描述

    缓存淘汰策略
    当 Redis 内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换 (swap)。交换会让 Redis 的性能急剧下降,对于访问量比较频繁的 Redis 来说,这样龟速的存取效率基本上等于不可用。
    在生产环境中我们是不允许 Redis 出现交换行为的,为了限制最大使用内存,Redis 提供了配置参数 maxmemory 来限制内存超出期望大小。
    当实际内存超出 maxmemory 时,Redis 提供了几种可选策略 (maxmemory-policy) 来让用户自己决定该如何腾出新的空间以继续提供读写服务。

    noeviction 不会继续服务写请求 (DEL 请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能持续进行。这是默认的淘汰策略。
    volatile-lru 尝试淘汰设置了过期时间的 key,最少使用的 key 优先被淘汰。没有设置过期时间的 key 不会被淘汰,这样可以保证需要持久化的数据不会突然丢失。
    volatile-ttl 跟上面一样,除了淘汰的策略不是 LRU,而是 key 的剩余寿命 ttl 的值,ttl 越小越优先被淘汰。
    volatile-random 跟上面一样,不过淘汰的 key 是过期 key 集合中随机的 key。
    allkeys-lru 区别于 volatile-lru,这个策略要淘汰的 key 对象是全体的 key 集合,而不只是过期的 key 集合。这意味着没有设置过期时间的 key 也会被淘汰。
    allkeys-random 跟上面一样,不过淘汰的策略是随机的 key。

    volatile-xxx 策略只会针对带过期时间的 key 进行淘汰,allkeys-xxx 策略会对所有的 key 进行淘汰。如果你只是拿 Redis 做缓存,那应该使用 allkeys-xxx,客户端写缓存时不必携带过期时间。如果你还想同时使用 Redis 的持久化功能,那就使用 volatile-xxx 策略,这样可以保留没有设置过期时间的 key,它们是永久的 key 不会被 LRU 算法淘汰。

    此文为多文档集合转载,时代久远已经无法考据,有疑问请私聊

    展开全文
  • 一.Redis简介Redis 是完全开源免费的,是一个高性能的key-value类型的内存数据库。整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常...
  • 概念Redis作为一个开源的用C编写的非关系型数据库,基于优秀的CRUD效率,常用于软件系统的缓存,其本身提供了以下五种数据格式:string:字符串list:列表hash:散列表set:无序集合zset:有序集合接下来我们就要...
  • 4. redis 主从架构redis replication:实现高并发高可用 单台redis的局限性: 内存上,单个Redis的内存不宜过大,内存过大会导致主从同步时全量同步时间过长,而且在实例重启恢复时也会消耗很长的数据加载时间,...
  • redis 集群架构 Java操作redis集群 Redis集群原理分析 -------------------------- 在redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态,如果master节点异常,则会 做主从切换,...
  • 2.1、常见的高可用MySQL解决方案 2.2、MySQL Replication架构的部署与应用 2.3、KeepAlived搭建MySQL双主模式的高可用集群系统 2.4、MHA架构的概念和原理 2.5、MHA的组成和恢复过程 2.6、MySQL高可用架构MHA部署...
  • 免责声明以下知识来源:https://juejin.im/post/5ce7efef518825332b59f79bslot架构redis中slot和节点的对应关系图:只要是redis集群版,slot的个数一定是16384个!数据库中的每个键都属于这16384个槽的其中一个,...
  • 正文 1. Redis Sentinel 简介 redis 的主从复制模式下,一旦主节点由于故障不能提供服务,需要人工将从节点晋升为主节点,再...于是,redis 从 2.8 开始正式提供了sentinel 架构来解决这个问题。 red...
  • Redis集群是一个由多个Redis服务器组成的分布式网络服务器群,集群中的各个服务器被称为节点(node),这些节点会相互连接并进行通信。分布式的Redis集群没有中心节点,所以用户不必担心某个节点会成为整个集群的...
  • 前面Redis Sentinel 架构原理详解(二)介绍了redis集群中sentinel的三种定时监控任务,还了解了主观下线,客观下线的概念,以及sentinel is-master-down-by-addr命令的作用。这里再和大家一起学习下Redis Sentinel...
  • 前面Redis Sentinel 架构原理详解(三)中介绍了redis哨兵集群中sentinel的leader如何选举,以及redis主从中的新master如何选择,这里再和大家一起学习下Sentinel集群的quorum 和majority,configuration epoch,以及...
  • 前面在Redis Sentinel 架构原理详解(一)中,我们学习了redis哨兵中的主从切换原理,也知道了sentinel集群在redis高可用架构中的作用。这里再和大家一起学习下sentinel 集群是如何实现节点监控的。 sentinel集群的...
  • 这套架构使用的是社区版本推出的原生高可用解决方案,其架构图如下! 这里Sentinel的作用有三个: 监控:Sentinel 会不断的检查主服务器和从服务器是否正常运行。 通知:当被监控的某个Redis服务器出现问题...
  • 077:RedisCluster哨兵集群实现原理1 回顾Redis主从复制与哨兵机制2 传统Redis哨兵集群存在那些缺陷3 RedisCluster分片集群实现原理4 基于不同Redis配置文件启动多个不同的Redis5 Linux环境上搭建RedisCluster6 ...
  • Redis Sentinel 简介 redis主从复制模式下,一旦主节点故障不能提供服务,需要人工...于是,redis从 2.8 开始正式提供了sentinel 架构来解决这个问题。redis sentinel是redis的高可用实现方案,多个sentinel 进程协...
  • Redis二:RDB、AOF及混合持久化、并行持久化之写时复制机制、Redis主从架构原理Redis管道及lua脚本、Redis哨兵高可用架构 Redis持久化 RDB快照(snapshot) 在默认情况下, Redis 将内存数据库快照保存在名字...
  • Redis 架构模式

    2019-08-01 15:05:24
    原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。 这里的哨兵有两个作用 通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。 当哨兵监测到master宕机,会...
  • redis架构设计

    2017-08-31 10:23:49
    一、前言 因为近期项目中开始使用Redis,为了更好的理解Redis...同时根据Redis初始化的流程,理解Redis各个模块的功能及原理。 二、redis启动流程 1.初始化server变量,设置redis相关的默认
  • Redis架构设计

    2016-11-11 10:56:48
    一、前言 因为近期项目中开始使用Redis,为了更好的理解...同时根据Redis初始化的流程,理解Redis各个模块的功能及原理。   二、redis启动流程     1.初始化server变量,设置redis相...
  • Redis架构设计

    2016-08-15 20:05:00
    一、前言 因为近期项目中开始使用Redis,为了更好的...同时根据Redis初始化的流程,理解Redis各个模块的功能及原理。 二、redis启动流程 1.初始化server变量,设置redis相关的默认值 2.读入配...
  • 单台redis支撑的最大并发数大概在几万到十几万不等。当我们系统中,并发数高过单台redis所能支撑的上限时,我们就需要...一,redis主从复制原理 redis的replication一共分两种操作: 1. resync 重新同步。当slave...
  • Redis是一个基于key-value的高速缓存系统,类似于memcached,但是支持更复杂的数据结构List、Set、SortedSet,并且有持久化的功能。...这个问题看似可笑,其实不然,我很赞同Timyang的观点,架构者对...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,805
精华内容 722
关键字:

redis架构原理

redis 订阅