redis 哨兵(sentinel)机制

news2024/11/26 17:00:24

1. 前言

sentinel(哨兵)是Redis 的高可用性解决方案之一。通过哨兵可以创建一个当主服务器出现故障时自动将从服务器升级为主服务器的分布式系统,解决了主从复制出现故障时需要人为干预的问题。

redis 的主从复制的作用有数据预热负载均衡故障恢复等,但主存复制存在一个问题就是故障恢复无法自动化,本文介绍的哨兵基于redis主存复制,主要作用是解决主节点故障恢复自动化的问题,进一步提高系统的高可用性。

redis的集群方案大致有三种:

  1. redis cluster集群方案;
  2. master/slave主从方案;
  3. 哨兵模式来进行主从替换以及故障恢复。

2. 夯实基础

2.1 知识回顾

在介绍哨兵之前,首先从宏观的角度回顾一下Redis实现高可用相关技术。它包括:持久化、复制、哨兵和集群,主要作用与解决的问题是:

1)持久化:持久化是最简单的高可用方法(有时甚至不被归为高可用的手段),主要作用是数据备份,即将数据存储在硬盘,保证数据不会因进程退出而丢失;
2)复制:复制是高可用Redis的基础,哨兵和集群都在复制基础上实现高可用的。复制主要实现了数据的多机备份,以及读操作的负载均衡和简单的故障转移。缺陷:故障恢复无法自动化。写操作无法负载均衡、存储能力受到单击的限制;
3)哨兵:在复制的基础上,哨兵实现了自动化的故障恢复。缺陷:写操作无法负载均衡;存储能力受到单机的限制。
4)集群:通过集群,Redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。

2.2 什么是哨兵机制?

redis Sentinel,即Redis哨兵,在Redis 2.8版本开始引入。哨兵的核心功能是主节点的自动故障转移

2.3 哨兵的核心功能

下面是 redis官方文档 对于哨兵功能的描述:

  • 主存监控(Monitoring):哨兵会不断地检查主节点和从节点是否运作正常。
  • 故障转移(Automatic failover):当主节点不能正常工作时,哨兵会开始自动故障转移操作,它会将失效主节点的其中一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点。
  • 配置中心(Configuration provider):客户端在初始化时,通过连接哨兵来获得当前Redis服务的主节点地址。
  • 消息通知(Notification):哨兵可以将故障转移的结果发送给客户端。

其中,监控和自动故障转移功能,使得哨兵可以及时发现主节点故障并完成转移;而配置提供者和通知功能,则体现在与客户端交互过程中。

2.4 哨兵模式架构模型

redis Sentinel是一个分布式架构,其中包含若干个 Sentinel 节点和 Redis 数据节点,每个 Sentinel 节点会对数据节点和其余 Sentinel 节点进行监控,当它发现节点不可达时,会对节点做下线标识。

如果被标识的是主节点,它还会和其他 Sentinel 节点进行“协商”,当大多数 Sentinel 节点都认为主节点不可达时,它们会选举出一个 Sentinel 节点来完成自动故障转移的工作(这个选举机制一会介绍),同时会将这个变化实时通知给 Redis 应用方。

整个过程完全是自动的,不需要人工来介入,所以这套方案很有效地解决了 Redis 的高可用问题。

可以理解为:之前的主从复制中增加了几个哨兵(这里注意是几个而不是一个)来监控redis,如果主机挂了,哨兵会经过选举在从机中选出一个redis作为主机,这样就不必手动切换了。

在这里插入图片描述

典型的哨兵架构图由两部分组成,哨兵节点和数据节点:

  1. 哨兵节点:哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的redis节点,不存储数据。
  2. 数据节点:主节点和从节点都是数据节点。

2.5 哨兵运行流程与选举原理

当一个主从配置中的master失效之后,sentinel可以选举出一个新的master用于自动接替原master的工作,主从配置中的其他redis服务器自动指向新的master同步数据。一般建议sentinel采取奇数台,防止某一台sentinel无法连接到master导致误切换。

2.5.1 三个哨兵监控,一主二从,正常运行中…

在这里插入图片描述

2.5.2 SDown主观下线(Subjectively Down)

1)主观下线(Subjectively Down, 简称 SDOWN)是单个sentinel自己主观上检测到的关于master的状态,从sentinel的角度来看,如果发送了PING心跳后,在一定时间内没有收到合法的回复,就达到了SDOWN的条件。

