Redis的哨兵模式和集群模式

Redis的哨兵模式和集群模式,第1张

接口异常的意思就是服务器崩了,网络导致视频播放失败,接口出现了异常。

检查自己的网路是不是已经连接成功了,网速限速没,连接成功后再次登录,就可以看自己想要看的视频了。

大致为两种措施:

一、脚本同步:

1、自己写脚本将数据库数据写入到redis/memcached。

2、这就涉及到实时数据变更的问题(mysqlrowbinlog的实时分析),binlog增量订阅Alibaba的canal,以及缓存层数据丢失/失效后的数据同步恢复问题。

二、业务层实现:

1、先读取nosql缓存层,没有数据再读取mysql层,并写入数据到nosql。

2、nosql层做好多节点分布式(一致性hash),以及节点失效后替代方案(多层hash寻找相邻替代节点),和数据震荡恢复了。

redis实现数据库缓存的分析:

对于变化频率非常快的数据来说,如果还选择传统的静态缓存方式(Memocached、FileSystem等)展示数据,可能在缓存的存取上会有很大的开销,并不能很好的满足需要,而Redis这样基于内存的NoSQL数据库,就非常适合担任实时数据的容器。

但是往往又有数据可靠性的需求,采用MySQL作为数据存储,不会因为内存问题而引起数据丢失,同时也可以利用关系数据库的特性实现很多功能。所以就会很自然的想到是否可以采用MySQL作为数据存储引擎,Redis则作为Cache。

MySQL到Redis数据复制方案,无论MySQL还是Redis,自身都带有数据同步的机制,比较常用的MySQL的Master/Slave模式,就是由Slave端分析Master的binlog来实现的,这样的数据复制其实还是一个异步过程,只不过当服务器都在同一内网时,异步的延迟几乎可以忽略。那么理论上也可用同样方式,分析MySQL的binlog文件并将数据插入Redis。

因此这里选择了一种开发成本更加低廉的方式,借用已经比较成熟的MySQLUDF,将MySQL数据首先放入Gearman中,然后通过一个自己编写的PHPGearmanWorker,将数据同步到Redis。比分析binlog的方式增加了不少流程,但是实现成本更低,更容易 *** 作。

Redis队列功能介绍

List

常用命令:

Blpop删除,并获得该列表中的第一元素,或阻塞,直到有一个可用

Brpop删除,并获得该列表中的最后一个元素,或阻塞,直到有一个可用

Brpoplpush

Lindex获取一个元素,通过其索引列表

Linsert在列表中的另一个元素之前或之后插入一个元素

Llen获得队列(List)的长度

Lpop从队列的左边出队一个元素

Lpush从队列的左边入队一个或多个元素

Lpushx当队列存在时,从队到左边入队一个元素

Lrange从列表中获取指定返回的元素

Lrem从列表中删除元素

Lset设置队列里面一个元素的值

Ltrim修剪到指定范围内的清单

Rpop从队列的右边出队一个元素

Rpoplpush删除列表中的最后一个元素,将其追加到另一个列表

Rpush从队列的右边入队一个元素

Rpushx从队列的右边入队一个元素,仅队列存在时有效

Redis支持php、python、c等接口

应用场景:

Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现。

Lists 就是链表,相信略有数据结构知识的人都应该能理解其结构。使用Lists结构,我们可以轻松地实现最新消息排行等功能。

Lists的另一个应用就是消息队列,

可以利用Lists的PUSH *** 作,将任务存在Lists中,然后工作线程再用POP *** 作将任务取出进行执行。Redis还提供了 *** 作Lists中某一段的api,你可以直接查询,删除Lists中某一段的元素。

如果需要还可以用redis的Sorted-Sets数据结构来做优先队列可以给每条消息加上一个唯一的序号。这里就不详细介绍了。

实现方式:

Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便 *** 作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。

示意图:

1)入队

2)出队(非阻塞模式)

