Spiga

2025年8月的文章归档

分布式架构之管理设计

2025-08-30 20:38:31

摘要:一、分布式锁 我们知道,在多线程情况下访问一些共享资源需要加锁,不然就会出现数据被写乱的问题。在分布式系统下,这样的问题也是一样的。只不过,我们需要一个分布式的锁服务。 分布式的锁服务需要有以下几个特点。 安全性(Safety):在任意时刻,只有一个客户端可以获得锁(排他性)。 避免死锁:客户端最终一定可以获得锁,即使锁住某个资源的客户端在释放锁之前崩溃或者网络不可达。 容错性:只要锁服务集群中的大部分节点存活,Client 就可以进行加锁解锁操作。 1. Redis 的分布式锁服务 我们通过以下命令对资源加锁。 SET resource_name my_random_value NX PX 30000 解释一下: SET NX 命令只会在 key 不存在的时候给 key 赋值,PX 命令通知 Redis 保存这个 key 30000ms。 my_random_value 必须是全局唯一的值。这个随机数在释放锁时保证释放锁操作的安全性。 PX 操作后面的参数代表的是这个 key 的存活时间,称作锁过期时间。 当资源被锁定超过这个时间时,锁将自动释放。 获得锁的客户端如果没有在这个时间窗口内完成操作,就可能会有其他客户端获得锁,引起争用问题。 通过下面的脚本为申请成功的锁解锁: if redis.call(get,KEYS[1]) == ARGV[1] then return redis.call(del,KEYS[1]) else return 0 end 如果 key 对应的 value 一致,则删除这个 key。通过这个方式释放锁是为了避免 Client 释放了其他 Client 申请的锁。 2. 分布式锁服务的一个问题 虽然 Redis 文档里说他们的分布式锁是没有问题的,但其实还是很有问题的。尤其是上面那个为了避免 Client 端把锁占住不释放,然后,Redis 在超时后把其释放掉,这事儿听起来就有点不靠谱。 我们来脑补一下,不难发现下面这个案例。 1. 如果 Client A 先取得了锁。 2. Client B 在等待 Client A 的工作完成。 3. 这个时候,如果 Client A 被挂在了某些事上,比如一个外部的阻塞调用,或是 CPU 被别的进程吃满,或是不巧碰上了 Full GC,导致 Client …… 阅读全文

分布式架构之弹力设计

2025-08-24 23:12:10

摘要:对于分布式系统的容错设计,在英文中又叫 Resiliency(弹力)。意思是,系统在不健康、不顺,甚至出错的情况下有能力 hold 得住,挺得住,还有能在这种逆境下力挽狂澜的能力。其中着眼于分布式系统的各种“容忍”能力,包括服务隔离、异步调用、请求幂等性、可伸缩性(有 / 无状态的服务)、一致性(补偿事务、重试)、应对大流量的能力(熔断、降级)。可以看到,在确保系统正确性的前提下,系统的可用性是弹力设计保障的重点。 我们很难计算我们设计的系统有多少的可用性,因为影响一个系统的因素实在是太多了,除了软件设计,还有硬件,还有第三方服务(如电信联通的宽带 SLA),当然包括“建筑施工队的挖掘机”,宕机原因主要有以下这些: 网络问题。网络链接出现问题,网络带宽出现拥塞…… 性能问题。数据库慢 SQL、Java Full GC、硬盘 IO 过大、CPU 飙高、内存不足…… 安全问题。被网络攻击,如 DDoS 等。 运维问题。系统总是在被更新和修改,架构也在不断地被调整,监控问题…… 管理问题。没有梳理出关键服务以及服务的依赖关系,运行信息没有和控制系统同步…… 硬件问题。硬盘损坏、网卡出问题、交换机出问题、机房掉电、挖掘机问题…… 一个分布式系统的故障是非常复杂的,因为故障是分布式的、多米诺骨牌式的。所以,要充分地意识到下面两个事。 故障是正常的,而且是常见的。 故障是不可预测突发的,而且相当难缠。 这就是为什么我们把这个设计叫做弹力(Resiliency)。 一方面,在好的情况下,这个事对于我们的用户和内部运维来说是完全透明的,系统自动修复不需要人的干预。 另一方面,如果修复不了,系统能够做自我保护,而不让事态变糟糕。 一、隔离设计 隔离设计对应的单词是 Bulkheads,中文翻译为隔板,这个概念来自于船舱里防漏水的隔板。我们的软件设计当然也“漏水”,所以为了不让“故障”蔓延开来,需要使用“隔板”技术,来将架构分隔成多个“船舱”来隔离故障。 1. 按服务的种类来做分离 上图中,我们将系统分成了用户、商品、社区三个板块。这三个块分别使用不同的域名、服务器和数据库,做到从接入层到应用层再到数据层三层完全隔离。这样一来,在物理上来说,一个板块的故障就不会影响到另一板块。 上面这种架构虽然在系统隔离上做得比较好,但是也存在以下一些问题。 如果我们需要同时获得多…… 阅读全文

