Kubernetes入门 八、StatefulSet控制器

news2024/9/21 23:37:12

目录

  • 概述
  • 创建StatefulSet
  • Pod 的管理策略
    • 扩容缩容
  • 镜像更新
    • 滚动更新
    • 分区更新
    • 删除更新
  • 删除

概述

Stateful 翻译为 有状态的 ,也是pod控制器的一种。

StatefulSet 是为了解决有状态应用的问题,Deployment是为无状态应用设计的。

  • 无状态应用:网络可能会变(IP 地址)、存储可能会变(卷)、顺序可能会变(启动的顺序)。应用场景:业务代码,如:使用 SpringBoot 开发的商城应用的业务代码。

  • 有状态应用:网络不变、存储不变、顺序不变。应用场景:中间件,如:MySQL 集群、Zookeeper 集群、Redis 集群、MQ 集群。

Stateful 具有以下特点:

  • 稳定的持久化存储,即 Pod 重新调度后还是能访问到相同的持久化数据,基于 PVC 来实现
  • 稳定的网络标志,即 Pod 重新调度后其 PodName 和 HostName 不变,基于 Headless Service(即没有 Cluster IP 的 Service)来实现
  • 有序部署,有序扩展,即 Pod 是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依序进行(即从 0 到 N-1,在下一个 Pod 运行之前所有之前的 Pod 必须都是 Running 和 Ready 状态),基于 init containers 来实现
  • 有序收缩,有序删除(即从 N-1 到 0)

StatefulSet 由以下几个部分组成:

  • 用于定义网络标志(DNS domain)的 Headless Service
  • 用于创建 PersistentVolumes 的 volumeClaimTemplates
  • 定义具体应用的 StatefulSet

StatefulSet 通过和其相关的无头服务为每个 Pod 提供 DNS 解析条目,并且每个 Pod 都是唯一的。

StatefulSet 中每个 Pod 的 DNS 条目为 statefulSetName-{0…N-1}.serviceName.namespace.svc.cluster.local

  • serviceName 为 Headless Service 的名字
  • 0…N-1 为 Pod 所在的序号,从 0 开始到 N-1
  • statefulSetName 为 StatefulSet 的名字
  • namespace 为服务所在的 namespace,Headless Servic 和 StatefulSet 必须在相同的 namespace
  • .cluster.local 为 Cluster Domain

我们可以通过这个dns域名直接访问,也可以省略的使用statefulSetName-{0…N-1}.serviceName就可以访问,后面我们会验证。

注意事项:

  • kubernetes v1.5 版本以上才支持
  • 给定 Pod 的存储必须由 PersistentVolume 驱动 基于所请求的 storage class 来提供,或者由管理员预先提供。
  • 删除或者收缩 StatefulSet 并不会删除它关联的存储卷。 这样做是为了保证数据安全,它通常比自动清除 StatefulSet 所有相关的资源更有价值。
  • StatefulSet 需要一个 Headless Service 来定义 DNS domain,需要在 StatefulSet 之前创建好。
  • 当删除 StatefulSets 时,StatefulSet 不提供任何终止 Pod 的保证。 为了实现 StatefulSet 中的 Pod 可以有序地且体面地终止,可以在删除之前将 StatefulSet 缩放为 0。
  • 在默认 Pod 管理策略(OrderedReady) 时使用 滚动更新,可能进入需要人工干预才能修复的损坏状态。

创建StatefulSet

一般我们还是通过yaml文件来创建StatefulSet。

创建nginx-sts.yaml文件,内容如下:

---
# 在yaml中,---中间的内容,属于嵌套配置,这里用于将 StatefulSet 加入网络
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None  # 不分配 ClusterIP ,形成无头服务,整个集群的 Pod 能直接访问,但是浏览器不可以访问。
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: nginx  # 使用哪个service来管理dns,,这个字段需要和 service 的 metadata.name 相同
  replicas: 2
  selector:  # 选择器,用于定义管理的指定资源的标签(Service和Pod)
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:  # 容器内部暴漏的端口
        - containerPort: 80  # 具体的端口
          name: web  # 端口的名字
        volumeMounts:  # 数据卷挂载
        - name: www  # 数据卷名字
          mountPath: /usr/share/nginx/html  # 加载到容器内的哪个目录
  volumeClaimTemplates:  # 数据卷模板
  - metadata:
      name: www  # 数据卷名称
      annotations:  # 注解信息
        volume.alpha.kubernetes.io/storage-class: anything
    spec:  # 数据卷配置
      accessModes: [ "ReadWriteOnce" ]  # 访问模式
      resources:  # 资源配置
        requests:
          storage: 1Gi

然后执行创建命令:

kubectl create -f nginx-sts.yaml
# 结果如下,service和statefulset都创建出来了
service/nginx created
statefulset.apps/web created

查看service:

kubectl get svc
# 结果如下,第一个是默认的,不用管,第二个ngin使我们创建出来的
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   9d
nginx        ClusterIP   None         <none>        80/TCP    103s

查看statefulset:

kubectl get sts
# 结果如下
NAME   READY   AGE
web    2/2     3m5s

查看存储卷PersistentVolumes:

kubectl get pvc
# 结果如下
NAME        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0   Bound    pvc-bdd3c8f0-8a9d-4c3c-ac3e-2fe6701d6c01   1Gi        RWO            hostpath       3m59s
www-web-1   Bound    pvc-54a1dab2-59ea-4611-9d73-312789c3d5f7   1Gi        RWO            hostpath       3m56s

查看po:

kubectl get po
# 结果如下
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          7m29s
web-1   1/1     Running   0          7m26s

可以看到pod的名字后缀和deployment不一样,这里是数字,deployment是一串字符串。

接着我们新创建一个容器,看看能否在新容器中通过name访问到这个容器。

# busybox是一个linux的工具包镜像;--restart=Never表示不重启, --rm:运行完的时候删除
kubectl run -it --image busybox dns-test --restart=Never --rm /bin/sh
# 成功后进入容器的终端控制台
If you don't see a command prompt, try pressing enter.
/ #

我们在容器内ping下刚刚创建的web-0 pod:

# web-0是pod的名字,nginx是svc的名字
ping web-0.nginx
# 结果如下
PING web-0.nginx (10.1.0.80): 56 data bytes
64 bytes from 10.1.0.80: seq=0 ttl=64 time=0.601 ms
64 bytes from 10.1.0.80: seq=1 ttl=64 time=0.190 ms
64 bytes from 10.1.0.80: seq=2 ttl=64 time=0.325 ms
64 bytes from 10.1.0.80: seq=3 ttl=64 time=0.294 ms

同样的,pod web-1也是可以ping通的。

这样就证明了service为pod提供了稳定网络,固定的dns,可以通过dns直接访问。

Pod 的管理策略

StatefulSet 的 Pod 的管理策略(podManagementPolicy)分为:

  • OrderedReady(有序启动,默认值):也就是pod的创建是按照顺序来的,启动后,我们看到后缀数字就是其顺序。
  • Parallel(并发一起启动):pod的创建没有顺序。

配置如下:

...
spec:
  podManagementPolicy: OrderedReady # 控制 Pod 创建、升级以及扩缩容逻辑。Parallel(并发一起启动) 和 
...

一般我们不用去修改。

扩容缩容

与deployment一样,statefulSet也可以实现扩容缩容。也是通过修改我们的副本数即可。

方式也是一样,这里我们再回顾一下:

  1. 使用 Kubectl edit 命令,修改 spec:replicas:n 即可
kubectl edit sts web
  1. 使用 scale 命令实现扩缩容
kubectl scale sts web --replicas=5
  1. 修改 yaml 文件中 spec.replicas 字段,随后使用 kubectl apply -f xxx.yaml 命令即可
vim nginx-sts.yaml
kubectl apply -f nginx-sts.yaml
  1. 使用patch命令
kubectl patch statefulset web -p '{"spec":{"replicas":3}}'

示例:

使用下面命令扩容:

kubectl scale sts web --replicas=5
# statefulset.apps/web scaled