2)sentinel配置文件中的down-after-milliseconds设置了判断主观下线的时间长度,master在多长时间内一直没有给Sentine返回有效信息,则认定该master主观下线。也就是说如果多久没联系上redis-servevr,认为这个redis-server进入到失效(SDOWN)状态。
在这里插入图片描述

2.5.3 ODown客观下线(Objectively Down)

客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断,然后开启failover。

客观下线就是说只有在足够数量的 Sentinel 都将一个服务器标记为主观下线之后, 服务器才会被标记为客观下线(ODOWN)。

masterName是对某个master+slave组合的一个区分标识(一套sentinel可以监听多组master+slave这样的组合)
在这里插入图片描述
quorum这个参数是进行客观下线的一个依据,法定人数/法定票数

意思是至少有quorum个sentinel认为这个master有故障才会对这个master进行下线以及故障转移。因为有的时候,某个sentinel节点可能因为自身网络原因导致无法连接master,而此时master并没有出现故障,所以这就需要多个sentinel都一致认为该master有问题,才可以进行下一步操作,这就保证了公平性和高可用。

2.5.4 选举出领导者哨兵-leader

当主节点被判断客观下线以后,各个哨兵节点会进行协商,会选举出一个领导者哨兵节点,并由该领导者节点也就是被选举出的Leader 进行failover(故障迁移)。
在这里插入图片描述

哨兵Leader 是如何选出来的呢?-- Raft算法

监视该主节点的所有哨兵都有可能被选为领导者,选举使用的算法是Raft算法;Raft算法的基本思路是先到先得:
即在一轮选举中,哨兵A向B发送成为领导者的申请,如果B没有同意过其他哨兵,则会同意A成为领导者。
在这里插入图片描述

2.5.5 哨兵 leader 推动故障转移,选出新master

在哨兵集群中通过投票的方式,选举出了哨兵 leader 后,就可以进行主从故障转移的过程了,如下图:
在这里插入图片描述
主从故障转移操作包含以下四个步骤:

  • 第一步:在已下线主节点(旧主节点)属下的所有「从节点」里面,挑选出一个从节点,并将其转换为主节点。
  • 第二步:让已下线主节点属下的所有「从节点」修改复制目标,修改为复制「新主节点」;
  • 第三步:将新主节点的 IP 地址和信息,通过「发布者/订阅者机制」通知给客户端;
  • 第四步:继续监视旧主节点,当这个旧主节点重新上线时,将它设置为新主节点的从节点;

第一步:选出新Master

故障转移操作第一步要做的就是在已下线主节点属下的所有「从节点」中,挑选出一个状态良好、数据完整的从节点,然后向这个「从节点」发送 SLAVEOF no one 命令,将这个「从节点」转换为「主节点」。

那么多「从节点」,到底选择哪个从节点作为新主节点的?

随机的方式好吗?随机的方式,实现起来很简单,但是如果选到一个网络状态不好的从节点作为新主节点,那么可能在将来不久又要做一次主从故障迁移。

所以,我们首先要把网络状态不好的从节点给过滤掉。首先把已经下线的从节点过滤掉,然后把以往网络连接状态不好的从节点也给过滤掉。

怎么判断从节点之前的网络连接状态不好呢?

Redis 有个叫 down-after-milliseconds * 10 配置项,其down-after-milliseconds 是主从节点断连的最大连接超时时间。如果在 down-after-milliseconds 毫秒内,主从节点都没有通过网络联系上,我们就可以认为主从节点断连了。如果发生断连的次数超过了 10 次,就说明这个从节点的网络状况不好,不适合作为新主节点。

至此,我们就把网络状态不好的从节点过滤掉了,接下来要对所有从节点进行三轮考察:优先级复制进度ID 号。在进行每一轮考察的时候,哪个从节点优先胜出,就选择其作为新主节点。

  • 第一轮考察:哨兵首先会根据从节点的优先级来进行排序,优先级越小排名越靠前,
  • 第二轮考察:如果优先级相同,则查看复制的下标,哪个从「主节点」接收的复制数据多,哪个就靠前。
  • 第三轮考察:如果优先级和下标都相同,就选择从节点 ID 较小的那个。