lpopd出列表首元素(即最后入队的元素)

Rpopd出列表尾元素 (即入队的最开始的一个元素)

注意:如果要当作队列功能,应该是用这个出队

这里的出队都是非阻塞模式,就是你用pop出队的时候,如果队列是空的话,你得到的是一个NULL的值

3)出队(阻塞模式)

假如现在queue队列为空  我们用brpop命令

BRPOP 是一个阻塞的列表d出原语。 它是 RPOP 的阻塞版本,因为这个命令会在给定list无法d出任何元素的时候阻塞连接。 该命令会按照给出的 key 顺序查看 list,并在找到的第一个非空 list 的尾部d出一个元素。

A)

我们执行brpop命令

可以看到队列queue没有元素的时候  是阻塞的  即不返回值

其中0是超时时间 为0表示一直等待

B)

这个时候我们用lpush往队列里 入队一个数据“bbb”

C)

阻塞的队列立马会d出出队元素   显示队列名字  和 出队元素  已经等待了多少时间

D)

Brpop还能同时阻塞多个队列比如这样

用redis的list当作队列可能存在的问题

1)redis崩溃的时候队列功能失效

2)如果入队端一直在塞数据,而出队端没有消费数据,或者是入队的频率大而多,出队端的消费频率慢会导致内存暴涨

3)Redis的队列也可以像rabbitmq那样  即可以做消息的持久化,也可以不做消息的持久化。

当做持久话的时候,需要启动redis的dump数据的功能暂时不建议开启持久化。

Redis其实只适合作为缓存,而不是数据库或是存储。它的持久化方式适用于救救急啥的,不太适合当作一个普通功能来用。应为dump时候,会影响性能,数据量小的时候还看不出来,当数据量达到百万级别,内存10g左右的时候,非常影响性能。

4)假如有多个消费者同时监听一个队列,其中一个出队了一个元素,另一个则获取不到该元素

5)Redis的队列应用场景是一对多或者一对一的关系,即有多个入队端,但是只有一个消费端(出队)

PHP的redis 简单 *** 作示例

1什么是Redis

Redis是由意大利人SalvatoreSanfilippo(网名:antirez)开发的一款内存高速缓存数据库。Redis全称为:RemoteDictionaryServer(远程数据服务),该软件使用C语言编写,Redis是一个key-value存储系统,它支持丰富的数据类型,如:string、list、set、zset(sortedset)、hash。

2Redis特点

Redis以内存作为数据存储介质,所以读写数据的效率极高,远远超过数据库。以设置和获取一个256字节字符串为例,它的读取速度可高达110000次/s,写速度高达81000次/s。

Redis跟memcache不同的是,储存在Redis中的数据是持久化的,断电或重启后,数据也不会丢失。因为Redis的存储分为内存存储、磁盘存储和log文件三部分,重启后,Redis可以从磁盘重新将数据加载到内存中,这些可以通过配置文件对其进行配置,正因为这样,Redis才能实现持久化。

Redis支持主从模式,可以配置集群,这样更利于支撑起大型的项目,这也是Redis的一大亮点。

3Redis应用场景,它能做什么

众多语言都支持Redis,因为Redis交换数据快,所以在服务器中常用来存储一些需要频繁调取的数据,这样可以大大节省系统直接读取磁盘来获得数据的I/O开销,更重要的是可以极大提升速度。

拿大型网站来举个例子,比如a网站首页一天有100万人访问,其中有一个板块为推荐新闻。要是直接从数据库查询,那么一天就要多消耗100万次数据库请求。上面已经说过,Redis支持丰富的数据类型,所以这完全可以用Redis来完成,将这种热点数据存到Redis(内存)中,要用的时候,直接从内存取,极大的提高了速度和节约了服务器的开销。

总之,Redis的应用是非常广泛的,而且极有价值,真是服务器中的一件利器,所以从现在开始,我们就来一步步学好它。