查看statefulset:

kubectl get sts
# 结果如下
NAME   READY   AGE
web    5/5     37m

可以看到结果变成了5个。

通过describe查看下Events信息:

kubectl describe sts web

结果如下:

Events:
  Type    Reason            Age   From                    Message
  ----    ------            ----  ----                    -------
  Normal  SuccessfulCreate  38m   statefulset-controller  create Claim www-web-0 Pod web-0 in StatefulSet web success
  Normal  SuccessfulCreate  38m   statefulset-controller  create Pod web-0 in StatefulSet web successful
  Normal  SuccessfulCreate  37m   statefulset-controller  create Claim www-web-1 Pod web-1 in StatefulSet web success
  Normal  SuccessfulCreate  37m   statefulset-controller  create Pod web-1 in StatefulSet web successful
  Normal  SuccessfulCreate  91s   statefulset-controller  create Claim www-web-2 Pod web-2 in StatefulSet web success
  Normal  SuccessfulCreate  91s   statefulset-controller  create Pod web-2 in StatefulSet web successful
  Normal  SuccessfulCreate  88s   statefulset-controller  create Claim www-web-3 Pod web-3 in StatefulSet web success
  Normal  SuccessfulCreate  88s   statefulset-controller  create Pod web-3 in StatefulSet web successful
  Normal  SuccessfulCreate  85s   statefulset-controller  create Claim www-web-4 Pod web-4 in StatefulSet web success
  Normal  SuccessfulCreate  85s   statefulset-controller  create Pod web-4 in StatefulSet web successful

可以看到pod后缀依次从0到4,共5个。

再进行缩容看下:

kubectl scale sts web --replicas=3
# statefulset.apps/web scaled

直接查看Events:

Events:
  Type    Reason            Age    From                    Message
  ----    ------            ----   ----                    -------
  Normal  SuccessfulCreate  41m    statefulset-controller  create Claim www-web-0 Pod web-0 in StatefulSet web success
  Normal  SuccessfulCreate  41m    statefulset-controller  create Pod web-0 in StatefulSet web successful
  Normal  SuccessfulCreate  41m    statefulset-controller  create Claim www-web-1 Pod web-1 in StatefulSet web success
  Normal  SuccessfulCreate  41m    statefulset-controller  create Pod web-1 in StatefulSet web successful
  Normal  SuccessfulCreate  5m13s  statefulset-controller  create Claim www-web-2 Pod web-2 in StatefulSet web success
  Normal  SuccessfulCreate  5m13s  statefulset-controller  create Pod web-2 in StatefulSet web successful
  Normal  SuccessfulCreate  5m10s  statefulset-controller  create Claim www-web-3 Pod web-3 in StatefulSet web success
  Normal  SuccessfulCreate  5m10s  statefulset-controller  create Pod web-3 in StatefulSet web successful
  Normal  SuccessfulCreate  5m7s   statefulset-controller  create Claim www-web-4 Pod web-4 in StatefulSet web success
  Normal  SuccessfulCreate  5m7s   statefulset-controller  create Pod web-4 in StatefulSet web successful
  Normal  SuccessfulDelete  104s   statefulset-controller  delete Pod web-4 in StatefulSet web successful
  Normal  SuccessfulDelete  103s   statefulset-controller  delete Pod web-3 in StatefulSet web successful

可以看到最后两行,依次把web-4和web-3删除了。也就是删除也是从后往前删除。

镜像更新

StatefulSet支持两种镜像更新策略:滚动更新(RollingUpdate)删除更新(OnDelete)。默认是RollingUpdate。

其配置如下:

...
spec:
  updateStrategy: # 更新策略
    type: RollingUpdate # OnDelete 删除之后才更新;RollingUpdate 滚动更新
    rollingUpdate:
      partition: 0 # 更新索引 >= partition 的 Pod ,默认为 0
...

滚动更新

StatefulSet的镜像更新目前还不支持set命令直接更新 image,需要 patch 来间接实现,如下:

kubectl patch sts web --type='json' -p='[{"op": "replace", "path":"/spec/template/spec/containers/0/image", "value":"nginx:1.9.1"}]'
# statefulset.apps/web patched