第一轮考察:优先级最高的从节点胜出 :Redis 有个叫 slave-priority 配置项,可以给从节点设置优先级。每一台从节点的服务器配置不一定是相同的,我们可以根据服务器性能配置来设置从节点的优先级。
第二轮考察:复制进度最靠前的从节点胜出:如果在第一轮考察中,发现优先级最高的从节点有两个,那么就会进行第二轮考察,比较两个从节点哪个复制进度。

什么是复制进度?

主从架构中,主节点会将写操作同步给从节点,在这个过程中,主节点会用 master_repl_offset 记录当前的最新写操作在 repl_backlog_buffer 中的位置(如下图中的「主服务器已经写入的数据」的位置),而从节点会用 slave_repl_offset 这个值记录当前的复制进度(如下图中的「从服务器要读的位置」的位置)。
在这里插入图片描述
如果某个从节点的 slave_repl_offset 最接近 master_repl_offset,说明它的复制进度是最靠前的,于是就可以将它选为新主节点。

第三轮考察:ID 号小的从节点胜出:如果在第二轮考察中,发现有两个从节点优先级和复制进度都是一样的,那么就会进行第三轮考察,比较两个从节点的 ID 号,ID 号小的从节点胜出。

什么是 ID 号?

每个从节点都有一个编号,这个编号就是 ID 号,是用来唯一标识从节点的。

到这里,选主的事情终于结束了。简单给大家总结下:
在这里插入图片描述
在选举出从节点后,哨兵 leader 向被选中的从节点发送 SLAVEOF no one 命令,让这个从节点解除从节点的身份,将其变为新主节点。

如下图,哨兵 leader 向被选中的从节点 server2 发送 SLAVEOF no one 命令,将该从节点升级为新主节点。
在这里插入图片描述
在发送 SLAVEOF no one 命令之后,哨兵 leader 会以每秒一次的频率向被升级的从节点发送 INFO 命令(没进行故障转移之前,INFO 命令的频率是每十秒一次),并观察命令回复中的角色信息,当被升级节点的角色信息从原来的 slave 变为 master 时,哨兵 leader 就知道被选中的从节点已经顺利升级为主节点了。

如下图,选中的从节点 server2 升级成了新主节点:
在这里插入图片描述
第二步:将从节点指向新主节点

当新主节点出现之后,哨兵 leader 下一步要做的就是,让已下线主节点属下的所有「从节点」指向「新主节点」,这一动作可以通过向「从节点」发送 SLAVEOF 命令来实现。

如下图,哨兵 leader 向所有从节点(server3和server4)发送 SLAVEOF ,让它们成为新主节点的从节点。
在这里插入图片描述
所有从节点指向新主节点后的拓扑图如下
在这里插入图片描述
第三步:通知客户的主节点已更换

经过前面一系列的操作后,哨兵集群终于完成主从切换的工作,那么新主节点的信息要如何通知给客户端呢?

这主要通过 Redis 的发布者/订阅者机制来实现的。每个哨兵节点提供发布者/订阅者机制,客户端可以从哨兵订阅消息。

哨兵提供的消息订阅频道有很多,不同频道包含了主从节点切换过程中的不同关键事件,几个常见的事件如下:
在这里插入图片描述
客户端和哨兵建立连接后,客户端会订阅哨兵提供的频道。主从切换完成后,哨兵就会向 +switch-master 频道发布新主节点的 IP 地址和端口的消息,这个时候客户端就可以收到这条信息,然后用这里面的新主节点的 IP 地址和端口进行通信了。

通过发布者/订阅者机制机制,有了这些事件通知,客户端不仅可以在主从切换后得到新主节点的连接信息,还可以监控到主从节点切换过程中发生的各个重要事件。这样,客户端就可以知道主从切换进行到哪一步了,有助于了解切换进度。

第四步:将旧主节点变为从节点

故障转移操作最后要做的是,继续监视旧主节点,当旧主节点重新上线时,哨兵集群就会向它发送 SLAVEOF 命令,让它成为新主节点的从节点,如下图:
在这里插入图片描述
至此,整个主从节点的故障转移的工作结束。

2.6 哨兵集群是如何组成的

前面提到了 Redis 的发布者/订阅者机制,那就不得不提一下哨兵集群的组成方式,因为它也用到了这个技术。

在我第一次搭建哨兵集群的时候,当时觉得很诧异。因为在配置哨兵的信息时,竟然只需要填下面这几个参数,设置主节点名字、主节点的 IP 地址和端口号以及 quorum 值。