分布式架构之本质

2025-08-23 21:03:23

摘要:我们一直在谈论各式各样的架构,如高并发架构、异地多活架构、容器化架构、微服务架构、高可用架构、弹性化架构等。还有和这些架构相关的管理型的技术方法,如 DevOps、应用监控、自动化运维、SOA 服务治理、去 IOE 等。面对这么多纷乱的技术,很多团队或是公司都是一个一个地去做这些技术,非常辛苦,也非常累。 接下来我们来谈一谈分布式架构。 一、概述 1. 分布式的优缺点 首先,为什么需要分布式系统,而不是传统的单体架构。 增大系统容量。我们的业务量越来越大,而要能应对越来越大的业务量,一台机器的性能已经无法满足了,我们需要多台机器才能应对大规模的应用场景。所以,我们需要垂直或是水平拆分业务系统,让其变成一个分布式的架构。 加强系统可用。我们的业务越来越关键,需要提高整个系统架构的可用性,这就意味着架构中不能存在单点故障。这样,整个系统不会因为一台机器出故障而导致整体不可用。所以,需要通过分布式架构来冗余系统以消除单点故障,从而提高系统的可用性。 当然,分布式系统还有一些优势,比如: 因为模块化,所以系统模块重用度更高; 因为软件服务模块被拆分,开发和发布速度可以并行而变得更快; 系统扩展性更高;团队协作流程也会得到改善; …… 不过,这个世界上不存在完美的技术方案,采用任何技术方案都是“按下葫芦浮起瓢”,都是有得有失,都是一种 trade-off。也就是说,分布式系统在解决上述问题的同时,也给我们带来了其他的问题。因此,我们需要清楚地知道分布式系统所带来的问题。 从上面的表格我们可以看到,分布式系统虽然有一些优势,但也存在一些问题。 架构设计变得复杂(尤其是其中的分布式事务)。 部署单个服务会比较快,但是如果一次部署需要多个服务,流程会变得复杂。 系统的吞吐量会变大,但是响应时间会变长。 运维复杂度会因为服务变多而变得很复杂。 架构复杂导致学习曲线变大。 测试和查错的复杂度增大。 技术多元化,这会带来维护和运维的复杂度。 管理分布式系统中的服务和调度变得困难和复杂。 2. 面向服务的架构有以下三个阶段 下面是一个 SOA 架构的演化图。 我们可以看到,面向服务的架构有以下三个阶段。 20 世纪 90 年代前,是单体架构,软件模块高度耦合。当然,这张图同样也说明了有的 SOA 架构其实和单体架构没什么两样,因为都是高度耦合在一起的。就像图中的齿轮一…… 阅读全文

DecoratR优雅的装饰器模式实现库

2025-08-17 22:54:34