执行完命令后看下我们StatefulSet:

kubectl get sts
# 结果如下
NAME   READY   AGE
web    3/3     56m

查看版本:

kubectl rollout history sts web
statefulset.apps/web
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

可以看到已经有两个版本了。

查看版本2的信息:

kubectl rollout history sts web --revision=2
# 结果如下:看到更新到版本1.9.1了
statefulset.apps/web with revision #2
Pod Template:
  Labels:	app=nginx
  Containers:
   nginx:
    Image:	nginx:1.9.1
    Port:	80/TCP
    Host Port:	0/TCP
    Environment:	<none>
    Mounts:
      /usr/share/nginx/html from www (rw)
  Volumes:	<none>

然后查看Events:

Events:
  Type    Reason            Age                From                    Message
  ----    ------            ----               ----                    -------
 # 只看最后6行即可
  Normal  SuccessfulDelete  39s                statefulset-controller  delete Pod web-2 in StatefulSet web successful
  Normal  SuccessfulCreate  38s (x2 over 19m)  statefulset-controller  create Pod web-2 in StatefulSet web successful
  Normal  SuccessfulDelete  37s                statefulset-controller  delete Pod web-1 in StatefulSet web successful
  Normal  SuccessfulCreate  36s (x2 over 56m)  statefulset-controller  create Pod web-1 in StatefulSet web successful
  Normal  SuccessfulDelete  35s                statefulset-controller  delete Pod web-0 in StatefulSet web successful
  Normal  SuccessfulCreate  34s (x2 over 56m)  statefulset-controller  create Pod web-0 in StatefulSet web successful

可以看到滚定更新全过程,是删除一个,再创建一个新的,依次一个一个地更新。

由 默认的,pod 是有序的,在 StatefulSet 中更新时也是基于 pod 的顺序倒序更新的。

分区更新

上面我们知道在配置更新策略时,还有一个partition的概念。

例如我们有 5 个 pod,如果当前 partition 设置为 3,那么此时滚动更新时,只会更新那些 序号 >= 3 的 pod。 partition 默认为0,也就是全部更新。

利用该机制,我们可以通过控制 partition 的值,来决定只更新其中一部分 pod,确认没有问题后再主键增大更新的 pod 数量,最终实现全部 pod 更新。

利用 滚动更新的partition 可以实现类似灰度发布/金丝雀发布的效果。

灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。AB test就是一种灰度发布方式,让一部用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。

接下来看下如何实现灰度发布。

首先还使用我们前面创建的,修改副本数为5:

kubectl scale sts web --replicas=5
# statefulset.apps/web scaled

然后通过edit命令修改sts:

kubectl edit sts web

修改我们的 partition值为3,即只有序号大于等于3的才会更新;修改镜像版本为1.7.9(原来为1.9.1):

在这里插入图片描述

编辑好后保存并退出。

查看pod:

kubectl get po
# 结果如下
NAME       READY   STATUS    RESTARTS   AGE
dns-test   1/1     Running   0          79m
web-0      1/1     Running   0          37m
web-1      1/1     Running   0          37m
web-2      1/1     Running   0          37m
web-3      1/1     Running   0          15s
web-4      1/1     Running   0          17s

这样看不出效果,再查看具体pod web-3的信息:

kubectl describe po web-3

结果如下,看到版本已经变为1.7.9。

在这里插入图片描述

再查看具体pod web-2的信息:

kubectl describe po web-2

结果如下,看到版本还是1.9.1:

在这里插入图片描述

同理,可以查看其他pod。得出结论:pod后面序号为0,1,2的没有更新,序号为3和4的更新了。也就验证了partition的作用。

接着如果发现序号为3和4的使用没问题,我们可以把partition改为0,实现全部更新。这里就不在演示了。

以上步骤就可以实现灰度发布的效果了。

删除更新

当使用删除更新的策略时,我们修改了镜像版本,并不会马上去更新。当我们手动删除某个pod时,就会吃席创建出一样的pod,这个时候,就会更新成最新的镜像了。