sentinel monitor <master-name> <ip> <redis-port> <quorum> 

不需要填其他哨兵节点的信息,我就好奇它们是如何感知对方的,又是如何组成哨兵集群的?

后面才了解到,哨兵节点之间是通过 Redis 的发布者/订阅者机制来相互发现的。

在主从集群中,主节点上有一个名为__sentinel__:hello的频道,不同哨兵就是通过它来相互发现,实现互相通信的。

在下图中,哨兵 A 把自己的 IP 地址和端口的信息发布到__sentinel__:hello 频道上,哨兵 B 和 C 订阅了该频道。那么此时,哨兵 B 和 C 就可以从这个频道直接获取哨兵 A 的 IP 地址和端口号。然后,哨兵 B、C 可以和哨兵 A 建立网络连接。
在这里插入图片描述
通过这个方式,哨兵 B 和 C 也可以建立网络连接,这样一来,哨兵集群就形成了。

3. 面试题及解析

3.1 哨兵集群如何知道「从节点」的信息?

哨兵集群会对「从节点」的运行状态进行监控,那哨兵集群如何知道「从节点」的信息?

主节点知道所有「从节点」的信息,所以哨兵会每 10 秒一次的频率向主节点发送 INFO 命令来获取所有「从节点」的信息。

如下图所示,哨兵 B 给主节点发送 INFO 命令,主节点接受到这个命令后,就会把从节点列表返回给哨兵。接着,哨兵就可以根据从节点列表中的连接信息,和每个从节点建立连接,并在这个连接上持续地对从节点进行监控。哨兵 A 和 C 可以通过相同的方法和从节点建立连接。
在这里插入图片描述
正式通过 Redis 的发布者/订阅者机制,哨兵之间可以相互感知,然后组成集群,同时,哨兵又通过 INFO 命令,在主节点里获得了所有从节点连接信息,于是就能和从节点建立连接,并进行监控了。

4. 总结

Redis 在 2.8 版本以后提供的哨兵(Sentinel)机制,它的作用是实现主从节点故障转移。它会监测主节点是否存活,如果发现主节点挂了,它就会选举一个从节点切换为主节点,并且把新主节点的相关信息通知给从节点和客户端。

哨兵一般是以集群的方式部署,至少需要 3 个哨兵节点,哨兵集群主要负责三件事情:监控、选主、通知。

哨兵节点通过 Redis 的发布者/订阅者机制,哨兵之间可以相互感知,相互连接,然后组成哨兵集群,同时哨兵又通过 INFO 命令,在主节点里获得了所有从节点连接信息,于是就能和从节点建立连接,并进行监控了。

1、第一轮投票:判断主节点下线

当哨兵集群中的某个哨兵判定主节点下线(主观下线)后,就会向其他哨兵发起命令,其他哨兵收到这个命令后,就会根据自身和主节点的网络状况,做出赞成投票或者拒绝投票的响应。

当这个哨兵的赞同票数达到哨兵配置文件中的 quorum 配置项设定的值后,这时主节点就会被该哨兵标记为「客观下线」。

2、第二轮投票:选出哨兵leader

某个哨兵判定主节点客观下线后,该哨兵就会发起投票,告诉其他哨兵,它想成为 leader,想成为 leader 的哨兵节点,要满足两个条件:

  • 第一,拿到半数以上的赞成票;
  • 第二,拿到的票数同时还需要大于等于哨兵配置文件中的 quorum 值。

3、由哨兵 leader 进行主从故障转移

选举出了哨兵 leader 后,就可以进行主从故障转移的过程了。该操作包含以下四个步骤:

  • 第一步:在已下线主节点(旧主节点)属下的所有「从节点」里面,挑选出一个从节点,并将其转换为主节点,选择的规则:
    • 过滤掉已经离线的从节点;
    • 过滤掉历史网络连接状态不好的从节点;
    • 将剩下的从节点,进行三轮考察:优先级、复制进度、ID 号。在每一轮考察过程中,如果找到了一个胜出的从节点,就将其作为新主节点。
  • 第二步:让已下线主节点属下的所有「从节点」修改复制目标,修改为复制「新主节点」;
  • 第三步:将新主节点的 IP 地址和信息,通过「发布者/订阅者机制」通知给客户端;
  • 第四步:继续监视旧主节点,当这个旧主节点重新上线时,将它设置为新主节点的从节点;

