Docker Volume (存储卷)

news2024/12/23 6:10:12

什么是存储卷?

存储卷就是将宿主机的本地文件系统中存在的某个目录直接与容器内部的文件系统上的某一目录建立绑定关系。这就意味着,当我们在容器中的这个目录下写入数据时,容器会将其内容直接写入到宿主机上与此容器建立了绑定关系的目录。在宿主机上的这个与容器形成绑定关系的目录被称作存储卷

的本质是文件或者目录,它可以绕过默认的联合文件系统,直接以文件或目录的形式存在于宿主机上。

宿主机的 /data/web 目录与容器中的 /container/data/web 目录绑定关系,然后容器中的进程向这个目录中写数据时,是直接写在宿主机的目录上的,绕过了容器文件系统,与宿主机的文件系统建立关联关系,实现了宿主机和容器共享数据共享。让容器直接访问宿主机中的内容,也可以宿主机向容器写入内容,容器和宿主机的数据读写是同步的。

不好理解的话,可以将这个过程看作是在你的 Windows 电脑上插了个 U 盘。其实也没有什么不好理解的,可以先看看后面的实战部分再来理解。

为什么需要存储卷?

  1. 数据丢失问题
    容器按照业务类型,总体可以分为两类:

    • 无状态的(数据不需要被持久化)
    • 有状态的(数据需要被持久化)

    显然,容器更擅长无状态应用。因为未持久化数据的容器根目录的生命周期与容器的生命周期一样,容器文件系统的本质是在镜像层上面创建的读写层,运行中的容器对任何文件的修改都存在于该读写层,当容器被删除时,容器中的读写层也会随之消失。虽然容器希望所有的业务都尽量保持无状态,这样容器就可以开箱即用,并且可以任意调度,但实际业务总是有各种需要数据持久化的场景,比如 MySQL、Kafka 等有状态的业务。因此为了解决有状态业务的需求,Docker 提出了卷(Volume)的概念。

  2. 性能问题
    UnionFS 对于修改删除等,一般效率非常低,如果对一于 I/O 要求比较高的应用,使用 Docker 的联合文件系统可能就不是非常适合了!如 redis 在实现持久化存储时,在底层存储时的性能要求比较高。

  3. 宿主机和容器互访不方便
    宿主机访问容器,或者容器访问要通过 docker cp 来完成,操作非常不方便。

  4. 容器和容器共享不方便
    每个 Docker 容器在运行时都是隔离的,拥有自己独立的文件系统、进程空间和网络环境等。这种隔离性保证了容器的安全性和稳定性,但同时也带来了一些限制,如文件共享的不便。我们即使是使用 docker cp 命令也无法直接将文件从一个容器拷贝到另一个文件。

存储卷分类

目前 Docker 提供了三种方式将数据从宿主机挂载到容器中。

  1. volume docker 管理卷,默认映射到宿主机的 /var/lib/docker/volumes 目录下,只需要在容器内指定容器的挂载点是什么,而被绑定宿主机下的那个目录,是由 Docker 容器引擎 daemon 自行创建一个空的目录,或者使用一个已经存在的目录,与存储卷建立存储关系,这种方式极大解脱用户在使用卷时的耦合关系,缺陷是用户无法指定那些使用目录,适用于临时存储。
  2. bind mount 绑定数据卷,映射到宿主机指定路径下,在宿主机上的路径要人工的指定一个特定的路径,在容器中也需要指定一个特定的路径,两个已知的路径建立关联关系。
  3. tmpfs mount 临时数据卷,映射到于宿主机内存中,一旦容器停止运行,tmpfs mount 会被移除,数据就会丢失,用于高性能的临时数据存储。

在这里插入图片描述

管理卷 Volume

Volume 命令操作

docker volume create

  • 功能:创建存储卷。
  • 语法:
    docker volume create [OPTIONS] [VOLUME]
    
  • 参数:
  • -d–drive:用于指定创建数据卷时所使用的存储驱动。这个不用管使用默认的 local 就行了。
  • –label:该选项允许为存储卷添加元数据标签。这些标签是以键值对的形式存储的,可以用于标识、分类或过滤卷。通过给存储卷添加标签,你可以更灵活地管理和查询存储卷。
  • 演示:

如下图,我们不指定创建的管理卷名称,Docker 会给我随机生成一个管理卷的名称。当我们指定创建出的管理卷的名称就使用自己指定的!我们在创建时指定的元数据标签可以通过 docker volume inspect 查看!其次,通过该命令还能查看挂载点,即 Docker 引擎自行创建的一个空目录,可以用于将来容器的绑定!
在这里插入图片描述

可以看到确实是一个空的目录:
在这里插入图片描述

docker volume inspect

  • 功能:查看一个或者多个卷的详细信息。
  • 语法:
    docker volume inspect [OPTIONS] VOLUME [VOLUMES]
    
  • 参数:
    • -f:指定返回的文件格式,例如:json。
  • 演示:
    通过 docker volume inspect 我们能看到卷的详细信息。包括:卷的创建时间,卷的驱动,卷的标签,卷的挂载点,卷的名字等等。
    在这里插入图片描述

docker volume ls

  • 功能:列出所有卷。

  • 语法:

    docker volume ls [OPTIONS]
    
  • 别名:

    docker volume list
    
  • 参数:

    • -f–filter:按指定条件过滤。
    • -q:仅显示名称。
    • –format:指定返回的格式,如:json。
  • 演示:

我们可以列出全部的卷,也可以按照条件筛选。
在这里插入图片描述

是 purpose 哈,单词刚刚拼写错了,不好意思哈!​😭​😭​😭​😭​😭​😭​😭​😭

docker volume rm

  • 功能:删除卷,前提条件是容器不使用!
  • 语法:
    docker volume rm [OPTIONS] VOLUME [VOLUME...]
    
  • 参数:
    • -f–force:强制删除。
  • 演示:
    如下图:我们尝试删除一个正在被容器使用的卷,是会直接报错的!!!
    在这里插入图片描述

我们将这个容器停止之后还是不能删除,除非加上 -f 选项,或者将容器删除!!
在这里插入图片描述
在这里插入图片描述

docker volume prune

  • 功能:删除不使用的本地卷
  • 语法:
    docker volume prune [OPTIONS]
    
  • 参数:
    • -f–force:不提示是否删除。
    • –filter:过滤。
  • 演示:
    如下图,我们直接将本地不使用的卷全部删除。
    在这里插入图片描述
    可以看到,他不能删除我们手动命名的卷!

-v 参数

  • 功能:完成目录映射,之前我们使用 docker volume create 知识创建了管理卷,我们需要在容器创建的时候指定 -v 参数来完成容器目录和管理卷的绑定(映射)。
  • 语法:
    docker run -v name:directory[:options]
    
  • 参数:
    • name:卷的名称。
    • directory:卷映射到容器的目录,不可以使用相对路径!。
    • options:选项,如 ro 表示 readonly,只读。
  • 演示:
    如下图:我们在用 nginx 镜像启动并运行一个容器的时候指定 -v 选项,将 nginx 服务器首页的 index.html 文件所在的目录绑定到 myvolume1 这个管理卷上。我们查看 myvolume1 的挂载点,并且看一看里面的内容!可以看到内容符合我们的预期!
    在这里插入图片描述
    现在,我们在宿主机上对 index.html 文件的内容进行修改,然后通过浏览器访问,看主页会不会发生变化!我们使用 vim 打开 index.html,然后对内容进行修改。我在网上找了一个相对好看的 html css 页面!!
    在这里插入图片描述
    使用浏览器访问,发现首页的确发生了变化,说明容器绑定存储卷之后,目录下的文件在宿主机和容器是共享的!!
    在这里插入图片描述
    同理,对容器目录下文件的修改宿主机也是可以看到的!前提是该目录下的文件可以修改哈!
    如下图:我们在容器内对目录下的文件做修改,在宿主机上能看到修改之后的内容。
    在这里插入图片描述

我们在启动容器的时候在 -v 选项后面加上 ro 表示只读,这样的话,在容器中就没有办法对 绑定(映射) 的目录做更改了!
如下图:指定 ro 选项之后,我们尝试在容器中对映射目录下的文件做更改会直接报错!!!
在这里插入图片描述
我们退出容器,在宿主机上对文件进行修改是没有问题的!
在这里插入图片描述
在这里插入图片描述


