新闻详情

新闻详情

首页 / 资讯中心 / 详情

高可用Web集群部署实战:Nginx+Keepalived+Redis+MySQL主从

发布时间:2026/10/1 12:40:38来源:尧图网络
高可用Web集群部署实战:Nginx+Keepalived+Redis+MySQL主从
做高可用Web集群架构部署实验最忌讳的是把它当成搭积木——Nginx挂完、Tomcat挂一堆、数据库搞个主从就觉得自己高可用了。我早年就是这么干的结果故障演练一上来用户会话乱跳、数据库主从拉起半天、Keepalived脑裂导致两个VIP同时飘着场面极其混乱。后来我重新把整套实验拆开逐步搞清楚了负载均衡的状态检查、会话共享、数据库故障切换这三块核心才算是真正能睡个安稳觉。这篇博文就是一次完整的高可用Web集群部署实验复盘。实验目标是在任意一台应用节点、负载均衡节点、Redis主节点或MySQL主节点宕机时服务自动切换业务中断时间控制在几十秒内不需要任何人手动登录服务器去敲命令。整套方案基于Nginx Keepalived Spring Boot Redis MySQL主从没有用Kubernetes原因后面会讲。如果你在准备类似的集群方案或者正在给现有的单体Web应用做高可用改造这篇内容可以直接当参考。1. 实验目标与技术选型1.1 先想清楚这套集群要防什么高可用不是玄学拆开来看就是两件事一是当某台机器突然宕机流量能不能自动绕开故障节点二是关键依赖比如数据库和会话存储能不能在业务可接受的时间内完成切换。如果不把这两件事量化后面所有部署都是自娱自乐。我把本次实验的可用性目标定成两个硬性指标任意一台Web应用节点故障时已有的请求连接断开重试新的请求必须在10秒内由其他节点接管任意一个MySQL主库故障时VIP漂移加从库提升整个切换过程在30秒内完成业务端不感知。这里隐含了一个概念叫RTO也就是恢复时间目标。如果你的业务只能接受秒级中断那主从切换脚本必须写得足够快如果能接受分钟级架构可以简单很多。这个目标也决定了我要买几台机器、要不要上Keepalived、要不要给Redis配哨兵。还有一个容易忽略的点是RPO也就是最多容忍丢多少数据。MySQL主从复制有异步、半同步和全同步的区别异步复制在极端情况下可能丢一条事务半同步可以最大程度保证主库提交的数据不会丢但会带来额外延迟。我这次实验选择了半同步复制因为“高可用”不能只保证服务能恢复还要保证恢复后数据不能少太离谱。这个思路会在后面的数据库章节里展开。1.2 技术选型为什么是Nginx Spring Boot Redis MySQL选型永远是被需求推着走的。这次实验的场景是标准的Java Web业务后端是Spring Boot内嵌Tomcat数据库是MySQL会话需要跨节点共享。在这个前提下技术栈几乎没有什么悬念。负载均衡层我选了Nginx而不是HAProxy或LVS。原因很简单Nginx不仅能做四层和七层转发还能直接承载HTTP层面的健康检查、静态文件缓存、安全限制等能力一个组件同时解决多个问题。HAProxy在TCP层性能更猛但在这个实验里不需要那么夸张的吞吐量Nginx的手感也更贴近大多数人的日常。LVS则偏底层部署和调试门槛高对实验来说反而会消耗太多精力在网络细节上。应用层的集群方案我用了最朴素的“两台服务器跑同一个Spring Boot程序”没有直接上Kubernetes。做这个实验的核心目的是理解“高可用”本身的机制而不是被容器编排的复杂度带偏。Kubernetes确实能把应用副本调度、自动重启、滚动更新都包了但如果连VIP漂移、会话Redis化、数据库主从切换都还没亲手滚过一遍直接上容器编排只会让你对故障的感知越来越弱。会话保存选了Redis。说明一下Redis哨兵模式和集群模式是两个不同的维度哨兵解决的是“主节点挂了自动选新主”集群模式解决的是“单机内存不够需要分片扩展”。这次实验只需要前者所以部署一主一从加一个哨兵就够了如果后续数据量真的大到单节点装不下再考虑迁移到Redis Cluster。数据库高可用则用MySQL主从复制 Keepalived虚拟IP后面会重点讲为什么单靠主从复制还不够。2. 高可用核心原理负载均衡、会话保持与故障转移2.1 负载均衡健康检查让流量自动绕开“坏节点”负载均衡的基本动作是分发请求但真正体现高可用价值的是健康检查。Nginx的upstream默认用的是被动健康检查简单说就是当请求被转发到某台后端节点后如果连接失败、超时或者返回HTTP 500Nginx会把这个节点标记为失败在fail_timeout时间内不再给它发送新请求。这里很多人会写一个特别宽松的配置upstream web_pool { server 192.168.1.21:8080 max_fails2 fail_timeout10s; server 192.168.1.22:8080 max_fails2 fail_timeout10s; keepalive 32; }这个配置的意思是10秒内如果转发到后端失败2次就将该节点摘除10秒。看起来没什么问题但如果你把max_fails设成1、fail_timeout设成2秒那后端线程池一个轻微排队就可能被误判。反过来如果设成max_fails5、fail_timeout30s节点真要宕机了得等不少请求被拖到超时才能摘除用户已经明显感知到卡顿。所以健康检查参数不是随便填的要结合你后端接口的响应时间一起来定。Nginx默认的健康检查是“被动”的也就是说没有业务请求打过来它不会主动去探测节点状态。生产上很多团队会手动加一个/actuator/health端点再用主动健康检查模块每几秒请求一次。主动检查的好处是可以尽早发现故障但要注意检查端点本身不要依赖数据库和下游服务否则下游一抖动所有应用节点全部被判死流量全部打到别处反而崩得更快。2.2 会话保持别把用户会话绑死在某台机器上做Web集群时最经典的问题就是用户登录之后刷新一下页面又被负载均衡转到另一台机器然后提示“未登录”。出现这个问题的根本原因是Session默认保存在应用进程内存里节点之间彼此不认账。很多人第一反应是用Nginx的ip_hash让同一个IP的请求固定打到同一台节点。这个方法在小流量下确实能用但坏处非常明显一个办公室出口IP可能是同一个流量全压在一台机器上用户手机从WiFi切到4GIP变了还是会跳会话更重要的是如果固定那台节点宕机了流量切到另一台时Session照样不在用户还是会掉线。真正的解法有两个方向要么把Session序列化到Redis或者数据库中所有应用节点都从同一个共享存储里读要么干脆抛弃Session改用JWT之类的无状态Token。我在实验里选了前者因为改造最小Spring Boot的Session Redis化几乎只需要加依赖和配置。无状态化还有一个额外的好处当一台应用节点被摘掉再扩容一台新机器时新机器启动后不需要复制任何会话数据直接就能接手流量。配置上是这样引入spring-session-data-redis后YAML里把Session存储类型切到Redisspring: session: store-type: redis timeout: 1800s同时要让Cookie的路径和域名保持统一别因为域名变更导致Cookie下发失败。很多人在本地开发时Session正常一上负载均衡就丢多半是忘了在反向代理层透传Host或设置正确的Cookie路径。2.3 数据库高可用主从复制、自动切换与脑裂数据库是整个Web系统里最不能随便拍脑袋的部分。MySQL主从复制本身只能保证数据有副本它解决不了“主库下线后谁来顶替”的问题。show slave status里那个Slave_IO_Running: Yes和Slave_SQL_Running: Yes只能说明从库还在同步不能说明主库故障后你能自动切换。所以实验里给MySQL加了一层Keepalived用虚拟IP承载应用的数据库连接。正常情况下应用通过VIP访问主库主库宕机后VIP漂移到从库从库通过脚本把自己从只读模式切换成读写模式同时停止复制线程接管业务。这套机制的核心是虚拟路由冗余协议也就是VRRP。主节点会周期性地发送广播报文备节点如果持续收不到报文就认为主节点挂了立刻抢占VIP。但这里埋着一个高可用领域最经典的陷阱脑裂。如果网络发生分区Keepalived主备之间收发不到VRRP报文备节点会认为自己应该成为主节点于是把VIP抢过来此时原来的主节点可能还活着也在持有VIP。两个节点同时认为自己是主节点客户端请求就会一会儿通一会儿不通数据写入还可能两边同时发生造成数据错乱。处理脑裂没有一劳永逸的银弹核心手段是仲裁和隔离比如通过第三个节点做投票、或者故障切换时先强制把老主节点停机也就是STONITH。实验环境里更直接的预防措施是放通VRRP的组播报文或者干脆改用单播通信再配合健康检查脚本让曾经的主节点在nginx或mysqld异常时主动让出VIP。3. 动手部署从零搭建Web高可用集群3.1 环境准备与资源规划本次实验我用了6台虚拟机系统统一是CentOS 7.9或者Ubuntu 22.04都可以重点是保持内核和防火墙行为一致。下面是资源清单你可以根据自己手上的机器缩减合并但至少要有4台以上才能真正演示故障转移角色IP地址安装服务用途Nginx主节点192.168.1.11Nginx Keepalived承载VIP 192.168.1.100Nginx备节点192.168.1.12Nginx Keepalived主节点故障时接管VIP应用节点1192.168.1.21Spring Boot Tomcat运行Web应用应用节点2192.168.1.22Spring Boot Tomcat运行Web应用MySQL主节点192.168.1.41MySQL Keepalived承载数据库VIP 192.168.1.110MySQL从节点192.168.1.42MySQL Keepalived主库故障时提升为可写Redis主从192.168.1.31/32Redis Sentinel存储Session并自动选主如果你的机器不够Redis可以用1台先不接从节点但那样Redis挂掉之后整个集群无法恢复到高可用状态了通常不建议在实验中省这一步。网络规划上要预留两个VIPNginx层的VIP是192.168.1.100数据库层的VIP是192.168.1.110两者不要混用否则维护和排查时非常难受。3.2 应用无状态化改造与数据库连接配置我准备了一个最简单的Spring Boot Web应用只提供两个接口登录接口把用户信息写入Session测试接口返回当前Session内容和当前服务器实例ID。实例ID用启动参数注入方便验证负载均衡是否真的到了不同节点。改造思路很简单先把Session存储切换到Redis。依赖方面加入spring-boot-starter-data-redis和spring-session-data-redis然后在application.yml里配置Redis连接这里用的是哨兵模式不是普通单节点server: port: 8080 spring: application: name: web-cluster-app redis: sentinel: master: mymaster nodes: - 192.168.1.31:26379 - 192.168.1.32:26379 session: store-type: redis timeout: 1800s datasource: url: jdbc:mysql://192.168.1.110:3306/web_cluster?useSSLfalsecharacterEncodingutf8 username: webapp password: WebApp123 hikari: maximum-pool-size: 20 minimum-idle: 5 connection-timeout: 3000 validation-timeout: 3000 connection-test-query: SELECT 1数据库连接串里的IP必须是VIP不能写死某一台主库的IP否则Keepalived漂移就没有意义了。HikariCP里我特意打开了connection-test-query并设置较短的校验超时这样数据库VIP切换后旧的物理连接失效时连接池能尽快剔除坏连接重新建立指向新主库的连接。3.3 Nginx负载均衡配置在Nginx主备两台节点上配置保持完全一致。重点是upstream块和location里的反向代理参数。我用的核心配置如下upstream web_pool { server 192.168.1.21:8080 max_fails2 fail_timeout10s; server 192.168.1.22:8080 max_fails2 fail_timeout10s; keepalive 32; } server { listen 80; server_name demo.example.local; location / { proxy_pass http://web_pool; proxy_http_version 1.1; proxy_set_header Connection ; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_connect_timeout 3s; proxy_read_timeout 10s; proxy_next_upstream error timeout http_500 http_502 http_503; } }这里有两个容易被忽略的地方。第一是proxy_http_version 1.1加上清空Connection头是为了启用后端长连接不然每次请求都要重新和Tomcat建TCP连接性能损耗很明显。第二是proxy_next_upstream它决定了当后端返回错误或者超时时Nginx是否继续尝试下一台节点。如果这里不配http_500后端正好返回一个业务逻辑错误Nginx会直接把500响应给用户而不是自动切换后端高可用的体验就大打折扣了。验证负载均衡很简单访问http://192.168.1.100/test多刷新几次能看到返回的实例ID在21和22之间交替说明流量已经分摊到两台应用节点了。3.4 用Keepalived为Nginx做VIP漂移两台Nginx单凭VIP还不能叫高可用因为如果Nginx进程自身挂了VIP即使绑在机器上也没有意义所以必须在Keepalived里加健康检查脚本。脚本内容非常简单检测nginx master进程是否存在#!/bin/bash if [ -z $(pgrep -f nginx: master) ]; then exit 1 fi然后配置Keepalived主备主节点/etc/keepalived/keepalived.confvrrp_script chk_nginx { script /etc/keepalived/check_nginx.sh interval 2 weight -2 } vrrp_instance VI_WEB { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass Web123 } track_script { chk_nginx } virtual_ipaddress { 192.168.1.100/24 dev eth0 } }备节点几乎相同只需要把state改成BACKUPpriority改成90。注意VRRP的virtual_router_id必须一致否则两个节点之间无法建立主备协商。advert_int是广播间隔单位是秒一般保持1秒。如果把间隔设得太大故障探测时间就会变长可用性指标容易超标。配置完成后检查主节点上能看到VIPip addr show eth0然后手动停掉主节点的Keepalivedsystemctl stop keepalived几秒后在备节点上执行ip addr show eth0应该能看到VIP已经漂移过来了。这时候再用curl http://192.168.1.100/test服务依然正常返回说明Nginx层的故障转移已经生效。3.5 Redis哨兵部署与Spring Boot接入Redis部分我用了两节点一哨兵的最小高可用组合。第一步先把主从复制建起来修改主库redis.confbind 0.0.0.0 protected-mode no port 6379 daemonize yes dir /var/lib/redis从库除了上面的基础配置再加上一行replicaof 192.168.1.31 6379哨兵节点的配置单独放在/etc/redis/sentinel.confport 26379 daemonize yes sentinel monitor mymaster 192.168.1.31 6379 1 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 10000 sentinel parallel-syncs mymaster 1这里的quorum设成1是因为我这套只是实验环境只有一个哨兵节点。生产上哨兵至少要3个quorum设为2避免哨兵自己单点故障造成误判。down-after-milliseconds表示哨兵连续5秒联系不上主节点就判定主观下线然后根据quorum确定客观下线触发选主。启动哨兵后可以用redis-cli -p 26379 sentinel get-master-addr-by-name mymaster查看当前主节点地址。之后Spring Boot因为配置了哨兵模式的Redis连接会自动监听主节点变化当主节点切换后Lettuce驱动会自动向哨兵查询新主地址并重建连接应用侧不需要改任何配置。3.6 MySQL主从复制与Keepalived自动切换MySQL的部署是这套实验里最需要耐心的一步。首先在两台数据库服务器上安装并初始化MySQL然后修改主库配置[mysqld] server-id1 log-binmysql-bin binlog_formatROW gtid_modeON enforce-gtid-consistencyON从库配置除server-id2之外保持一致。然后创建复制账号CREATE USER repl192.168.1.% IDENTIFIED BY Repl123; GRANT REPLICATION SLAVE ON *.* TO repl192.168.1.%; FLUSH PRIVILEGES;在主库执行SHOW MASTER STATUS\G;记录Position在从库上执行CHANGE MASTER TO MASTER_HOST192.168.1.41, MASTER_USERrepl, MASTER_PASSWORDRepl123, MASTER_LOG_FILEmysql-bin.000001, MASTER_LOG_POS154, MASTER_AUTO_POSITION1; START SLAVE; SHOW SLAVE STATUS\G;看到Slave_IO_Running: Yes和Slave_SQL_Running: Yes主从复制就正常工作了。不过光有复制还不够我还在主库上启用了半同步复制插件INSTALL PLUGIN rpl_semi_sync_master SONAME semisync_master.so; INSTALL PLUGIN rpl_semi_sync_slave SONAME semisync_slave.so; SET GLOBAL rpl_semi_sync_master_enabled 1; SET GLOBAL rpl_semi_sync_slave_enabled 1;然后在两台数据库上配置Keepalived这次检测脚本要同时检查MySQL进程是否存活以及从库IO线程和SQL线程是否出错。从库的Keepalived需要配置notify_master脚本在切换为主库后执行以下逻辑先停止复制线程然后关闭read_only确保应用可以正常写入。#!/bin/bash mysql -uroot -pRoot123 -e STOP SLAVE; SET GLOBAL read_onlyOFF;这样当主库宕机时VIP 192.168.1.110漂移到从库从库立刻变成可写的新主库应用连接池通过短超时和探测SQL自动切到新物理连接上整个过程不需要重启应用。3.7 故障演练把关键节点一个个杀死部署完成不等于实验完成真正的重头戏是故障演练。我按顺序执行了下面四组测试每一组都在独立时间点进行避免多个故障同时发生时干扰判断。第一组杀应用节点。在192.168.1.21上执行kill -9杀掉Spring Boot进程然后从客户端持续请求VIP地址。刚开始会有个别请求超时或返回500但Nginx在失败两次后很快把节点从upstream摘除后续请求全部由192.168.1.22处理Session因为存储在Redis所以没有丢失。观察窗口大概需要10秒左右符合预期。第二组杀Nginx主节点。停掉192.168.1.11上的Keepalived进程VIP在几秒后漂移到192.168.1.12。由于两个Nginx配置一致客户端的TCP长连接会断一下但重新发起HTTP请求即可恢复对公网用户来说基本无感。第三组杀Redis主节点。redis-cli -p 6379 DEBUG sleep 30模拟主节点假死或者直接kill -9主节点进程。哨兵在down-after-milliseconds到期后触发选主从节点提升为新主。Spring Boot应用短暂的连接中断后自动恢复。这里要注意原本写入Redis的Session数据如果复制是异步的可能丢失最近几秒的Session但相比整个站点不可用这个代价是可以接受的。第四组杀MySQL主节点。这是最刺激也最容易翻车的一步。我停掉主库mysqld后Keepalived脚本检测到异常VIP漂移到从库notify_master脚本把从库设为可写。应用连接池的旧连接因为底层TCP断掉会在下一次获取连接时被清理新的连接指向新主库。我持续测试了插入数据的接口十几秒后恢复成功。四组故障演练全部通过后我还额外测试了同时杀掉Web应用节点和MySQL主节点这种复合故障。结果是Web层和数据库层各自独立恢复说明高可用组件之间没有互相耦合这也是分层架构带来的最大好处。4. 踩坑实录高可用实验最容易翻车的五个地方4.1 Keepalived脑裂VIP出现在两台机器上第一次搭Keepalived时我的主备两台Nginx之间没有放通VRRP组播。结果备节点一直收不到主节点的广播以为自己才是主把VIP抢了过来于是两台机器上都出现了192.168.1.100这个地址。客户端访问时有的请求到了主节点有的请求到了备节点负载均衡完全失控。排查方法很简单在任意一台疑似脑裂的机器上执行ip addr show eth0 | grep 192.168.1.100如果两台都能看到VIP基本就是脑裂。然后用tcpdump -i eth0 vrrp抓包观察VRRP报文是否正常通信。如果抓不到报文多半是防火墙或云安全组把协议拦了。解决方法是两层的第一放通VRRP组播或者直接在Keepalived里指定unicast_peer用单播通信避免组播在各种网络策略下失效第二健康检查脚本要足够灵敏节点上的服务一旦挂了立即降低自身优先级让出VIP减少脑裂窗口。记住脑裂不会因为你认真配置了就消失它只会在网络抖动时给你上一课。4.2 健康检查误判好好的节点被摘掉我在Nginx层做过一次乌龙操作把后端应用的健康检查URL指向了一个查询数据库的接口。这个接口平时响应很快但在一次数据库主从切换时主库短暂不可写导致接口查询超时Nginx连续两次判定应用节点失败把两台应用节点全部摘除。最后的结果是整个站点直接502而不是想象中的“数据库切换期间短暂不可用”。事后复盘健康检查必须区分“节点存活”和“业务健康”。正常情况下健康检查URL应该只检查应用进程是否能响应HTTP请求最多再检查一下本地磁盘、内存等基础资源绝对不要在下游服务抖动时也跟着抖动。如果确实需要检查下游依赖状态那就应该单独做一个只读的/actuator/health并把对数据库的依赖标记为“不参与就绪判定”或者加一个较长的超时。4.3 Redis哨兵切换后应用却连不上新主Spring Boot接入Redis哨兵之后我一度认为Lettuce驱动会自动搞定一切。有一次故障演练时Redis主库切换成功但应用日志里一直报连接老主节点地址失败原因是Lettuce的拓扑刷新策略在旧连接异常时没能及时触发。解决方法是检查Spring Boot版本较新版本里可以主动配置Lettuce的拓扑刷新器或者降低连接重试的粒度。更保守的方案是在Redis主从切换前把应用连接池里的空闲连接全部清掉但生产环境不可能每次切换前都人工干预。所以我在代码里安排了针对Redis Sentinel的自动重连逻辑配合超时配置保证在主从切换后的几秒内应用能从错误中恢复。还有一个常见坑spring.redis.sentinel.master写成了普通Redis的host导致永远找不到master这个字段应该填哨兵配置的master名字也就是sentinel monitor里的mymaster。4.4 MySQL半同步复制退化的真相半同步复制并不是高可用银弹。MySQL的半同步机制是主库提交事务后至少要等一台从库确认收到binlog才向客户端返回成功。但如果你把超时参数配得很大从库网络一旦抖动主库的写性能就会直线下降如果配得太小半同步会自动退化成异步此时主从复制就“看起来正常”实际上已经丢数据。我在实验中故意把从库网络加了一点损耗然后观察主库状态发现rpl_semi_sync_master_status变成了OFF对应的rpl_semi_sync_master_no_times也在上涨。这提醒我一个重要原则半同步能减少丢数据窗口但不能完全替代备份和监控。生产环境至少要同时开启binlog和定期全量备份并把主从延迟和半同步状态纳入监控告警否则高可用变成“高概率可用”。4.5 Web安全加固高可用不等于裸奔集群把Nginx暴露到公网之后我一开始只顾着做负载均衡和故障转移完全忽略了安全配置。后来发现日志里出现大量扫描器请求针对/admin、/.git和/actuator路径试探。这才意识到高可用只是基础Web安全同样要在实验阶段一起做。基础加固我总结了几个要点第一隐藏Nginx版本号和服务器软件信息修改server_tokens off第二用防火墙限制SSH管理端口只允许办公网访问第三Nginx层做URL访问控制禁止外部访问/actuator等敏感路径第四设置合理的client_max_body_size和proxy_read_timeout防止恶意大包打满后端第五如果有条件可以接入WAF规则对SQL注入和XSS请求做拦截。安全和高可用并不是两个独立模块漏掉任何一方线上都可能在半夜给你“惊喜”。做完整套高可用Web集群架构部署实验我个人最大的体会是高可用不是搭完就完事的静态结果而是一套需要反复验证的动态能力。我见过太多团队架构图上画得漂漂亮亮一遇到真实故障就露馅要么健康检查端口没有配置要么Keepalived脚本权限不对要么Redis哨兵没有自动重连。与其等线上故障教我们做人不如把每次演练当成一次正式事故把“杀掉节点后能不能切过去”变成日常习惯。另外从这套实验还可以继续扩展。如果你需要支持更复杂的微服务架构可以尝试把Nginx换成Kubernetes的Ingress把Spring Boot应用容器化后交给工作负载调度器来管理如果单台Redis已经扛不住再进一步从哨兵模式迁移到Redis集群模式。但无论架构怎么演进负载均衡、会话共享、数据库故障转移这“三板斧”的原理不会变在实验里亲手踩过一遍坑后面上任何平台都会踏实很多。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