4.1 哨兵使用建议

  1. 哨兵节点的数量应为多个,哨兵本身应该集群,保证高可用。
  2. 哨兵节点的数量应该是奇数
  3. 各个哨兵节点的配置应一致
  4. 如果哨兵节点部署在Docker等容器里面,尤其要注意端口的正确映射。
  5. 哨兵集群 + 主从复制,并不能保证数据零丢失。

参考资料

  1. https://redis.io/docs/management/sentinel/
  2. Redis哨兵模式(sentinel)学习总结及部署记录(主从复制、读写分离、主从切换)
  3. 深入学习Redis:哨兵

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1020035.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UML基础与应用之对象图

什么是对象图&#xff1f; 对象图表示一组对象及它们之间的关系&#xff0c;是某一时刻系统详细信息的快照&#xff0c;描述系统交互的静态图形&#xff0c;它由协作的对象组成&#xff0c;但不包含在对象之间传递的任何消息。因为对象是类的实例化&#xff0c;所以说某一时刻…

步步为营,如何将GOlang引用库的安全漏洞修干净

文章目录 引场景构建第一步、直接引用的第三方库升级修复策略1.确认是否为直接引用的第三方库2.找到需要升级的版本是否为release版本 第二步、间接引用的第三方库升级修复策略那么问题来了&#xff0c;我们这么间接引用库的对应的直接引用库是哪个呢&#xff1f; &#xff08;…

uni-app实现web-view图片长按下载

<template><view><web-view :webview-styles"webviewStyles" :src"webUrl"></web-view></view> </template> uniapp的web-view中图片无法长按保存&#xff0c;IOS下是正常的&#xff0c;但是Android下长按无反应 解…

在测试过程中引入可观测性平台提升业务质量

作者 观测云 产品技术专家 成都办公室 - 刘跃兰 前言 随着微服务技术的发展&#xff0c;微服务概念已深入人心&#xff0c;越来越多的企业开始使用微服务架构来开发业务应用。业务应用系统的整体架构变得更加复杂&#xff0c;并存在各种各样的不确定性因素&#xff0c;从而对…

nginx+keepalived集群搭建

1. nginx部署 单机部署可参考&#xff1a;https://blog.csdn.net/ym5209999/article/details/119897237 2. keepalived安装 [rootnginx1 ~]# yum -y install keepalived3. keepalived配置 3.1 安装完成后&#xff0c;默认配置文件位于&#xff1a;/etc/keepalived&#xff…

奶奶都看的懂的《栈》(C语言实现,超详细解析 !!!)

目录 一、前言 二、栈 &#x1f34e;栈的概念 &#x1f350;栈的结构​编辑 &#x1f349;栈的实现 &#x1f34a;栈 各个接口的实现 ⭕ 定义一个 栈 结构体 ⭕栈 的初始化 ⭕ 栈 的尾插 ⭕ 栈 的尾删 ⭕ 栈 内数据个数 ⭕ 获取 栈 顶元素 ⭕ 判断 栈 是否为空 ⭕…

Linux-网卡和网络配置

链接一篇大佬的博客&#xff1a;Linux之手把手教会修改网卡名称 文章目录 修改网卡名称步骤1&#xff1a;修改“/etc/default/grub”步骤2&#xff1a;修改“/etc/sysconfig/network-scripts”下的文件步骤3&#xff1a;修改“ifcfg-eth0”配置步骤4&#xff1a;判断操作系统的…

AIGC入门 - LLM 信息概览

本文将介绍以下 LLM OPTLLaMaAlpacaVicunaMosschatGLMBaichuanOpenbuddy 一、OPT 1、背景 OPT全称Open Pre-trained Transformer Language Models&#xff0c;即“开放的预训练Transformer语言模型”&#xff0c;是 Meta AI 团队在2022年5月发布了开源大模型OPT-175B&#…

Ninja: Towards Transparent Tracing and Debugging on ARM【TEE的应用】

目录 摘要引言贡献 背景TrustZone和受信任的固件PMU和ETM 相关工作x86上的透明恶意软件分析ARM上的动态分析工具基于仿真的系统硬件虚拟化裸机系统 Trustzone相关的系统 系统架构具体实现和评估可以看论文&#xff0c;这里不赘述了讨论总结 作者&#xff1a;Zhenyu Ning and Fe…