如下图:当我们使用 -v 选项指定一个不存在的管理卷时,Docker 引擎会自动帮我们创建这个管理卷。
在这里插入图片描述


我们可以使用 docker inspect 命令,在容器的详细信息中看到卷的挂载信息!Typevolume 表示是管理卷哈!
在这里插入图片描述

--mount 参数

  • 功能:完成目录映射。

  • 语法:

    --mount '<key>=<value>, <key>=<value>'
    
  • 参数:

    • type:存储卷的类型,bind 表示绑定数据卷,volume 表示存储卷,tmpfs 表示临时数据卷。
    • sourcesrc:对于命名卷,这是卷的名称;对于匿名卷,省略这个字段即可!
    • destinationdsttarget:文件或目录挂载在容器中的路径,不可以使用相对路径!!。
    • roreadonly:只读方式挂载。
  • 演示:
    如下图:我们使用 nginx 镜像启动并运行一个容器!不指定 type 默认是管理卷 (volume),不指定 src 会创建一个匿名卷,也就是 Docker 引擎帮我们创建一个,名字随机!
    在这里插入图片描述

如果想设置为只读:只读不能使用匿名卷哦!

docker run -d --name mynginx1 -p 9999:80 --mount src=myvolume1, dst=/usr/share/nginx/html, readonly nginx:1.25.4

同样地,使用 --mount 选项,如果 src 指定的卷不存在,会自动创建的哦!


我们使用 nginx 镜像启动并运行一个容器,使用 --mount 参数,并且不指定 type

docker run -d --name mynginx1 -p 9999:80 --mount src=myvolume5,dst=/usr/share/nginx/html nginx:1.25.4

可以看到,默认的 type 就是 volume 即管理卷!
在这里插入图片描述

绑定卷 bind

-v 参数和 --mount 参数都可以完成绑定卷的创建。

-v 参数

  • 功能:完成卷映射。
  • 语法:
    docker run -v name:directory[:options]
    
  • 参数:
    • name必须是宿主机的目录,这个和管理卷不同。不可以使用相对路径!
    • directory:卷映射到容器的目录,不可以使用相对路径!
    • options:选项,如 ro 表示 readonly,只读。
  • 演示:
    如下图:我们使用 -v 选项创建一个绑定卷,因为我之前没有创建 /root/test_bind 这样的目录,Docker 就会自动帮我们创建!我们查看这个目录下的内容,发现啥也没有!
    在这里插入图片描述
    这也就意味着容器中的 /usr/share/nginx/html 目录下也是空的。使用浏览器访问就会访问出错!
    在这里插入图片描述

可见绑定卷和管理卷在这一方面还是有差别的,管理卷能将容器映射目录中的内容进行同步,而绑定卷只在乎宿主机目录的内容!


同样,我们可以通过 docker inspect mynginx1 命令来查看容器的挂载情况。可以看到 typebind 表示绑定卷
在这里插入图片描述

--mount 参数

  • 功能:完成卷映射。
  • 语法:
    --mount '<key>=<value>, <key>=<value>'
    
  • 参数:
    • type:存储卷的类型,bind 表示绑定数据卷,volume 表示存储卷,tmpfs 表示临时数据卷。
    • sourcesrc:对于命名卷,这是卷的名称;对于匿名卷,省略这个字段即可!
    • destinationdsttarget:文件或目录挂载在容器中的路径,不可以使用相对路径!!。
    • roreadonly:只读方式挂载。
  • 演示:
    我们使用以下命令,以 --mount 选项创建一个绑定卷!然后通过 docker inspect 查看容器的 Mounts 信息。
docker run -d --name mynginx1 -p 9999:80 --mount type=bind,src=/root/test_bind,dst=/usr/share/nginx/html nginx:1.25.4

在这里插入图片描述

临时卷 tmpfs


临时卷数据位于内存中,在容器和宿主机之外。

tmpfs 局限性

  • 不同于卷和绑定挂载,不能在容器之间共享 tmpfs 挂载。
  • 这个功能只有在 Linux 上运行 Docker 时才可用。Windows 用不了,嘻嘻嘻!