行李箱缺陷检测数据集实战:VOC与YOLO双格式训练全流程 2026/10/1 13:24:17

行李箱缺陷检测数据集实战:VOC与YOLO双格式训练全流程

简介:本资源为行李箱缺陷检测数据集,面向从事目标检测算法训练与验证的开发者、学生及研究人员,可用于行李箱外观质量检测、缺陷识别等场景的模型训练与评估。压缩包共1952个文件,约25.11MB,包含650张jpg图片、650个xm…

阅读更多 →
PHP 8.1+ 中 mysqli--execute() 直接传参功能详解 2026/10/1 13:24:17

PHP 8.1+ 中 mysqli--execute() 直接传参功能详解

前言在 PHP 8.1 之前,用 mysqli 预处理语句(Prepared Statement)必须走两步:先 bind_param() 绑变量,再 execute() 执行。bind_param() 的第一个参数是类型字符串(如 sdi),它和后面的…

阅读更多 →
Coze二次开发实战:低代码边界、API鉴权与私有化部署 2026/10/1 13:24:17

Coze二次开发实战:低代码边界、API鉴权与私有化部署

1. 从零拆解 Coze 二次开发:低代码边界到底卡在哪 1.1 为什么会有“二次开发”这个需求 Coze 这类平台刚出来的时候,很多人第一反应是“拖拖拽拽就能搭个 Bot,还要开发干什么”。我一开始也这么想,直到真正把它放进企业场景里跑了…

