[Redis] Redis服务集群

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:
🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm=1001.2014.3001.5482
🍕 Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀线程与网络(96平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
🍃 Spring(97平均质量分)https://blog.csdn.net/2301_80050796/category_12724152.html?spm=1001.2014.3001.5482
🎃Redis(97平均质量分)https://blog.csdn.net/2301_80050796/category_12777129.html?spm=1001.2014.3001.5482
🐰RabbitMQ(97平均质量分) https://blog.csdn.net/2301_80050796/category_12792900.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述

目录

  • 1. 集群概念介绍
  • 2. 数据分片方式与规则
    • 2.1 哈希求余算法
    • 2.2 一致性哈希算法
    • 2.3 哈希槽分区算法(redis使用)
  • 3. 基于docker搭建集群
  • 4. 主节点宕机自动处理流程
  • 5. 集群扩容

1. 集群概念介绍

集群这个词,可以从广义上来理解,也可以从狭义上来理解,其中广义的集群,只要是多个机器,构成了分布式系统。我们前面学过的哨兵模式,也可以算作是一种广义上的集群。狭义上的集群,是redis提供的一种集群模式,在这个集群模式之下,这个集群模式之下,主要解决存储空间不足的问题,即拓展存储空间
我们前面的哨兵模式提高了系统的可用性,哨兵模式中,本质上还是redis主从节点存储数据,其中要是请求一个主节点/从节点,就得存储整个数据的“全集”。但是集群中主要要解决的问题就是要引入多台机器,每台机器存储一部分数据.只要机器规模足够大,就可以存储任意数据的大小了.比如整个数据全集是1TB,引入三组Master/Salve来存储(注意是三组集群,每组集群中由一个主节点和若干从结点组成,集群中各个服务器存储的数据是相同的).那么每一组机器只需要存储整个数据全集的1/3即可.
在这里插入图片描述
这其中每个服务器集群上都需要存储一定规模的数据,也就是把数据分为了多份,但是数据在分成多份的时候,应该怎么分?这就是我们接下来需要主要研究的问题.

2. 数据分片方式与规则

上面的每个红框中的集群,都可以算是一个数据分片.下面是三种主流的数据分片方式.

2.1 哈希求余算法

所谓哈希求余,就是借鉴了哈希表的基本思想,借助哈希函数,把一个key映射到整数,再针对数据的长度,求余就可以得到一个数组的下标.
哈希求余的分片算法具体是什么样子的呢?
比如有三个分片,编号0 1 2,此时就可以针对要插入的数据的key计算出一个哈希值(计算哈希值的算法,一般是针对一个字符串里面的内容进行一系列的变换,比如md5算法就是一种哈希算法,他是把一个字符串变换成为一个16进制的数字).在把这个哈希值余上一个分片个数,就会得到一个下标.此时就可以把这个数据放到该下标对应的分片中了.
在这里插入图片描述
比如,hash(key) % N => 0,由于求出的余数是0,此时这个key对应的数据就要存储在0号分片中.后续查询key的时候也是同样的算法.只要key是一样的,hash函数式一样的,得到的分片的值就是一样的.
随着业务逐渐增长,数据变多的时候,仅有的几个分片就不足以保存数据了,这就需要对集群进行扩容,引入新的分片.**这时候,哈希求余算法的缺点就体现出来了,就是在增加集群容量,需要对数据进行搬运的时候,开销非常大 **.需要对数据进行搬运的原因就是,集群的数量增加,取余的N会增加,这就使得有些数据不应该待在当前的分片了,就需要重新进行分配.
而这些数据在搬运的时候,大部分的数据都是需要搬运的,这就是扩容的开销非常大.
在这里插入图片描述
从上图中可以看到,其中的21个数据,只有3个key没有被搬运,其他的key都是搬运过的.
当然,哈希求余的分片算法也是有一定优点的,那就是简单高效,数据分配比较均匀.

2.2 一致性哈希算法

哈希求余这种操作中,当前的key属于哪个分片是交替的.
比如某些数据的hash值分别是102,103,104,这些数据在余3之后,得到的值分别是0,1,2,它们哈希求余求出的值是交替的,交替分布在不同的集群中.在一致性哈希这种算法中,我们就把数据交替存储改进成了连续存储.以下的过程就是一致性哈希算法的过程:

  1. 首先把数据空间全部映射到一个圆环上,数据按照顺时针方向增长.
    在这里插入图片描述
  2. 假设当前存在三个分片,把分片放到圆环的某个位置.
    在这里插入图片描述
  3. 假定有一个key,通过哈希函数计算得到的哈希值H,之后把计算出的H映射到圆盘上对应数据的位置.之后从H所在的位置,顺时针向下找,找到的第一个分片,就是该key所从属的分片.
    在这里插入图片描述
    这就相当于,N个分片的位置,把整个圆环分成了N个管辖的区间,key的哈希值落在某个区间内,就归对应区间管理.
    在这里插入图片描述
    在这种一致性哈希算法情况下,如果想要对数据进行扩容,我们需要如何处理呢?原有分片在环上的位置不动,只需要在换上安排一个新的分片即可.
    在这里插入图片描述
    此时只需要把0号分片上的部分数据搬运给3号分片即可,1号分片和2号分片管理的区间都是不变的.
    这种算法的搬运成本相对于哈希求余的方式确实低了不少.虽然搬运的成本低了,但是缺点就是这几个分片的数据量就可能会发生某种程度上的不均匀,也就是发生数据倾斜.

2.3 哈希槽分区算法(redis使用)

这种算法是redis真正采用的算法,为了解决上述问题,redis集群就引入了哈希槽算法

hash_slot = crc16(key) % 16384
其中crc也是一种哈希算法,16384其实是16*1024,也就是2^14

其实这种算法就是把一致性哈希和哈希求余两种方式结合一下.也就是把哈希值映射到16384个槽位上.
然后再把这些槽位均匀地分给每个分片
,每个分片的接地那都需要记录自己持有哪些分片.每个分片都会使用"位图"这样的数据结构来表示出当前有多少槽位号,每一位用0/1来区分自己这个分片当前是否持有该槽位号
假设当前有三个分片,一种可能得分配方式:
• 0号分片:[0,5461],共5462个槽位
• 1号分片:[5462,10923],共5462个槽位
• 2号分片:[10924,16383],共5460个槽位
这里只是一种可能得分片方式,实际上分片方式是很灵活的.每个分片持有的槽位号,是可以连续,也可以不连续的.这里的分配虽然不是严格意义上的"均匀",但是差异却非常小了.此时这三个分片上的数据已经在某种程度上比较均匀了.
如果后需要进行扩容,比如新增一个3号分片,就可以针对原有的槽位进行重新分配.比如可以把之前的每个分片持有的槽位各拿出一点,分给新的分片:
• 0号分片:[0,4095],共4096个槽位
• 1号分片:[5462,9557],共4096个槽位
• 2号分片:[10924,15019],共4096个槽位
• 3号分片:[4096,5461]+[9558,10923]+[15019,16383],共4096个槽位
此外,还有一些其他的问题:

  1. redis集群最多有16384个分片吗?
    key是要先映射到槽位上,在映射到分片上的.如果每个分片包含的槽位比较多,槽位个数相当,就可以认为包含的key的个数是相当的,那么就可以认为数据分布式均匀的.如果每个分片包含的槽位非常少,槽位个数不一定直观反应到key的数目,这种情况之下,数据均匀性是很难保证的.而且如果每个分片中包含的槽数非常少,这就会使得集群的服务器规模非常庞大,服务器越多,出现故障的概率就越大.
    在redis官方文档中提到,作者建议我们集群的分片数不应该超过1000.
  2. 为什么是16384个槽位?
    这是由于结点之间需要通过心跳包进行通信,心跳包通过网络来在结点之间发送,心跳包中包含了该结点持有了哪些槽位,如果每个心跳包中给定的槽位数更多了,这时候心跳包就会变大,会增加网络传输上的开销.

3. 基于docker搭建集群

在搭建docker集群的时候,一定要记得把之前启动的redis容器给停止掉.否则可能会产生端口上的冲突.我们需要搭建的集群环境如下:
在这里插入图片描述
由于我们需要创建的redis结点较多,redis结点之间大同小异.在Linux操作系统的环境之下,我们需要引入shell脚本来批量创建.
就是把shell命令操作写入了一个文件中,批量化执行,同时还可以加入,条件,循环,函数机制等.

  1. 首先批量生成redis配置文件.创建redis-cluster目录.内部创建shell脚本文件,命名为generate.sh注意文件后缀必须是sh.
    generate文件的内容如下:
for port in $(seq 1 9); \
do \
mkdir -p redis${port}/
touch redis${port}/redis.conf
cat << EOF > redis${port}/redis.conf
port 6379
bind 0.0.0.0
protected-mode no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.30.0.10${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
EOF
done
# 注意 cluster-announce-ip 的值有变化. 
for port in $(seq 10 11); \
do \
mkdir -p redis${port}/
touch redis${port}/redis.conf
cat << EOF > redis${port}/redis.conf
port 6379
bind 0.0.0.0
protected-mode no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.30.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
EOF
done
  1. 之后在redis-cluster目录之下执行命令执行脚本.bash generate.sh.注意想要在指定的目录中生成文件,必须在指定的目录之下执行命令,于是就会在目录之下批量生成指定目录和配置文件.
redis-cluster/
├── generate.sh 
├── redis1 
│   └── redis.conf 
├── redis10 
│   └── redis.conf 
├── redis11 
│   └── redis.conf 
├── redis2 
│   └── redis.conf 
├── redis3 
│   └── redis.conf 
├── redis4 
│   └── redis.conf 
├── redis5 
│   └── redis.conf 
├── redis6 
│   └── redis.conf 
├── redis7 
│   └── redis.conf 
├── redis8 
│   └── redis.conf 
└── redis9 └── redis.conf 

其中每个redis.conf每个都不同.区别在与每个配置中配置的cluster-announce-ip是不同的,其他的部分都是相同的.

port 6379
bind 0.0.0.0
protected-mode no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.30.0.101
cluster-announce-port 6379
cluster-announce-bus-port 16379

我们对conf文件中的这些字段来解释一下:
- cluster-enabled: 开启集群
- cluster-config-file: 启动结点之后,redis自动配置的一些集群信息,这些是redis自动生成的,不需要手写.
- cluster-node-timeout: 多个结点之间需要进行交互,保持联络,如果发送心跳包之后,超过这个时间没有回应,则会主观判定为宕机.
- cluster-announce-ip: 该redis接地那所在主机的ip地址.当前是使用docker容器模拟主机,此处写的应该是docker容器的ip.
- cluster-announce-port: 业务端口,用来进行业务数据通信
- cluster-announce-bus-port: 管理端口,为了完成一些管理上的任务来进行通信.
3. 之后就需要使用docker来创建出redis容器了.在redis-cluster目录之下创建docker-compose.yml配置文件.

version: '3.7'
networks:mynet:ipam:config:- subnet: 172.30.0.0/24
services:redis1:image: 'redis:5.0.9'container_name: redis1restart: alwaysvolumes:- ./redis1/:/etc/redis/ports:- 6371:6379- 16371:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.101redis2:image: 'redis:5.0.9'container_name: redis2restart: alwaysvolumes:- ./redis2/:/etc/redis/ports:- 6372:6379- 16372:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.102redis3:image: 'redis:5.0.9'container_name: redis3restart: alwaysvolumes:- ./redis3/:/etc/redis/ports:- 6373:6379- 16373:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.103
...redis4,5,6...同理
  • subnet: 此处为了后续创建静态的ip,就需要先手动创建出网络,同时给这个网段分配ip,这里分配的网络号是172.30.0,其中这个网络号是私网格式的一种,需要注意的是,不能和当前主机上现有的其他网段冲突,0/24是主机号.
  • volumes: 配置文件映射
  • ports: 端口映射,需要注意的是,映射右边的端口必须和配置文件中的保持一致.
  • ipv4_address: 静态配置的网络ip,这里的ip也必须和之前的配置文件中的一致.
  1. 启动容器docker-compose up -d
  2. 接下来就需要把这些服容器全部构建为集群
    redis-cli --cluster create 172.30.0.101:6379 172.30.0.102:6379 172.30.0.103:6379 172.30.0.104:6379 172.30.0.105:6379 172.30.0.106:6379 172.30.0.107:6379 172.30.0.108:6379 172.30.0.109:6379 --cluster-replicas 2
    • –cluster create表示建立集群,后面填写每个结点的ip和地址.
    • –cluster-replicas 2表示每个主节点需要两个从结点备份.设置了这个配置之后,redis就会知道,每3个结点是一伙的(一个分片).但是分配的时候,谁是主节点,谁是从结点,都是随机的.
      执行之后,容器之间会进行加入集群操作.之后系统会弹出日志,描述集群的搭建是增怎样的.输入yes之后才会真正创建.见到[OK]之后说明集群建立完成.
  3. 使用客户端连上集群中的任何一个结点,都相当于连上了整个集群.redis-cli -h 172.30.0.101 -p 6379,在客户端中,我们使用cluster nodes来查看当前集群的信息,但是存在一个问题,我们知道redis集群中存储数据的时候是使用哈希槽分区算法来分配数据的,如果我们以这种姿势启动客户端的话,如果set的key不属于所在主节点的集群的话,就会报错.
    在这里插入图片描述
    所以我们在启动客户端的时候,我们就需要在后面加上一个-c,这时候如果所添加的key不属于当前的集群的话,就会重定向到其他对应分片上的主机中.后期获取也是可以直接获取到的.
172.30.0.101:6379> set k1 1
-> Redirected to slot [12706] located at 172.30.0.103:6379
OK
172.30.0.103:6379> get k1
"1"

4. 主节点宕机自动处理流程

如果集群中的主节点发生了宕机,此处集群做的工作就和之前哨兵做的工作类似了,就会自动的把该主节点旗下的从结点给挑出来一提拔为主节点.
但是此处的故障处理转移,具体的流程还和哨兵有一些区别.

  1. 故障判定,通过周期性发送心跳包来判定某个结点是否挂掉.
    结点A首先给结点B发送ping包,如果B不能如期回应的时候,A就会尝试重置和B的tcp连接,看能否连接成功,如果仍然连接失败,A就会把B设置为PFAIL(主观下线)状态.== A判定B为主观下线之后,会通过redis内置的gossip协议,和其他节点进行沟通==,向其他节点确认B的状态.此时A发现其他很多结点都认为B主观下线了,并且数目超过了集群总个数的一半,那么A就会把B标记为客观下线.并且把这个消息同步给其他的结点,其他节点收到之后,也会把B标记为客观下线.

  2. 故障迁移
    如果B是从结点,就不需要进行故障迁移.如果B是主节点,那么就会由B的从结点(比如C和D)触发故障迁移.把从结点提拔为主节点.
    从结点首先判定自己是否具有参选资格.如果主节点和从结点太久没有通信,那么就证明主节点和从结点的数据差异太大了,就会失去竞选资格.具有资格的结点,比如C和D,就会先休眠一定的时间.休眠时间=500ms基础时间+[0,500ms]随机时间+排名*1000ms. 其中offset越大,则排名越靠前(越小),offset越大,数据就越靠近主节点,排名就会更靠前休眠时间也更短.比如C的休眠时间到了,C就会给其他所有集群中的结点进行拉票操作.但是只有主节点才有投票的资格.主节点就会把自己的票投给C.当C收到的票数超过主节点的一半的时候,C就会晋升为主节点.同时C还会把自己成为主节点的消息通知其他集群的结点,大家也都会更新自己保存的集群结构的信息.

上述的选举过程符合Raft算法,在随机休眠时间的加持之下,基本上谁先唤醒,谁就可以竞选成功.

上述和哨兵最明显的区别就是,哨兵是选取一个Leader来进行提拔主节点,而这里是直接通过主节点投票选举出主节点

5. 集群扩容

扩容会涉及到大量数据的迁移操作,所以扩容是一件风险比较高,成本比较大的操作.

  1. 把新的主节点加入到集群中
    redis-cli --cluster add-node 172.30.0.110:6379 172.30.0.101:6379
    add-node之后的第一组地址是新节点的地址,第二组是集群中的任意节点地址,表示把新的结点添加到哪个集群中去.
  2. 重新分配哈希槽位
    把之前Master上面的slots拎出来一些,分配给新的master.
    redis-cli --cluster reshard 172.30.0.101:6379
    reshard之后的地址是集群中任意一个结点的地址.
    执行之后,会进入交互式操作,redis会询问一下内容:
    • 多少个槽位需要reshard?
    • 哪个结点来接收槽位?此处填写新加入的结点.
    • 这些槽位从哪些结点搬运过来?此处如果填写all,表示的就是每个主节点都会拿一点槽位过来,如果手动指定,就会动指定的某个或者是几个节点来搬运槽位.
    • 之后会打印初步分配方案,让用户确认,确定的时候输入yes即可.在搬运真正开始的时候,此时不仅仅是槽位的重新划分,也会把槽位上对应的数据搬运到新的主机上,此时是一个比较重量的操作,可能需要消耗一定的时间.

注意在搬运的时候,在迁移的槽位不可被访问,其他未搬运的key是可以正常访问的

  1. 给新的主节点添加从结点
    redis-cli --cluster add-node 172.30.0.111:6379 172.30.0.101:6379 --clusterslave --cluster-master-id [172.30.1.110 节点的 nodeId]
    此时扩容目标初步达成,但是为了保证整个集群的可用性,还需要给主节点添加一些从结点,保证主节点宕机之后,有接班人.

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

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

相关文章

期权懂|上证50ETF期权的交易时间是什么时候?

期权小懂每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 上证50ETF期权的交易时间是什么时候&#xff1f; 一、开盘集合竞价时间‌&#xff1a; 上午9:15至9:25。在这段时间内&#xff0c;投资者可以提交或撤销委托&#xff0c;但不会立…

FPGA 第7讲 简单组合逻辑译码器

时间&#xff1a;2024.11.15 一、学习内容 1.译码器 译码是编码的逆过程&#xff0c;在编码时&#xff0c;每一种二进制代码&#xff0c;都赋予了特定的含义&#xff0c;即都表示了一个确定的信号或者对象。把代码状态的特定含义翻译出来的过程叫做译码&#xff0c;实现译码操…

jmeter常用配置元件介绍总结之断言

系列文章目录 安装jmeter jmeter常用配置元件介绍总结之断言 9.断言9.1.响应断言9.2.JSON断言9.3.大小断言9.4.JSON JMESPath Assertion9.5.断言持续时间9.6.MD5Hex断言9.7.XPath断言9.8.XPath2 Assertion 9.断言 检查测试中得到的响应数据结果是否符合预期 9.1.响应断言 功…

莱特币转型MEME币:背后隐含的加密市场现象

随着加密市场的风云变幻&#xff0c;莱特币&#xff08;LTC&#xff09;这款曾经的“老牌矿币”近日以自嘲式推文宣布“自己是一个MEME币”&#xff0c;迅速引发了市场的广泛关注和一波围绕MEME币的炒作浪潮。这一举动看似玩笑&#xff0c;却反映出当前加密市场的一种微妙转变&…

【网页设计】CSS3 进阶(动画篇)

1. CSS3 2D 转换 转换&#xff08;transform&#xff09;是CSS3中具有颠覆性的特征之一&#xff0c;可以实现元素的位移、旋转、缩放等效果 转换&#xff08;transform&#xff09;你可以简单理解为变形 移动&#xff1a;translate旋转&#xff1a;rotate缩放&#xf…

系统架构设计师:软件架构的演化和维护

软件架构一般会经历初始设计、实际使用、修改完善和退化弃用的过程&#xff0c;其中修改完善的过程实际上就是软件架构的演化和维护过程&#xff0c;演化和维护的目的就是为了使软件能够适应环境的变化而进行的纠错性修改和完善性修改等。 软件架构的演化和维护过程是一个不断…

如何在 Ubuntu 上安装 Jupyter Notebook

本篇文章将教你在 Ubuntu 服务器上安装 Jupyter Notebook&#xff0c;并使用 Nginx 和 SSL 证书进行安全配置。 我将带你一步步在云服务器上搭建 Jupyter Notebook 服务器。Jupyter Notebook 在数据科学和机器学习领域被广泛用于交互式编码、可视化和实验。在远程服务器上运行…

IoT [remote electricity meter]

IoT [remote electricity meter] 物联网&#xff0c;远程抄表&#xff0c;电表数据&#xff0c;举个例子

使用ivew-ui-plus 的Submit组件踩坑 injection “LoginInstance“ not found 记录 问题原因分析与解决方案

问题描述: 在下面这个页面中 注册按钮使用了view-ui-plus的Submit组件 结果控制台报错 runtime-core.esm-bundler.js:257 Uncaught TypeError: Cannot read properties of undefined (reading handleSubmit)at Proxy.handleSubmit (viewuiplus.min.esm.js:32610:26)at callW…

力扣 LeetCode 1047. 删除字符串中的所有相邻重复项(Day5:栈与队列)

解题思路&#xff1a; 方法一&#xff1a;栈 class Solution {public String removeDuplicates(String s) {Deque<Character> stack new ArrayDeque<>();for (char c : s.toCharArray()) {if (stack.isEmpty() || stack.peek() ! c) stack.push(c);else stack.p…

无人机检测车辆——多目标检测

目录 YOLOv3&#xff08;You Only Look Once version 3&#xff09;简介 YOLOv3 的主要特点 YOLOv3 的结构 1. 特征提取网络&#xff08;Backbone&#xff09; 2. 检测头&#xff08;Head&#xff09; 3. 输出层 YOLOv3 损失函数 YOLOv3 的优势 YOLOv3 的应用 YOLOv3…

集群搭建高可用

contos7.9 部署3节点 hadoop3.4 高可用集群 contos7.9 部署3节点 hadoop3.4 高可用集群环境信息Hadoop与Zookeeper的版本对应关系服务器角色分配使用端口服务器配置配置免密登录服务器配置初始化 init_server.sh配置主机名映射所有节点配置 hosts文件 hadoop 安装环境配置下载安…

网络IP地址会经常换吗?深入解析与实操指南

在互联网的生态系统中&#xff0c;IP地址&#xff08;Internet Protocol Address&#xff09;是每台连接设备的唯一标识符&#xff0c;它在网络通信中起着至关重要的作用。然而&#xff0c;不少用户观察到自己的IP地址有时会发生变化&#xff0c;这引发了诸多疑问。本文旨在详细…

AI测试的主要研究方向介绍

随着AI技术的不断进步和应用场景的日益广泛&#xff0c;如何确保人工智能系统的可靠性和安全性&#xff0c; 变得日益重要。人工智能测试作为保障AI系统质量的关键环节&#xff0c;也随着AI技术不断向前发展。本文将介绍当前AI测试的主要研究方向&#xff0c;以期为大家提供一个…

Python3中str和bytes

参考文章&#xff1a;浅析Python3中的bytes和str类型 - Chown-Jane-Y - 博客园 Python 3最重要的新特性之一是对字符串和二进制数据流做了明确的区分。文本总是Unicode&#xff0c;由str类型表示&#xff0c;二进制数据则由bytes类型表示。Python 3不会以任意隐式的方式混用str…

比特币前景再度不明,剧烈波动性恐即将回归

比特币市场降温&#xff0c;波动性增加 自特朗普赢得美国总统大选以来&#xff0c;比特币市场的投机狂热有所降温&#xff0c;现货和衍生品市场的活跃度开始减弱。比特币在上周五跌破87000美元&#xff0c;较之前创下的历史高点低了约6500美元。这一变化受到美联储主席鲍威尔讲…

node对接ChatGpt的流式输出的配置

node对接ChatGpt的流式输出的配置 首先看一下效果 将数据用流的方式返回给客户端,这种技术需求在传统的管理项目中不多见,但是在媒体或者有实时消息等功能上就会用到,这个知识点对于前端还是很重要的。 即时你不写服务端,但是服务端如果给你这样的接口,你也得知道怎么去使用联…

esp32c3安装micropython环境

esp32c3竟然支持micropython环境&#xff0c;真的太让人高兴了。主要是python开发比较友好&#xff0c;开发速度要快于C和C&#xff0c; 可以用来快速创意验证。 下载 首先到官网&#xff1a;MicroPython - Python for microcontrollers 点击“download”进入下载页面&#…

Linux运维工程师推荐学习的开发语言

前言&#xff1a;会开发的运维和不会开发的运维可以说是两个世界的运维。 个人推荐python和go&#xff0c;前者可以做自动化运维&#xff0c;后者可以深挖k8s&#xff1b;最近就不先演示运维服务技术的部署和架构搭建了&#xff0c;在深挖自动化运维&#xff0c;为了让现在的工…

新手小白学习docker第八弹------实现MySQL主从复制搭建

目录 0 引言1 实操1.1 新建主服务器容器1.2 书写配置文件1.3 重启master实例1.4 进入mysql-master容器master容器实例内创建数据同步用户 1.5 新建从服务器容器1.6 书写配置文件1.7 重启slave实例1.8 查看主从同步状态1.9 进入mysql-slave容器1.9.1 配置主从复制1.9.2 查看主从…