--tmpfs 选项创建临时卷

  • 功能:完成临时卷映射。
  • 语法:
    --tmpfs DPCKER_PATH
    
  • 演示:
    我们使用 docker run 命令运行容器的时候加上 --tmpfs 选项就可以啦!
docker run -d --name mynginx1 -p 9999:80 --tmpfs /usr/share/nginx/html nginx:1.25.4

我们使用 docker inspect 看容器的 Mounts 信息,是空的!
在这里插入图片描述
但是里面有一个 Tmpfs 的字段可以看到挂载信息:
在这里插入图片描述

--mount 选项创建临时卷

  • 功能:完成目录映射。
  • 语法:
    --mount '<key>=<value>, <key>=<value>'
    
  • 参数:
    • type:存储卷的类型,bind 表示绑定数据卷,volume 表示存储卷,tmpfs 表示临时数据卷。
    • destinationdsttarget:文件或目录挂载在容器中的路径,不可以使用相对路径!!
    • tmpfs-size:tmpsfs 挂载的大小 (以字节为单位),默认无限制。
    • tmps-mode:tmpfs 的八进制文件模式。
  • 演示:
docker run -d --name mynginx1 -p 9999:80 --mount type=tmpfs,dst=/usr/share/nginx/html nginx:1.25.4

可以看到使用 --mount 选项创建的容器,还是能在 Mouts 字段中看到 tmpfs 的。
在这里插入图片描述


我们去看一下容器中目录的内容哈:可以看到里面啥也没有,说明 tmpfs 会覆盖容器目录原有的内容!!!
在这里插入图片描述


我们向 index.html 里面写点东西:用浏览器访问是没有任何问题的!

echo "hello tmpfs" > /usr/share/nginx/html/index.html

在这里插入图片描述
然后我们回到宿主机,重启这个容器,再次访问浏览器!可以看到原来写入到 index.html 文件的内容没了!说明 tmpfs 是内存级的文件,一旦容器重启数据就会丢失!

docker restart mynginx1

在这里插入图片描述






docker 卷的生命周期

如下图:我们创建一个管理卷,并使用 nginx 镜像启动一个容器,并且将 nginx 服务器的首页绑定到这个管理卷上。然后,我们将容器停止并删除。最后在宿主机上查看挂载点目录下的文件,发现文件并没有随着容器的消失而消失。
在这里插入图片描述

以上结论对绑定卷同样适用!


Docker 卷共享

如下图,我们创建一个绑定卷,指定目录为 /root/test_bind。然后使用 nginx 镜像运行多个容器,将这些容器中的 nginx 服务器的主页目录挂载到 root/test_bind 上!

# 第一个容器
docker run -d --name mynginx1 -p 9997:80 --mount type=bind,src=/root/test_bind,dst=/usr/share/nginx/html nginx:1.25.4
# 第二个容器
docker run -d --name mynginx2 -p 9998:80 --mount type=bind,src=/root/test_bind,dst=/usr/share/nginx/html nginx:1.25.4
# 第三个容器
docker run -d --name mynginx3 -p 9999:80 --mount type=bind,src=/root/test_bind,dst=/usr/share/nginx/html nginx:1.25.4

在这里插入图片描述
我们进入到宿主机的 /root/test_bind 目录下,在里面创建一个 index.html 的文件,然后再网上找一个页面源码,粘贴到 index.html 文件中!
在这里插入图片描述
在我们创建这个 index.html 文件之前,访问三个 nginx 服务器都是 403 forbidden。创建之后逐个刷新,可以看到每个 nginx 服务器的主页都发生了变化!这就是 Docker 卷共享啦!
在这里插入图片描述

文件消失了?