阅读更多 →
基于OpenCV的银行卡识别系统:从卡面校正到Luhn校验全流程 2026/10/1 13:24:17

基于OpenCV的银行卡识别系统:从卡面校正到Luhn校验全流程

简介:这是一套面向计算机视觉初学者与金融科技方向学习者的银行卡识别实战项目,基于Python与OpenCV实现卡号等关键信息的自动提取,可用于课程设计、毕业设计或图像识别入门练手。资源包共43个文件,约10.31MB,包含10个p…

阅读更多 →
AI短剧渲染上云GPU:成本从15万降到8000元的实战拆解 2026/10/1 13:24:10

AI短剧渲染上云GPU:成本从15万降到8000元的实战拆解

做AI短剧渲染,最怕的不是技术跑不顺,而是算力账单先把利润吃掉。我最近用腾讯云GPU算力跑完一批AI短剧渲染,把单部秒剧的制作成本从15万元打到了8000元出头。这篇文章不聊虚的,直接把项目怎么设计、GPU怎么选、流水线怎么搭、账单…

阅读更多 →
百家号发布软件怎么选?从原理到实战的自动化发布指南 2026/10/1 13:24:10

百家号发布软件怎么选?从原理到实战的自动化发布指南

做内容的人应该都有过这种体验:一篇稿子在电脑前改了又改,定稿之后以为万事大吉,结果真正磨人的工作才刚开始——登录百家号后台,复制正文、逐段调整格式、上传封面、选分类、填标签、勾选原创声明,再预览一遍确认排版…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