ffmpeg编译 Error: operand type mismatch for `shr‘

错误如下&#xff1a; D:\msys2\tmp\ccUxvBjQ.s: Assembler messages: D:\msys2\tmp\ccUxvBjQ.s:345: Error: operand type mismatch for shr D:\msys2\tmp\ccUxvBjQ.s:410: Error: operand type mismatch for shr D:\msys2\tmp\ccUxvBjQ.s:470: Error: operand type mismatch…

BCrypt 密码数据加解密运用

前言&#xff1a; 当涉及到存储用户密码时&#xff0c;确保密码的安全非常重要。以往&#xff0c;我们通常都是采用 MD5 这种不可逆算法来进行密码数据的加密后存储&#xff0c;虽然MD5算法是一种常见的哈希函数&#xff0c;但是它已经不再被认为是安全的选项。 常规MD5加密&a…

趣解设计模式之《小王的学习秘籍》

〇、小故事 小王是学校的学霸&#xff0c;凭借着自己的天赋以及对于学习的刻苦&#xff0c;每次考试都能排到年级第一名。但是&#xff0c;他所在的班级总成绩却不高&#xff0c;在所有班级中&#xff0c;属于中游水平。老师希望通过小王的贡献&#xff0c;能否帮助整个班级同…

证券账户可以绑定几张银行卡,可以更换绑定吗

个人账户实现股票量化程序化自动交易&#xff0c;券商有接口&#xff0c;门槛已降低_股票程序交易接口的博客-CSDN博客像上面的例子&#xff0c;如果按照市面上常见的可转债万3或万2不免5&#xff0c;人工操作费率限制&#xff0c;这种情况就不要想&#xff0c;根本没机会&…

返回最大元素的索引 忽略数组中所有的NaN值 numpy.nanargmax()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 返回最大元素的索引 忽略数组中所有的NaN值 numpy.nanargmax() [太阳]选择题 请问代码中第一次执行语句的输出正确的是&#xff1f; import numpy as np a np.array([0,np.nan,2]) print(&…

H264视频压缩格式

H264简介 H.264从1999年开始&#xff0c;到2003年形成草案&#xff0c;最后在2007年定稿有待核实。在ITU的标准里称为H.264, 在MPEG的标准里是MPEG-4的一个组成部分-MPEG-4 Part 10&#xff0c;又叫Advanced Video Codec&#xff0c;因此常常称为MPEG-4AVC或直接叫AVC。 压缩算…

服务器搭建(TCP套接字)-fork版(服务端)

基础版的服务端虽然基本实现了服务器的基本功能&#xff0c;但是如果客户端的并发量比较大的话&#xff0c;服务端的压力和性能就会大打折扣,为了提升服务端的并发性能&#xff0c;可以通过fork子进程的方式&#xff0c;为每一个连接成功的客户端fork一个子进程&#xff0c;这样…

Ansible自动化:简化你的运维任务

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

OpenStack创建云主机并连接CRT

文章目录 OpenStackT版创建云主机并连接CRT命令行操作&#xff08;1&#xff09;创建镜像&#xff08;2&#xff09;创建实例&#xff08;3&#xff09;创建网络创建内网创建外网 &#xff08;4&#xff09;创建安全组&#xff08;5&#xff09;创建路由&#xff08;6&#xff…

如何利用CSS实现三角形、扇形、聊天气泡框

思路 三角形 实现三角形的关键思路是使用 CSS 的 border 属性来创建一个透明的矩形块&#xff0c;并利用边框的透明部分来形成三角形。下面是创建三角形的一般思路&#xff1a; 创建一个 HTML 元素&#xff0c;通常是一个 <div> 元素&#xff0c;用于容纳三角形。 为该…

超低功耗段码LCD液晶显示驱动IC-VKL144A/BQFN48超小体积液晶驱动

产品品牌&#xff1a;永嘉微电/VINKA 封装形式&#xff1a;TSSOP48/QFN48L 产品年份&#xff1a;新年份 沈先生 135 、547/44,703 原厂&#xff0c;工程服务&#xff0c;技术支持&#xff01; VKL144A/B 概述: VKL144A/B 是一个点阵式存储映射的LCD 驱动器&#xff0c;可…