如下图:我们使用 busybox 镜像运行一个容器,进入容器之后,我们创建一个文件,退出容器。在宿主机上使用 find 命令查找这个文件!我们发现是能够在宿主机上找到这个文件的!
在这里插入图片描述
这是为什呢?docker 容器不是使用了 namespace 资源隔离和 cgroups 资源控制实现与宿主机的隔离了吗?为什么还能看到容器中的文件呢?

  • 在使用镜像创建容器时,实际上是在镜像的文件系统之上创建了一个可写层。这个可写层是容器的一部分,用于存储容器运行时产生的数据、文件变动以及新创建的文件等。当你在容器内创建新文件或者对现有文件进行修改时,这些操作实际上都是在容器的可写层上进行的,而镜像的文件系统则保持不变。
  • 当使用容器技术创建一个容器时,基础镜像中的文件系统是只读的,也就是说用户无法直接修改基础镜像中的文件。这样做的好处是可以确保基础镜像的完整性和稳定性,因为任何对基础镜像的修改都会被保存在容器的可写层中,而不会影响到基础镜像本身。容器技术通过使用只读的基础镜像和可写的容器层来实现文件的修改和添加,同时保证了基础镜像的稳定性和可重复性。
  • 镜像中的文件系统在宿主机上一般是不可见的。镜像是一个静态的文件,它包含了容器运行所需的文件系统结构和配置信息。这个文件系统在宿主机上实际上是以一种特殊的格式(比如 Docker 的aufs、overlayfs等)存储在宿主机的文件系统中的。当你运行一个容器时,容器引擎会将镜像中的文件系统加载到容器的文件系统命名空间中,这样容器就可以访问并使用这些文件了。但是,在宿主机上,你不能直接看到镜像中的文件系统,也无法直接对其进行操作。
  • 当创建一个容器时,实际上是在宿主机上创建了一个与宿主机系统隔离但可以共享部分资源的进程。容器的文件系统,包括可写层,通过一种叫做联合文件系统(Union File System)的技术,在宿主机的文件系统上进行了一种特殊的挂载。
    • 基础镜像的只读部分:容器启动时会加载一个基础镜像,这个基础镜像包含了容器所需的文件系统结构,但是这部分文件系统是只读的,宿主机不能对其进行修改。
    • 容器的可写层:在基础镜像之上,容器会有一个可写层,用于存储容器内的运行时数据,比如应用程序的日志、数据库的数据等。这个可写层是宿主机上的一个特殊目录,它通过联合文件系统技术与基础镜像的只读部分进行合并,形成了容器的完整文件系统。
    • 宿主机的文件系统:在宿主机上,容器的可写层实际上是以一种特殊的方式挂载到了宿主机的文件系统中。这种挂载使得宿主机可以看到容器的可写层,也可以对其进行读写操作。
  • 这种特殊的挂载就可以使用我们今天学的存储卷来实现。

现在我们使用 tmpfs 与容器中的特定目录 /app 绑定,然后在容器中的这个目录下创建一个文件,再次在宿主机上查找这个文件,来看看找不找得到哈!
在这里插入图片描述
由实验现象可以进一步证明 tmpfs 是内存级文件!并且可以看到 tmpfs 的隐私性很高呢!

什么时候用 volume,什么时候用 bind、tmpfs?

  • volume:volume 是 docker 的宿主机文件系统一部分,用于不需要规划具体目录的场景。
  • bindbind mount 完全是依赖于主机的目录结构和操作系统,用于目录需要提前规划,比如 mysql 的目录需要个空间大的,其他服务有不占用的时候,用 volume 就不太合适了。
  • tmpfs:用于敏感文件存储,文件不想存储的宿主机和容器的可写层之中。

