当前位置: 首页 > news >正文

云原生之容器编排实践-ruoyi-cloud项目部署到K8S:MySQL8

背景

前面搭建好了 Kubernetes 集群与私有镜像仓库,终于要进入服务编排的实践环节了。本系列拿 ruoyi-cloud 项目进行练手,按照 MySQLNacosRedisNginxGatewayAuthSystem 的顺序来部署 ruoyi-cloud 微服务应用。

部署一个服务前,需要明确它是有状态服务还是无状态服务,这里 MySQLNacosRedisNginx 当做有状态服务(StatefulSet)来部署;而 GatewayAuthSystem 这些微服务作为无状态服务(Deployment)来部署。

这一次对全部服务采用 YAML 文件的方式来进行部署,这有助于理解K8S组织管理资源的风格,后续我们可以借助开源的容器平台,eg: KubeSphere 来进行可视化的服务部署。不过,手动编写 YAML 文件有一个问题,那就是当面对较多的微服务时,工作量较大,基本成了体力活;有个好消息是,我们可以使用 Kubernetes 官方提供的 kompose 工具,实现对 dokcer-composeyamlK8Syaml 的转换。

另外,为了保证后续在实际生产环境下各组件的稳定与可靠,我们限定了所有基础镜像的版本。

  • MySQL: 8.0
  • Nacos: 2.2.3
  • Redis: 7.2.3
  • Nginx: 1.25.3

虚机资源

共用到了三台虚机,1台作为 Master 节点,2台 Worker 节点。

主机名IP说明
k8s-master172.16.201.25主节点
k8s-node1172.16.201.26工作节点
k8s-node2172.16.201.27工作节点
[root@k8s-master ~]# kubectl get nodes
NAME         STATUS   ROLES                  AGE   VERSION
k8s-master   Ready    control-plane,master   37h   v1.20.9
k8s-node1    Ready    <none>                 35h   v1.20.9
k8s-node2    Ready    <none>                 35h   v1.20.9

系统环境

[root@k8s-master ~]# uname -a
Linux k8s-master 3.10.0-1160.71.1.el7.x86_64 #1 SMP Tue Jun 28 15:37:28 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
[root@k8s-master ~]# cat /proc/version 
Linux version 3.10.0-1160.71.1.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) ) #1 SMP Tue Jun 28 15:37:28 UTC 2022
[root@k8s-master ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)

YAML转换

ruoyi-cloud 项目本身提供了一个使用 docker-compose 部署的配置文件以及所有依赖服务镜像的构建脚本,是在项目根目录的 docker 目录下,可参考Docker容器化部署若依微服务ruoyi-cloud项目。

先将这个 docker 目录上传到 Kubernetes 的主节点,然后使用 komposedokcer-composeyaml 转换为 K8Syaml

curl -L https://github.com/kubernetes/kompose/releases/download/v1.26.0/kompose-linux-amd64 -o kompose
chmod +x kompose
mv ./kompose /usr/local/bin/kompose
[root@k8s-master docker]# cd /opt/docker
[root@k8s-master docker]# kompose convert

对于自动转换后的 YAML ,我们做简单的修改后即可应用部署。下面是 MySQLYAML 配置文件(做了合并和微调)。

  • ruoyi-mysql-ns-sc-pv-pvc.yaml
apiVersion: v1
kind: Namespace
metadata:name: ruoyi-basic---apiVersion: v1
kind: PersistentVolume
metadata:name: ruoyi-mysql-data-pvlabels:pv: ruoyi-mysql-data-pv
spec:capacity: storage: 5GiaccessModes:- ReadWriteOncepersistentVolumeReclaimPolicy: RetainstorageClassName: local-storagelocal:path: /data/mysql/datanodeAffinity:required:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- k8s-node1---apiVersion: v1
kind: PersistentVolume
metadata:name: ruoyi-mysql-log-pvlabels:pv: ruoyi-mysql-log-pv
spec:capacity: storage: 5GiaccessModes:- ReadWriteOncepersistentVolumeReclaimPolicy: RetainstorageClassName: local-storagelocal:path: /data/mysql/lognodeAffinity:required:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- k8s-node1
---apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: ruoyi-mysql-data-pvcnamespace: ruoyi-basic
spec:accessModes:- ReadWriteOnceresources:requests:storage: 10MistorageClassName: local-storageselector:matchLabels:pv: ruoyi-mysql-data-pv
---apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: ruoyi-mysql-log-pvcnamespace: ruoyi-basic
spec:accessModes:- ReadWriteOnceresources:requests:storage: 2GistorageClassName: local-storageselector:matchLabels:pv: ruoyi-mysql-log-pv---apiVersion: v1
kind: ConfigMap
metadata:name: ruoyi-mysql-configmapnamespace: ruoyi-basic
data:my-custom.cnf: |[mysqld]# handle error "this is incompatible with sql_mode=only_full_group_by"sql_mode=STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTIONsocket=/var/run/mysqld/mysqld.sock[client]socket=/var/run/mysqld/mysqld.sock