删除更新不常用,就不再演示了。

删除

创建StatefulSet时,会创建出三个资源:StatefulSet、Service、Pod。

当我们需要删除时,

执行如下命令:

kubectl delete statefulset web

注意:当我们删除statefulset时,会级联删除下面所有的Pod。

但是Service不会被级联删除,需要单独删除,如下:

kubectl delete service nginx

如果不想级联删除Pod,可以使用如下命令:

kubectl deelte sts web --cascade=false

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

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

相关文章

Python 驱动连接 OceanBase 数据库

安装 JayDeBeApi 驱动 pip3 install JayDeBeApi 待更新 Python 驱动连接 OceanBase 数据库_云数据库 OceanBase 版-阿里云帮助中心

《你当像鸟飞往你的山》 书目总结

《你当像鸟飞往你的山》 书目总结

二、7.用户进程

TSS 是 x86CPU 的特定结构&#xff0c;被用来定义“任务”&#xff0c;它是内置到处理器原生支持的多任务的一种形式。 通过 call 指令&#xff0b;TSS 选择子的形式进行任务切换&#xff0c;此过程大概分成 10 步&#xff0c;这还是直接用 TSS 选择子进行任务切换的步骤&…

卷积神经网络——下篇【深度学习】【PyTorch】

文章目录 5、卷积神经网络5.10、⭐批量归一化5.10.1、理论部分5.10.2、代码部分 5.11、⭐残差网络&#xff08;ResNet&#xff09;5.11.1、理论部分5.11.2、代码部分 话题闲谈 5、卷积神经网络 5.10、⭐批量归一化 5.10.1、理论部分 批量归一化可以解决深层网络中梯度消失和…

分享因缺少 xPortSysTickHandler()函数而导致程序一直卡死在函数portTASK_FUNCTION的案例分析

今天来分享一个在学习freertos过程中遇到的一个小问题。就是发现程序跑不起来&#xff0c;但是debug调试时候发现也没有到while循环中&#xff0c;于是通过排查发现是因为缺少相应的SysTick中断服务函数导致的。话不多说&#xff0c;我们开始讲~ 问题锁定&#xff1a; 首先这…

springboot跨域踩坑笔记

事情是这样的&#xff0c;我在进行前后端联调的时候&#xff0c;发送了跨域拦截 马上在spring项目中创建一个CorsConfig类 package com.example.demo.config;import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.an…

聚观早报 | 抢先体验阿维塔11座舱;本田和讴歌采用NACS充电标准

【聚观365】8月21日消息 抢先体验阿维塔11鸿蒙座舱 本田和讴歌采用特斯拉NACS充电标准 华为秋季新品发布会将于9月12日举行 iQOO Z8即将到来 三星Galaxy S24系列外观或更改 抢先体验阿维塔11鸿蒙座舱 当前&#xff0c;智能座舱成了各大巨头跑马圈地的重要领域。根据毕马威…

国标GB28181安防视频平台EasyGBS通过对应密钥上传到其他平台展示的详细步骤来啦!

国标GB28181协议视频平台EasyGBS是基于国标GB28181协议的视频云服务平台&#xff0c;支持多路设备同时接入&#xff0c;并对多平台、多终端分发出RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。平台可提供视频监控直播、云端录像、云存储、检索回放、智能告警、语音对讲、平台级…

C# 使用递归方法实现汉诺塔步数计算

C# 使用递归方法实现汉诺塔步数计算 Part 1 什么是递归Part 2 汉诺塔Part 3 程序 Part 1 什么是递归 举一个例子&#xff1a;计算从 1 到 x 的总和 public int SumFrom1ToX(int x) {if(x 1){return 1;}else{int result x SumFrom1ToX_2(x - 1); // 调用自己return result…

交换机常见配置、H3C防火墙配置

真机演示学习 console线连接之后&#xff0c;检查电脑有无console线对应的驱动&#xff0c;无则根据型号去网上下载驱动 交换机的端口类型是百兆还是千兆&#xff08;e为百兆&#xff0c;g为千兆&#xff09;&#xff1a; 如果是百兆端口&#xff0c;那么调试时的接口名称就…