Redis是一个nosql数据库,可以存储key-value值。因为其底层实现中,数据读写是基于内存,速度非常快,所以常用于缓存;进而因其为独立部署的中间件,常用于分布式缓存的实现方案。

常用场景有:缓存、秒杀控制、分布式锁。

虽然其是基于内存读写,但底层也有持久化机制;同时具备集群模式;不用担心其可用性。

关于Redis的使用,可以参考《Redis的使用方法、常见应用场景》

在算法的分布式版本中,我们假设我们有N个Redis主节点。这些节点是完全独立的,因此我们不使用复制或任何其他隐式协调系统。我们已经描述了如何在单个实例中安全地获取和释放锁。我们理所当然地认为,算法将使用此方法在单个实例中获取和释放锁。在我们的示例中,我们设置了 N=5,这是一个合理的值,因此我们需要在不同的计算机或虚拟机上运行 5 个 Redis 主节点,以确保它们以一种基本独立的方式失败。

为了获取锁,客户端执行以下 *** 作:

该算法依赖于以下假设:虽然进程之间没有同步时钟,但每个进程中的本地时间以大致相同的速率更新,与锁的自动释放时间相比,误差幅度很小。这个假设与现实世界的计算机非常相似:每台计算机都有一个本地时钟,我们通常可以依靠不同的计算机来具有很小的时钟漂移。

在这一点上,我们需要更好地指定我们的互斥规则:只要持有锁的客户端在锁有效时间内(如步骤3中获得的那样)终止其工作,减去一些时间(只需几毫秒,以补偿进程之间的时钟漂移),它才能得到保证。

本文包含有关需要绑定 时钟漂移 的类似系统的更多信息: Leases:分布式文件缓存一致性的高效容错机制 。

当客户端无法获取锁时,它应该在随机延迟后重试,以便尝试取消同步多个客户端,尝试同时获取同一资源的锁(这可能会导致没有人获胜的裂脑情况)。此外,客户端在大多数 Redis 实例中尝试获取锁的速度越快,裂脑情况的窗口就越小(并且需要重试),因此理想情况下,客户端应尝试使用多路复用同时将 SET 命令发送到 N 个实例。

值得强调的是,对于未能获取大多数锁的客户端来说,尽快释放(部分)获取的锁是多么重要,这样就不需要等待密钥到期才能再次获取锁(但是,如果发生网络分区并且客户端不再能够与 Redis 实例通信, 在等待密钥过期时需要支付可用性罚款)。

释放锁很简单,无论客户端是否认为它能够成功锁定给定实例,都可以执行。

算法安全吗?让我们来看看在不同场景中会发生什么。

首先,我们假设客户端能够在大多数实例中获取锁。所有实例都将包含一个具有相同生存时间的密钥。但是,密钥是在不同的时间设置的,因此密钥也会在不同的时间过期。但是,如果在时间 T1(我们在联系第一台服务器之前采样之前采样的时间)将第一个键设置为最差,而在时间 T2(我们从最后一个服务器获得回复的时间)将最后一个键设置为最差,则我们确信集中第一个过期的密钥将至少存在 。所有其他密钥稍后将过期,因此我们确信至少这次将同时设置这些密钥。 MIN_VALIDITY=TTL-(T2-T1)-CLOCK_DRIFT

在设置大多数密钥期间,另一个客户端将无法获取锁,因为如果 N/2+1 密钥已存在,则 N/2+1 SET NX *** 作无法成功。因此,如果获得了锁,则不可能同时重新获得它(违反互斥属性)。

但是,我们还希望确保尝试同时获取锁的多个客户端无法同时成功。