Note: 这里使用 local-storageStorageClass ,并使用本地磁盘的方式创建使用 PV ,实际建议使用 NFS

  • ruoyi-mysql-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:annotations:kompose.cmd: kompose convertkompose.version: 1.26.0 (40646f47)labels:io.kompose.service: ruoyi-mysqlname: ruoyi-mysqlnamespace: ruoyi-basic
spec:replicas: 1selector:matchLabels:io.kompose.service: ruoyi-mysqltemplate:metadata:annotations:kompose.cmd: kompose convertkompose.version: 1.26.0 (40646f47)labels:io.kompose.service: ruoyi-mysqlspec:containers:- args:- --innodb-buffer-pool-size=80M- --character-set-server=utf8mb4- --collation-server=utf8mb4_unicode_ci- --default-time-zone=+8:00- --lower-case-table-names=1env:- name: MYSQL_DATABASEvalue: ruoyi-cloud- name: MYSQL_ROOT_PASSWORDvalue: you-guessimage: mysql:8.0name: ruoyi-mysqlports:- containerPort: 3306volumeMounts:- mountPath: /var/lib/mysqlname: ruoyi-mysql-data-pvc- mountPath: /var/log/mysqlname: ruoyi-mysql-log-pvc- mountPath: /etc/mysql/conf.dname: ruoyi-mysql-configrestartPolicy: Alwaysvolumes:- name: ruoyi-mysql-data-pvcpersistentVolumeClaim:claimName: ruoyi-mysql-data-pvc- name: ruoyi-mysql-log-pvcpersistentVolumeClaim:claimName: ruoyi-mysql-log-pvc- name: ruoyi-mysql-configconfigMap:name: ruoyi-mysql-configmap
  • ruoyi-mysql-service.yaml
apiVersion: v1
kind: Service
metadata:annotations:kompose.cmd: kompose convertkompose.version: 1.26.0 (40646f47)labels:io.kompose.service: ruoyi-mysqlname: ruoyi-mysqlnamespace: ruoyi-basic
spec:ports:- name: "3306"port: 3306targetPort: 3306nodePort: 30306selector:io.kompose.service: ruoyi-mysqltype: NodePort

部署MySQL

Note: 本次部署 MySQL 时用了 Deployment (运行的pod名称会有个随机后缀),实际生产建议使用 StatefulSet (pod名称后缀为0)更合适。