存储卷在实际研发中带来了哪些问题?

  1. 跨主机使用:
    docker 存储卷是使用其所在的宿主机上的本地文件系统目录,也就是宿主机有一块磁盘,这块磁盘并没有共享给其他的 docker 主机,容器在这宿主机上停止或删除,是可以重新再创建的,但是不能调度到其他的主机上,这也是 docker 本身没有解决的问题,所以 docker 存储卷默认就是 docker 所在主机的本地。虽然自己搭建一个共享的 NFS 来存储 docker 存储的数据,也可以实现,但是这个过程强依赖于运维人员的能力。所以为了满足未来应用的存储和数据分离,越来越多的分布式存储方案出现,如 s3 系列,nfs 等。
  2. 启动参数未知:
    容器有一个问题,一般与进程的启动不太一样,就是容器启动时选项比较多,如果下次再启动时,很容器会忘记它启动时的选项,所以最好有一个文件来保存容器的启动,这就是容器编排工具的作用。一般情况下,是使用命令来启动操作 docker,但是可以通过文件来读,也就读文件来启动,读所需要的存储卷等,但是它也只是操作一个容器,如果要几十上百个容器操作,就需要专业的容器编排工具这种一般像开源的 k8s,各个云厂商也有自己的企业版编排软件。
  3. 复杂场景仍然需要运维:
    对于有状态要持久的集群化组件,如 MySQL 的主从。部署维护一个 MySQL 主从需要运维知识、经验整合进去才能实现所谓的部署,扩展或缩容,出现问题后修复,必须要了解集群的规模有多大,有多少个主节点,有多少个从节点,主节点上有多少个库,这些都要一清二楚,才能修复故障,这些就强依赖于运维经验这种复杂的场景往往还是需要人力,很难有完美的工具出现。

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

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

相关文章

接口压力测试 jmeter--增强篇(二)

前期准备 1. JMeter的插件的安装 下载Jmeter Plugins Manager对插件进行管理 &#xff08;1&#xff09;下载地址&#xff1a;https://jmeter-plugins.org/install/Install/ &#xff08;2&#xff09;下载后&#xff0c;将jar包放到jmeter包目录下/lib/ext目录下 &#xff0…

绝对隔离+底层限制,成就猎鹰蜜罐“牢不可破”的立体化安全

前言 自网络诞生以来&#xff0c;攻击威胁事件层出不穷&#xff0c;网络攻防对抗已成为信息时代背景下的无硝烟战争。然而&#xff0c;传统的网络防御技术如防火墙、入侵检测技术等都是一种敌暗我明的被动防御&#xff0c;难以有效应对攻击者随时随地发起的无处不在的攻击和威胁…

MySQL学习笔记3——条件查询和聚合函数

条件查询和聚合函数 一、条件查询语句二、聚合函数1、SUM&#xff08;&#xff09;2、AVG()、MAX()、MIN()3、COUNT&#xff08;&#xff09; 一、条件查询语句 WHERE 和 HAVING 的区别&#xff1a; WHERE是直接对表中的字段进行限定&#xff0c;来筛选结果&#xff1b;HAVIN…

BUG:vue表单验证校验不报错,必填都有信息,就是不能正常往下进行

vue表单验证未报错却出现异常 框架bug场景解决办法 框架 UI&#xff1a;element-UI 前端&#xff1a;vue2 bug场景 正常表单里面&#xff0c;有的信息要求必填或者加了一些限制&#xff0c;作为校验验证&#xff0c;只有走到校验才会执行其他行为&#xff0c;比如调用保存接…

在 Linux 终端中创建目录

目录 ⛳️推荐 前言 在 Linux 中创建一个新目录 创建多个新目录 创建多个嵌套的子目录 测试你的知识 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 前言 在本系列的这一部…

微服务之CircuitBreaker断路器

一、概述 1.1背景 在一个分布式系统中&#xff0c;每个服务都可能会调用其它的服务器&#xff0c;服务之间是相互调用相互依赖。假如微服务A调用微服务B和微服务C&#xff0c;微服务B和微服务C又调用其他的微服务。这就是构成所谓“扇出”。 如果扇出的链路上某个微服务的调…

【详细的Kylin使用心得】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

【任务调度】Apache DolphinScheduler快速入门

Apache DolphinScheduler基本概念 概念&#xff1a;分布式、去中心化、易扩展的可视化DAG工作流任务调度系统。 作用&#xff1a;解决数据处理流程中错综复杂的依赖关系&#xff0c;使调度系统在数据处理流程中开箱即用。Apache DolphinScheduler是一款开源的调度工具&#xff…

高仿小米商城用户端