摘要:.Net生态有一个大名鼎鼎中介者模式实现库MediatR,今天介绍一个优雅的装饰器模式实现库DecoratR。 作为软件工程师,我们不断面临在应用程序中实现横切关注点的挑战,例如日志记录、缓存、验证、重试逻辑和安全性。传统方法通常会导致: 重复的样板代码散布在你的服务中。 业务逻辑与基础设施关注点之间紧密耦合。 由于职责混合而导致测试困难。 当需求变更时,可维护性差。 考虑这个典型的服务方法: public async TaskOrder GetOrderAsync(int orderId) { _logger.LogInformation(Getting order {OrderId}, orderId); // 正在获取订单 {OrderId} // 先检查缓存 var cacheKey = $order_{orderId}; if (_cache.TryGetValue(cacheKey, out Order cachedOrder)) { _logger.LogInformation(Order {OrderId} found in cache, orderId); // 订单 {OrderId} 在缓存中找到 return cachedOrder; } try { // 验证输入 if (orderId = 0) thrownew ArgumentException(Invalid order ID); // 无效的订单 ID // 业务逻辑埋没在基础设施代码中 var order = await _repository.GetOrderAsync(orderId); // 缓存结果 _cache.Set(cacheKey, order, TimeSpan.FromMinutes(5)); _logger.LogInformation(Order {OrderId} retrieved successfully, orderId); // 订单 {OrderId} 成功获取 return order;…… 阅读全文

Docker Swarm部署2

2025-08-10 10:55:01

摘要:一、安装Harbor 1. Harbor介绍 Harbor是由VMWare在Docker Registry的基础之上进行了二次封装,加进去了很多额外程序,而且提供了一个非常漂亮的web界面。 Project Harbor是一个开源的受信任的云本地注册表项目,用于存储、标记和扫描上下文。 Harbor扩展了开源Docker发行版,增加了用户通常需要的功能,如安全、身份和管理。 Harbor支持高级特性,如用户管理、访问控制、活动监视和实例之间的复制。 2. 功能 多租户内容签名和验证 安全性与漏洞分析 审计日志记录 身份集成和基于角色的访问控制 实例间的镜像复制 可扩展的API和图形UI 国际化(目前为英文和中文) 3. docker compose Harbor在物理机上部署是非常难的,而为了简化Harbor的应用,Harbor官方直接把Harbor做成了在容器中运行的应用,而且这个容器在Harbor中依赖类似redis、mysql、pgsql等很多存储系统,所以它需要编排很多容器协同起来工作,因此VMWare Harbor在部署和使用时,需要借助于Docker的单机编排工具(Docker compose)来实现。 Compose是一个用于定义和运行多容器Docker应用程序的工具。使用Compose,我们可以使用YAML文件来配置应用程序的服务。然后,只需要一个命令,就可以从配置中创建并启动所有服务。 4. 部署 需要提前安装好docker 提前下载好安装包:Release v2.13.2 · goharbor/harbor · GitHub 安装docker-compose DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} mkdir -p $DOCKER_CONFIG/cli-plugins curl -SL https://github.com/docker/compose/releases/download/v2.39.1/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose docker comp…… 阅读全文

Docker Swarm集群1

2025-08-09 10:45:35

摘要:最近公司有个.net项目需要集群部署,由于不打算使用K8S,计划用docker swarm来搭建整个集群环境。 所以计划用2篇文章,记录一下docker swarm部署的整个过程。 文章使用的环境是本地虚拟机环境,生产环境大同小异。 文中用的到资料下载:docker-swarm.zip 一、安装 Docker 对于 Ubuntu/Debian 系统: # 查看 ip ip a 使用工具测试链接,如putty # 1. 更新软件包索引 sudo apt-get update # 2. 安装依赖包 sudo apt-get install ca-certificates curl gnupg lsb-release # 3. 添加 Docker 官方 GPG 密钥 sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # 4. 设置稳定版仓库 echo deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 5. 安装 Docker 引擎 sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin # 检查 Docker 版本 docker --version 对于 CentOS/RHEL 系统: # 安装依赖包 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 # 添加 Docker 仓库 sudo yum-config-manager --add-r…… 阅读全文