如果客户端锁定大多数实例的时间接近或大于锁定最大有效时间(我们基本上用于 SET 的 TTL),它将认为锁定无效并将解锁实例,因此我们只需要考虑客户端能够在小于有效时间的时间内锁定大多数实例的情况。在这种情况下,对于上面已经表达的参数,因为任何客户端都不应该能够重新获取锁。因此,仅当锁定大多数实例的时间大于 TTL 时间时,多个客户端才能同时锁定 N/2+1 个实例(“时间”是步骤 2 的结束),从而使锁定无效。 MIN_VALIDITY

系统活动性基于三个主要功能:

但是,我们支付的可用性损失等于网络分区上的 TTL 时间,因此,如果有连续分区,我们可以无限期地支付此罚款。每次客户端获取锁并在能够删除锁之前进行分区时,都会发生这种情况。

基本上,如果存在无限连续的网络分区,则系统可能会在无限长的时间内变得不可用。

许多使用 Redis 作为锁服务器的用户在获取和释放锁的延迟以及每秒可以执行的获取/释放 *** 作数方面都需要高性能。为了满足这一要求,与N Redis服务器对话以减少延迟的策略肯定是多路复用(将套接字置于非阻塞模式,发送所有命令,稍后读取所有命令,假设客户端和每个实例之间的RTT相似)。

但是,如果我们想以崩溃恢复系统模型为目标,则关于持久性还有另一个考虑因素。

基本上,为了看到这里的问题,让我们假设我们配置Redis时根本没有持久性。客户端在 5 个实例中的 3 个实例中获取锁。客户端能够获取锁的其中一个实例重新启动,此时我们可以为同一资源锁定3个实例,而另一个客户端可以再次锁定它,这违反了锁的独占性的安全属性。

如果我们启用AOF持久性,事情将会有所改善。例如,我们可以通过向服务器发送 SHUTDOWN 命令并重新启动它来升级服务器。由于 Redis 过期在语义上是实现的,因此当服务器关闭时,时间仍然会过去,因此我们所有的要求都很好。但是,只要它是干净关闭,一切都很好。停电怎么办?如果 Redis 配置为(默认情况下)每秒在磁盘上同步一次,则重新启动后,我们的密钥可能会丢失。从理论上讲,如果我们想在面对任何类型的实例重启时保证锁定安全,我们需要在持久性设置中启用。由于额外的同步开销,这将影响性能。 fsync=always

然而,事情比乍一看要好。基本上,只要实例在崩溃后重新启动,它就不再参与任何 当前活动的 锁定,算法安全性就会保留。这意味着实例重新启动时的当前活动锁定集都是通过锁定重新加入系统的实例以外的实例而获得的。

为了保证这一点,我们只需要在崩溃后使一个实例不可用,至少比我们使用的最大 TTL 多一点。这是实例崩溃时存在的有关锁的所有密钥变得无效并自动释放所需的时间。

使用 延迟重启 ,即使没有任何可用的Redis持久性,基本上也可以实现安全,但请注意,这可能会转化为可用性损失。例如,如果大多数实例崩溃,系统将全局不可用 TTL (此处全局意味着在此期间根本没有资源可锁定)。

如果客户端执行的工作由小步骤组成,则默认情况下可以使用较小的锁定有效期,并扩展实现锁定扩展机制的算法。基本上,如果客户端在计算过程中锁定有效性接近较低值,则可以通过将Lua脚本发送到所有实例来扩展锁定,该实例扩展密钥的TTL(如果密钥存在并且其值仍然是客户端在获取锁定时分配的随机值)。

只有当客户端能够将锁扩展到大多数实例中,并且在有效时间内(基本上要使用的算法与获取锁时使用的算法非常相似),才应考虑重新获取锁。

但是,这在技术上不会更改算法,因此应限制锁定重新获取尝试的最大次数,否则会违反其中一个活动属性。

以上就是关于Redis的哨兵模式和集群模式全部的内容,包括:Redis的哨兵模式和集群模式、搞懂Redis (八) - 哨兵机制、接口异常是什么意思等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/9811850.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-02
下一篇2023-05-02

发表评论

登录后才能评论

评论列表(0条)

    保存