# 创建NameSpace、StorageClass、PV、PVC
[root@k8s-master mysql]# kubectl apply -f ruoyi-mysql-ns-sc-pv-pvc.yaml
namespace/ruoyi-basic created
persistentvolume/ruoyi-mysql-data-pv created
persistentvolume/ruoyi-mysql-log-pv created
persistentvolumeclaim/ruoyi-mysql-data-pvc created
persistentvolumeclaim/ruoyi-mysql-log-pvc created
configmap/ruoyi-mysql-configmap created# 部署MySQL
[root@k8s-master mysql]# kubectl apply -f ruoyi-mysql-deployment.yaml
deployment.apps/ruoyi-mysql created# 创建MySQL服务
[root@k8s-master mysql]# kubectl apply -f ruoyi-mysql-service.yaml
service/ruoyi-mysql created# 查看PV信息
[root@k8s-master mysql]# kubectl get pv -owide
NAME                 CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                 STORAGECLASS    REASON   AGE     VOLUMEMODE
docker-registry-pv   5Gi        RWX            Retain           Bound    docker-registry/docker-registry-pvc   local-storage            26h     Filesystem
ruoyi-mysql-data-pv   5Gi        RWX            Retain           Bound    ruoyi-basic/ruoyi-mysql-data-pvc        local-storage            5m16s   Filesystem
ruoyi-mysql-log-pv    5Gi        RWX            Retain           Bound    ruoyi-basic/ruoyi-mysql-log-pvc         local-storage            5m16s   Filesystem# 获取配置信息
[root@k8s-master mysql]# kubectl get cm -n ruoyi-basic
NAME                   DATA   AGE
kube-root-ca.crt       1      17m
ruoyi-mysql-configmap   1      17m# 可通过以下命令查看编辑MySQL的配置
[root@k8s-master ~]# kubectl edit cm ruoyi-mysql-configmap -n ruoyi-basic# 查看MySQL日志
[root@k8s-master ~]# kubectl logs ruoyi-mysql-8c779d94c-b7r9n -n ruoyi-basic# 查看所有Pod,MySQL就绪
[root@k8s-master mysql]# kubectl get pod -A
NAMESPACE              NAME                                         READY   STATUS    RESTARTS   AGE
docker-registry        docker-registry-9bc898786-l477q              1/1     Running   1          17h
kube-system            calico-kube-controllers-577f77cb5c-hv29w     1/1     Running   2          3d22h
kube-system            calico-node-4fkrs                            1/1     Running   0          3d22h
kube-system            calico-node-d4tqq                            1/1     Running   2          3d22h
kube-system            calico-node-sdmm6                            1/1     Running   4          3d22h
kube-system            etcd-k8s-master                              1/1     Running   9          5d9h
kube-system            kube-apiserver-k8s-master                    1/1     Running   9          5d9h
kube-system            kube-controller-manager-k8s-master           1/1     Running   9          5d9h
kube-system            kube-proxy-4789z                             1/1     Running   0          5d9h
kube-system            kube-proxy-7mt7k                             1/1     Running   5          5d9h
kube-system            kube-proxy-lqtpz                             1/1     Running   2          5d9h
kube-system            kube-scheduler-k8s-master                    1/1     Running   10         5d9h
kubernetes-dashboard   dashboard-metrics-scraper-79c5968bdc-j9bnv   1/1     Running   0          3d22h
kubernetes-dashboard   kubernetes-dashboard-658485d5c7-pq7z8        1/1     Running   0          3d22h
ruoyi-basic             ruoyi-mysql-8c779d94c-b7r9n                   1/1     Running   0          4m3s# MySQL对外暴露了端口,用于测试
[root@k8s-master mysql]# kubectl get svc -n ruoyi-basic -o wide
NAME         TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE   SELECTOR
ruoyi-mysql   NodePort   10.96.58.67   <none>        3306:30306/TCP   4s    io.kompose.service=ruoyi-mysql

验证MySQL服务

  1. 可以直接进入容器,通过MySQL自带的命令行客户端进行测试连接:mysql -uroot -p
  2. 可以使用busybox,验证集群内部是否可以正常连接MySQL数据库。
  3. 由于暴露了服务端口30306,也可以通过远程的数据库客户端进行连接测试。
# 进入mysql的服务,测试客户端连接:mysql -uroot -p
kubectl exec -it pod/ruoyi-mysql-8c779d94c-b7r9n  -n ruoyi-basic -- /bin/bash# 使用Busybox进行数据库连接测试;以服务名的方式
[root@k8s-master ~]# kubectl exec -it pod/busybox -- /bin/sh
/ # telnet ruoyi-mysql.ruoyi-basic.svc.cluster.local:3306
J
8.0.27,'~_xJ{��C~;f<*,mqlcaching_sha2_password

远程测试 MySQL 服务状态:

2024-02-25-TelnetMySQL.jpg

导入数据

若依提供了微服务用到的数据库脚本,在 MySQL 服务部署完成后可以通过 SQL 文件自行导入脚本。

小总结

这次我们先是借助 kompose 工具,实现对 dokcer-composeyamlK8Syaml 的转换,经过简单的加工后即可应用部署;通过以上操作,成功将 MySQL 8.0 部署到了 K8S 集群,下一步我们安装下 Nacos v2.2.3


If you have any questions or any bugs are found, please feel free to contact me.

Your comments and suggestions are welcome!

相关文章:

云原生之容器编排实践-ruoyi-cloud项目部署到K8S:MySQL8

背景 前面搭建好了 Kubernetes 集群与私有镜像仓库&#xff0c;终于要进入服务编排的实践环节了。本系列拿 ruoyi-cloud 项目进行练手&#xff0c;按照 MySQL &#xff0c; Nacos &#xff0c; Redis &#xff0c; Nginx &#xff0c; Gateway &#xff0c; Auth &#xff0c;…...

go interface{} 和string的转换问题

1.遇到的问题 问题来源于,我sql模版拼接遇到的问题。 首先&#xff0c;这样是没有问题的。 var qhx interface{} "qhx"s : qhx.(string)fmt.Println(s) 但是当我在这段代码里用:1.类型断言 var sqlStr "select * from tx_user where username %s" join…...

【Git教程】(三)提交详解 —— add、commit、status、stach命令的说明,提交散列值与历史,多次提交及忽略 ~

Git教程 提交详解 1️⃣ 访问权限与时间戳2️⃣ add命令与 commit 命令3️⃣ 提交散列值4️⃣ 提交历史5️⃣ 一种特别的提交查看方法6️⃣ 同一项目的多部不同历史6.1 部分输出&#xff1a;-n6.2 格式化输出&#xff1a;--format、--oneline6.3 统计修改信息&#xff1a;--st…...

vue3个人网站电子宠物

预览 具体代码 Attack.gif Attacked.gif Static.gif Walk.gif Attack.gif Static.gif Attacked.gif Walk.gif <template><div class"pet-container" ref"petContainer"><p class"pet-msg">{{ pet.msg }}</p><img re…...

2.22 作业

顺序表 运行结果 fun.c #include "fun.h" seq_p create_seq_list() {seq_p L (seq_p)malloc(sizeof(seq_list));if(LNULL){printf("空间申请失败\n");return NULL;}L->len 0; bzero(L,sizeof(L->data)); return L; } int seq_empty(seq_p L) {i…...

office word保存pdf高质量设置

1 采用第三方pdf功能生成 分辨率越大质量越好...

微服务设计模式

微服务在过去十年中已经发展到现在非常成熟的水平。许多模式被演变以适应不同的需求。 架构模式 分层图案 2层三层n层客户端服务器 一个服务器和多个客户端大多数在线应用程序,例如电子邮件、银行应用程序等。分开演示 模型-视图-控制器 (MVC) 模型——包含核心功能和数据查看…...

10.网络游戏逆向分析与漏洞攻防-游戏网络架构逆向分析-接管游戏发送数据的操作

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;接管游戏连接服务器的操作 码云地址&#xff08;master 分支&#xff09;&#xff1a;染指/titan 码云版本号&#xff1a;00820853d5492fa7b6e32407d46b5f9c01930ec6 代码下载地址&#xff0c;在 ti…...

将SU模型导入ARCGIS,并获取高度信息,多面体转SHP文件(ARCMAP)

