问题描述
Azure Redis作为微软云提供的一种PaaS服务,由于PaaS的特性,服务端的安装和维护、修补、升级等操作均由平台放负责。虽然最终用户只需要关注当前服务的使用,但是后台的升级和补丁行为,总会对使用Redis服务产生影响。如:Azure Redis的“故障转移 Failover”就是专为此类行为设计的功能。
故障转移的说明
当Redis的副本节点将其自身提升为主节点,且旧主节点关闭现有连接时,将发生故障转移。 主节点重新启动后,它将自身降级为副本节点。 故障转移可以是计划性的,也可以是非计划的。
计划性故障转移发生在系统更新(例如 Redis 修补或 OS 升级)和管理操作(例如缩放和重启)过程中。 由于节点会提前收到更新通知,因此它们可以协作交换角色,并在更改后快速更新负载均衡器。 计划性故障转移通常可在 1 秒内完成。
发生非计划性故障转移的可能原因是硬件故障、网络故障或主节点的其他意外中断。 副本节点可将自身提升为主节点,但该过程需要更长时间。 副本节点必须先检测到其主节点不可用,然后才能启动故障转移过程。 副本节点还必须验证此非计划性故障不是暂时性的或局部性的,以避免不必要的故障转移。 检测时出现的这种延迟意味着非计划性故障转移通常要在 10 到 15 秒内完成。
所以在Redis发生故障,升级时,在前端使用Redis时,虽然受影响的时间非常的短,但是还是会有所影响。所以当前端Redis收到异常消息时候,如何快速的定位是否Redis由升级行为呢?
解决办法
使用Redis的“事件(Events)”功能页面,配置Event Grid,发送补丁完成事件到接收端,如Webhook, Azure Storage Queue, Function等,方式非常的多。
当前,Redis Events支持四种事件:
- ExportRDBCompleted :导出缓存数据时触发
- ImportRDBCompleted :导入缓存数据时触发
- PatchingCompleted :修补完成时触发
- ScalingCompleted :缩放完成后触发
使用PatchingCompleted事件,则可以在更新,升级完成后,收到来自Redis服务端的消息。此外,也需要针对缓存设置“计划更新”。 告知Redis管理服务在指定的每周时段应用 Redis 运行时修补程序。 通常,这些时段是客户端应用程序流量较低的时段,目的是避免潜在的事件。
操作步骤
因本文在测时并无法得知何时有升级事件发生,所以以下操作步骤中,以ScallingCompleted事件做为结果演示。并且在演示中使用的存储队列方式来接收事件消息,这里也可以使用其他方式,此处只作为一个演示。
一:创建Redis的Event Grid订阅,并配置存储队列作为接收端
- 需要提前准备好在配置中需要的 存储账号 和 队列 信息,如示例中使用的为:backuptest01 和redisupdatequeue01
- 自定义订阅事件的名称
- 选择订阅Redis的事件,如这里全部选择了Redis的四个事件
- 选择终结点类型。
二:触发Scalling 操作。在存储队列中查看结果
补充说明
一:在Redis发生故障转移,对客户端的影响和如何减少影响?
Redis客户端遇到的错误数目取决于故障转移时该连接上挂起的操作数目。 在连接中断时,许多客户端库可能会引发不同类型的错误,包括超时异常、连接异常或套接字异常。 例如,在发生故障转移时发送了请求但未收到响应的操作可能会收到超时异常。 对关闭的连接对象发出的新请求将收到连接异常,直到重新连接成功为止。
由于故障转移不可完全避免,因此,客户端应用程序需要使用重试机制,大多数的Redis客户端都支持重试机制。在 Microsoft.NET 和其他面向对象的语言中,可以使用 Lazy<T> 模式来重新创建连接,而无需重启应用程序。
private static Lazy<ConnectionMultiplexer> CreateMultiplexer() { return new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(connectionString)); } private static void CloseMultiplexer(Lazy<ConnectionMultiplexer> oldMultiplexer) { if (oldMultiplexer != null) { try { oldMultiplexer.Value.Close(); } catch (Exception) { // Example error condition: if accessing old.Value causes a connection attempt and that fails. } } }
更多消息,请查看Redis故障转移和修补文档:https://docs.azure.cn/zh-cn/azure-cache-for-redis/cache-failover
二:如何设置Redis的计划更新功能?
使用“计划更新”边栏选项卡可以为缓存实例指定维护时段。 借助维护时段,可以控制在一周中的哪一天和哪个时间点更新托管缓存的 VM。 Azure Cache for Redis 将尽最大努力在定义的指定时间范围内启动和完成 Redis 服务器软件的更新。详见:https://docs.azure.cn/zh-cn/azure-cache-for-redis/cache-administration#schedule-updates
三:Redis Event Grid事件中消息体内容格式
PatchingCompleted 事件
[{ "id":"9b87886d-21a5-4af5-8e3e-10c4b8dac73b", "eventType":"Microsoft.Cache.PatchingCompleted", "topic":"/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.Cache/Redis/{cache_name}", "data":{ "name":"PatchingCompleted", "timestamp":"2020-12-09T21:50:19.9995668+00:00", "status":"Succeeded"}, "subject":"PatchingCompleted", "dataversion":"1.0", "metadataVersion":"1", "eventTime":"2020-12-09T21:50:19.9995668+00:00"}]
ScalingCompleted 事件
[{ "id":"9b87886d-21a5-4af5-8e3e-10c4b8dac73b", "eventType":"Microsoft.Cache.ScalingCompleted", "topic":"/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.Cache/Redis/{cache_name}", "data":{ "name":"ScalingCompleted", "timestamp":"2020-12-09T21:50:19.9995668+00:00", "status":"Succeeded"}, "subject":"ScalingCompleted", "dataversion":"1.0", "metadataVersion":"1", "eventTime":"2020-12-09T21:50:19.9995668+00:00"}]
跟多全面的事件消息体,请参考 Azure Redis事件网格源: https://docs.microsoft.com/zh-cn/azure/event-grid/event-schema-azure-cache#the-contents-of-an-event-response
参考资料
Redis 的故障转移和修补:https://docs.azure.cn/zh-cn/azure-cache-for-redis/cache-failover
Redis计划更新:https://docs.azure.cn/zh-cn/azure-cache-for-redis/cache-administration#schedule-updates
什么是事件网格(Event Grid):https://docs.microsoft.com/zh-cn/azure/event-grid/overview?WT.mc_id=Portal-HubsExtension
Redis 事件网格源:https://docs.microsoft.com/zh-cn/azure/event-grid/event-schema-azure-cache#the-contents-of-an-event-response