高仿小米商城用户端(分为商城前端&#xff08;tongyimall-vue)和商城后端(tongyimall-api)两部分)&#xff0c;是Vue SpringBoot的前后端分离项目&#xff0c;用户端包括首页门户、商品分类、首页轮播、商品展示、商品推荐、购物车、地址管理、下订单、扫码支付等功能模块。 …

邮箱群组是什么?怎么创建邮箱群组?

在我们群发邮件时&#xff0c;可能会遇到这样的状况&#xff0c;一个个输入邮箱地址效率很低&#xff0c;而且很容易就漏发。而对于一个企业来说&#xff0c;如果出现这样的问题&#xff0c;很有可能会影响公司的业务进展和团队协作。这个时候我们就需要邮箱群组这个功能&#…

spring cloud介绍

Spring Cloud是一系列框架的集合&#xff0c;它旨在简化构建分布式系统的过程。基于Spring Boot的快速配置和管理&#xff0c;Spring Cloud为微服务架构提供了全面的基础设施支持。它包括但不限于以下组件&#xff1a; 1. **Spring Cloud Discovery** - 服务发现组件&#xff0…

MySQL行级锁——技术深度+1

引言 本文是对MySQL行级锁的学习&#xff0c;MySQL一直停留在会用的阶段&#xff0c;需要弄清楚锁和事务的原理并DEBUG查看。 PS:本文涉及到的表结构均可从https://github.com/WeiXiao-Hyy/blog中获取&#xff0c;欢迎Star&#xff01; MySQL行级锁 行级锁&#xff08;Row-…

并发学习28--多线程 Fork、Join线程池

概念 使用 import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;public class TC51 {public static void main(String[] args) {//递归到最小不可分解单元&#xff0c;再进行计算ForkJoinPool pool new ForkJoinPool(5);pool.invoke(new My…

短视频素材在哪下载?优质视频素材APP下载

在这个视频内容日益成为关键传播手段的时代&#xff0c;选择正确的视频素材可以极大地增强你的内容影响力。无论是制作广告、社交媒体内容还是电影制作&#xff0c;高质量的视频素材都是不可或缺的。以下是精心挑选的全球顶级视频素材网站列表&#xff0c;每个网站都能为你的视…

嵌入式4-18

做一个简单数据库终端操作系统 #include <myhead.h> int main(int argc, const char *argv[]) {int id;char name[16];float score;sqlite3 *pNULL;if(sqlite3_open("./my.db",&p)!SQLITE_OK){printf("sqlite3_open error\n");return -1;} …

QT Webengine开发过程报错qml: Render process exited with code 159 (killed)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、解决方法二、补充说明总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 基于QT的Webengine开发过程中&#xff0c;QT的官方示例…

C语言进阶课程学习记录-函数指针的阅读

C语言进阶课程学习记录-函数指针的阅读 5个标识符含义解析技巧 本文学习自狄泰软件学院 唐佐林老师的 C语言进阶课程&#xff0c;图片全部来源于课程PPT&#xff0c;仅用于个人学习记录 5个标识符含义解析 int (*p1) (int* , int (*f) ( int* ) );定义了指针p1,指向函数&#…

面试题:一个 URL 在浏览器被输入到页面展现的过程中发生了什么

文章目录 前言一、回答二、深入追问 前言 这是一段~ 经典的旋律 ~&#xff0c;不好意思串台了&#xff0c;哈哈&#xff0c;这是一个经典的面试题&#xff1a;一个URL从浏览器到页面的过程中发生了什么&#xff0c;那么今天就带大家九浅一深来研究一下 觉得不错的同学可以加我…

RocketMQ 02 功能大纲介绍

RocketMQ 02 主流的MQ有很多&#xff0c;比如ActiveMQ、RabbitMQ、RocketMQ、Kafka、ZeroMQ等。 之前阿里巴巴也是使用ActiveMQ&#xff0c;随着业务发展&#xff0c;ActiveMQ IO 模块出现瓶颈&#xff0c;后来阿里巴巴 通过一系列优化但是还是不能很好的解决&#xff0c;之后…

SAP SD学习笔记06 - 受注的据否,受注的理由,简易变更(一括处理)

上文讲了一括处理和Block&#xff08;冻结&#xff09;处理。 SAP SD学习笔记05 - SD中的一括处理&#xff08;集中处理&#xff09;&#xff0c;出荷和请求的冻结&#xff08;替代实现承认功能&#xff09;-CSDN博客 本章继续讲SAP的流程中一些常用的操作。 1&#xff0c;受注…