FastViT:一种使用结构重新参数化的快速混合视觉变换器

文章目录 摘要1、简介2、相关工作3、体系结构3.1、概述3.2、FastViT3.2.1、重新参数化跳过连接3.2.2、线性训练时间过参数化3.2.3、大核卷积 4、实验4.1、图像分类4.2、鲁棒性评价4.3、3D Hand网格估计4.4、语义分割和目标检测 5、结论 摘要 论文&#xff1a;https://arxiv.or…

为什么20位数据总线决定寻址空间是2^20B,即1MB,而不是2^20/2^3=2^17B????

升级版的说明 –升级了一下图片&#xff1b;增加了对按字节编制的默认设定的说明&#xff0c;免得引起误导&#xff1b;去掉了之前评论区有人说单位的问题。 老版链接&#xff1a; http://t.csdn.cn/pYIXD 小白的疑惑 小白刚开始学习的时候很疑惑&#xff0c;为什么20位地…

实验二 Hdoop2.7.6+JDK1.8+SSH的安装部署与基本操作

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目…

电商系统架构设计系列(九):如何规划和设计分库分表?

上篇文章中&#xff0c;我给你留了一个思考题&#xff1a;分库分表该如何设计&#xff1f; 今天这篇文章&#xff0c;我们来聊一下如何规划和设计分库分表&#xff0c;以及要考虑哪些问题。 引言 当要解决海量数据的问题&#xff0c;就必须要用到分布式的存储集群了&#xff…

银河麒麟服务器版ky10 server arm版设置网卡开机自启

cd /etc/sysconfig/network-scripts 命令进入制定路径 pwd 查看当前路径 ip a命令查看网卡信息&#xff0c;确认用到的网卡是哪一张 ls 查看网卡配置文件 &#xff0c;找到名称跟 ip a 查询出来的一致的网卡 修改对应网卡 vi *0f0&#xff1a;网卡后缀对应上即可 修改网卡开…

【LeetCode】224. 基本计算器

224. 基本计算器&#xff08;困难&#xff09; 方法&#xff1a;双栈解法 思路 我们可以使用两个栈 nums 和 ops 。 nums &#xff1a; 存放所有的数字ops &#xff1a;存放所有的数字以外的操作&#xff0c;/- 也看做是一种操作 然后从前往后做&#xff0c;对遍历到的字符做…

亥姆霍兹线圈在各行业中的作用

亥姆霍兹线圈是指两个相同的同轴圆形线圈&#xff0c;它们的圆心之间相隔一个相同的距离&#xff0c;并且电流的方向相反。亥姆霍兹线圈的作用非常广泛&#xff0c;不仅在物理学实验中得到广泛应用&#xff0c;而且在医学磁共振成像、电子学和通信领域中也有广泛的应用。 亥姆霍…

java学习——二叉树

二叉树的种类&#xff1a; 满二叉树&#xff1a;如果一棵二叉树只有度为0的结点和度为2的结点&#xff0c;并且度为0的结点在同一层上&#xff0c;则这棵二叉树为满二叉树。 完全二叉树&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层…

代码随想录第27天|39. 组合总和,40.组合总和II,131.分割回文串

39. 组合总和 分析这道题的搜索过程如下&#xff1a; 因为这道题没有限制要搜索几层&#xff0c;所以可以一直搜索直到sumtarget或者sum>target就return 回溯三部曲 1.递归函数参数 本题还需要startIndex来控制for循环的起始位置&#xff0c;对于组合问题&#xff0c;什么…

净水器赛道迈向“柠檬市场”,易开得彰显自己的“价值主张”

作者 | 曾响铃 文 | 响铃说 一直以来&#xff0c;关于第一台净水器的诞生都有着不小的争论&#xff0c;有说是因为19世纪的一场霍乱&#xff0c;也有说是因为20世纪的水污染&#xff0c;但无论哪种说法&#xff0c;恰恰也说明净水产品在人类近代发展历程中都有着举足轻重的地…