问题:将Sketchup中导出的su模型,导入arcgis并得到面shp文件,进而获取各建筑的高度、面积等信息。 思路: (1)导入arcgis得到多面体 (2)转为面shp文件 (3)计算高度/面积等 1、【3D Analyst工具】【转换】【由文件转出】【导入3D文件】(在此步骤之间,建议先建立一个…...

【电子通识】为什么单片机芯片上会有多组VDD电源?

在单片机芯片规格书中&#xff0c;我们经常能看到多个组VDD的设计&#xff0c;如下红框所示管脚都是VDD管脚。 为什么需要这样设计&#xff1f;只设置一个VDD管脚&#xff0c;把其他的VDD管脚让出来多做几个IO或是其他复用功能不好吗&#xff1f;接下来我们从单片机内部的电路结…...

跟我学C++中级篇——单实例和静态化

一、单实例模式 在设计模式中&#xff0c;单实例模式几乎是所有语言中都非常常用的一种设计模式。它在实际的应用中也非常广泛&#xff0c;在很多的开源框架中&#xff0c;都可以看到单实例的影子。单实例&#xff0c;简单的就可以看做在整个应用周期中&#xff0c;只有一个对…...

下载 axios.js 文件到本地【linux】

方式一 npm install axios在$NODE_PATH/node_modules/axios/dist路径下即可找到axios.js。 方式二 1、百度搜索 GitHub 官网&#xff1a;https://github.com/ 2、搜索 axios 3、点击 axios/axios 4、下载到本地 5、解压&#xff0c;进入到 dist 文件夹** 参考&#x…...

一些matlab的常用用法。在MATLAB中,如何实现数据的导入和导出?

一些matlab的常用用法。 MATLAB&#xff08;Matrix Laboratory&#xff09;是一款广泛使用的数值计算环境和编程语言&#xff0c;主要用于算法开发、数据可视化、数据分析以及数值计算等。以下是一些MATLAB的常用用法&#xff1a; 创建矩阵&#xff1a; 使用方括号 [] 创建矩阵…...

数学建模【插值与拟合】

一、插值与拟合简介 在数学建模过程中&#xff0c;通常要处理由试验、测量得到的大量数据或一些过于复杂而不便于计算的函数表达式&#xff0c;针对此情况&#xff0c;很自然的想法就是&#xff0c;构造一个简单的函数作为要考察数据或复杂函数的近似。插值和拟合就可以解决这…...

汽修专用产品---选型介绍 汽修示波器 汽车示波器 汽车电子 汽修波形 汽车传感器波形 汽车检测

为了满足汽车电子用户的测量需求&#xff0c;我司特推出汽修专用版示波器&#xff0c;一键测量&#xff0c;轻松找出汽车问题。 LOTO各种型号的示波器其实都可以用作汽车传感器信号波形的检测。汽修应用中&#xff0c;工程师对示波器的性能要求对于LOTO产品来说不算高。 在我们…...

如何将简历项目部署到自己的域名下

通过上一篇文章我们得知如何在Github上Fork项目到自己账号下&#xff0c;还有学会配置好简历项目并部署上线&#xff0c;接下来我们就来看一下该项目是如何部署到自己的域名下的 &#x1f447; 在项目文档中可以看到该简历项目是部署在Vercel上的&#xff0c;首先打开Vercel的官…...

Redisson - 实现Java的Redis分布式和可扩展解决方案

Redisson - 实现Java的Redis分布式和可扩展解决方案 引言&#xff1a; 在现代的分布式系统中&#xff0c;缓存和数据存储扮演着至关重要的角色。Redis作为一种高性能的键值存储数据库&#xff0c;被广泛用于缓存、消息队列、实时数据分析等场景。然而&#xff0c;原生的Redis…...

如何利用EXCEL批量插入图片

目录 1.excel打开目标表格&#xff1b; 2.点开视图-宏-录制宏&#xff0c;可以改宏的名字或者选择默认&#xff1b; 3.然后点开视图-宏-查看宏 4.点编辑进去 5.修改代码&#xff1a; &#xff08;1&#xff09;打开之后会显示有一堆代码 &#xff08;2&#xff09;将这个…...

django rest framework 学习笔记-实战商城3

01用户模块模型定义_哔哩哔哩_bilibili 本博客借鉴至大佬的视频学习笔记 用户模块及商品数据表结构设计 from ckeditor.fields import RichTextField # pip install django-ckeditor from django.db import models# Create your models here. # from wx.richtext import Ri…...

WPF真入门教程29--MVVM常用框架之MvvmLight

1、MVVM模式回顾 关于mvvm模式的基础知识&#xff0c;请看这2个文章&#xff1a; WPF真入门教程23--MVVM简单介绍 WPF真入门教程24--MVVM模式Command命令 做过VUE开发或微信小程序开发的伙伴&#xff0c;就知道MVVM模式&#xff0c;核心就是数据驱动控件&#xff0c;全栈开…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...

[USACO23FEB] Bakery S

题目描述 Bessie 开了一家面包店! 在她的面包店里&#xff0c;Bessie 有一个烤箱&#xff0c;可以在 t C t_C tC​ 的时间内生产一块饼干或在 t M t_M tM​ 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC​,tM​≤109)。由于空间…...

针对药品仓库的效期管理问题,如何利用WMS系统“破局”

案例&#xff1a; 某医药分销企业&#xff0c;主要经营各类药品的批发与零售。由于药品的特殊性&#xff0c;效期管理至关重要&#xff0c;但该企业一直面临效期问题的困扰。在未使用WMS系统之前&#xff0c;其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...