版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1.前言 在前面的文章中, 《REDIS-CLUSTER集群创建内部细节详解》 萌叔创建一个Redis集群。 这篇文章,我会为集群添加2个节点,并介绍slot的迁移过程。 2.集群扩容 添加主节点127.0.0.1:7006 redis-cli –cluster add-node 127.0.0.1:7006 127.0.0.1:7000 添加从节点127.0.0.1:7007(并指定其Master节点) redis-cli –cluster add-node 127.0.0.1:7007 127.0.0.1:7000 –cluster-slave –cluster-master-id 86f3cb72813a2d07711b56b3143ff727911f4e1e 新添加的节点上并没有slot分布,需要通过命令让slot重新分布 root@BJ-02:~/cluster-test/7007# redis-cli –cluster reshard 127.0.0.1:7000 >>> Performing Cluster Check (using node 127.0.0.1:7000) S: 7eb7ceb4d886580c6d122e7fd92e436594cc105e 127.0.0.1:7000 slots: (0 slots) slave… 继续阅读 REDIS-CLUSTER集群slot迁移过程分析

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 本文基于go1.17.6 1.什么是协程? 协程,英文Coroutines,是一种基于线程之上,但又比线程更加轻量级的存在,这种由程序员自己写程序来管理的轻量级线程叫做『用户空间线程』, 具有对内核来说不可见的特性。 1.1 协程的特点 线程的切换由操作系统负责调度,协程由用户自己进行调度 线程的默认Stack大小是MB级别,而协程更轻量,接近KB级别。 在同一个线程上的多个协程,访问某些资源可以不需要锁 适用于被阻塞的,且需要大量并发的场景。 1.2 Golang的GMP模型 CPU驱动线程上的任务执行 线程由操作系统内核进行调度,Goroutine由Golang运行时(runtime)进行调度 P的 local runnable queue是无锁的,global runnable queue是有锁的 P的 local runnable queue长度限制为256 注意: M和P是绑定关系 M和G是绑定关系 P只是暂存G,他们之间不是绑定关系 E-R图 简化后的E-R图 注意: 后面为了书写简单直接将 local runnable queue表示为本地队列 global runnable queue表示为全局队列 延伸 timer的四叉堆和内存分配器使用的mcache也是每个P一个 Q:… 继续阅读 Golang协程调度

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 引言 因为使用golangci-lint时长有关于内存对齐的告警提示,所以做了一个小工具,可以查看struct中Field在内存中的对齐情况 传送门: vearne/mem-align 2. 使用 package main import ( “github.com/vearne/mem-align” ) type Car struct { flag bool age int32 F1 int8 age2 int32 age3 int16 F2 int64 F3 *int32 InnerStruct struct{ InnerByte byte //InnerStr string } F4 []byte Name… 继续阅读 打印struct中Field内存对齐的小工具

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1.简介 RocketMQ是一个分布式消息和流数据平台,具有低延迟、高性能、高可靠性、万亿级容量和灵活的可扩展性。RocketMQ是2012年阿里巴巴开源的第三代分布式消息中间件,2016年11月21日,阿里巴巴向Apache软件基金会捐赠了RocketMQ;第二年2月20日,Apache软件基金会宣布Apache RocketMQ成为顶级项目。 2.架构 正常情况,写和读都走Master,Master如果宕机,读可以走Slave 在 RocketMQ 4.5 版本之前,RocketMQ 只有 Master/Slave 一种部署方式,虽然这种模式可以提供一定的高可用性但也存在比较大的缺陷。为了实现新的高可用多副本架构,RockeMQ 最终选用了基于 Raft 协议的 commitlog 存储库 DLedger。 2.1 四种角色 2.1.1 NameServer 存储元数据 topic -> broker 无状态 接收来自broker的心跳 检查与borker的通讯是否过期 Topic路由信息 { “OrderTopicConf”: “”, “queueDatas”: [{ “brokerName”: “broker-3”, “readQueueNums”: 4, “writeQueueNums”: 4,… 继续阅读 rocketmq分享

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 前言 Dashboard是Grafana中非常重要的概念,每个Dashboard都是一个巨大的看板,在Dashboard上可以配置Panel(图表)。在Dashboard中有个特别的配置–Variables,Variables提供了用户和面板交互,可以动态刷新面板。 有些特殊的场景,需要有些小技巧,否则Variables仍然无法满足我们的要求。 1. Case 1 我要查看不同股票的日线图 1.1 Query SELECT trade_date AS “time”, close FROM daily_data where ts_code = “$ts_code” order by trade_date ts_code是股票的代码,显然如果只看股票代码,很难想起这个代码究竟对应的是哪一只股票。 最好的方式是如下图这样,在变量的下拉列表中,显示股票名称,但是在实际的Query中使用股票代码查询。 grafan支持这种玩法,称为text和value 1.2 变量配置 注意需要Grafana的版本在7.4.5 或以上 1.2.1 配置Query select concat(name, “#”, ts_code) from target; 这一步会查出形如下面的结果 中国平安#601318.SH 三一重工#600031.SH… 继续阅读 Grafana-Variable配置小技巧

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 2.3 连接池的变化情况 如果采用确定性算法来划分子集还需要考虑在有节点宕机或者Backend进行过滚动升级的情况下,引起的连接池中连接的变化情况。 这里先上结论,要保证连接池中的连接不大量的销毁和创建,Backend也需要绑定backendID,以确保对于每个Client选出的子集不发生重大的变化 绑定backendID确保调用Subset时,Backend在backends中的位置不发生变化。(绑定backendID可以利用分布式锁来实现) func Subset(backends []string, clientID, subsetSize int) 我们来看一个反例,假定某个Backend backend-10实例宕机,连接池的变化情况 subset/certainty4/verify.go 结果 所有连接数:2500, 重建的连接总数:1257, 百分比: 50.280000 % 因为一个实例宕机,整个集群的连接池中一半的连接都要重新销毁,重连一次,开销还是非常大的。大家都知道集群做滚动发布,持续时间可能长达数分钟。也就是在这数分钟内Client的连接池可能会频繁的发生销毁和创建,这不得不引起我们的重视。不过好在发布动作在服务运行的整个生命周期占比不大。 3. 效果 最后我们来看下,使用划分子集方案后,带来的实际效果 连接数大概下降了30% 常驻内存大概下降40% 协程数下降30% 令人惊喜的是,GC耗时也有了一定程度的下降 总结 使用划分子集的方案来限制连接池的大小确实有不俗的效果,但也要注意细节和风险点。河豚虽然美味,但也有可能有毒。 参考资料 用subsetting 限制连接池中的连接数量 load balancing datacenter/ 打赏我

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 引言 在萌叔的文章玩转consul(3)–大规模部署的性能开销定量分析 中,探讨了consul支持大规模集群可能出现性能瓶颈。引出可以通过拆分consul集群或者逻辑切分DC的方法,来降低consul的压力。本文将展开说明一下。 2. 解释 2.1 单个DC的情况 假设服务A依赖服务B(调用服务B), 服务A和服务B各有200个实例, 服务B注册到consul集群上, 服务A通过consul集群发现服务B。 如果服务B做滚动发布,考虑最坏的情况,每次发布一个实例, consul总共发出的通知数为 200 * 200 = 40,000 2.2 2个DC的情况 拆分成2个DC后,单个DC中,服务A和服务B各有100个实例,限制不允许跨DC调用。如果服务B做滚动发布,考虑最坏的情况,DC1和DC2同时发布,每次发布一个实例,consul总共发出的通知数为 100 * 100 + 100 * 100 = 20,000 3. 总结 当服务的规模很大时,即使拆分成2个DC,服务整体的高可用能力不会受到影响。对比2.1和2.2,consul集群的压力减少了一半。另外咱们之前提过,单个DC中consul集群(server)的规模不宜过大,否则会影响日志复制、还有选主的速度。拆分到2个DC后,原有的consul集群也被拆分成了2个集群,单个DC中consul集群的规模下降了,这样还给我们留出扩容的余地。 后记 2022年1月29日 用单元化的思想(见参考资料1、2)来解决注册中心压力大的问题与我文章中提到的,划分逻辑DC的思想不谋而合。 参考资料 1.单元化架构解决了什么问题 2.单元化介绍 请我喝瓶饮料

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 前言 读者们可能使用过 fullstorydev/grpcurl 来对grpc服务进行调用调试。 假定有一个简单的grpc的服务 main.go package main import ( “context” “log” “net” “google.golang.org/grpc” pb “google.golang.org/grpc/examples/helloworld/helloworld” “google.golang.org/grpc/reflection” ) const ( port = “:50051” ) // server is used to implement helloworld.GreeterServer. type server struct { pb.UnimplementedGreeterServer } // SayHello implements… 继续阅读 grpc的反射机制

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 引言 假如你正在使用go mod管理某个项目的代码库依赖 case1: 某个项目的tag是超过v1版本的,你该怎么定义module case2: 某个项目要同时进行2个版本的开发,v2和v3 你该怎么定义module 2. 问题 为了验证效果,萌叔创建了项目 vearne/mod-multi-version 这个代码库只有一个文件 package mmv import “fmt” const Versoin = “v1.0.0” func PrintVersion(){ fmt.Println(“version:”, Versoin) } 其它项目使用vearne/mod-multi-version package main import ( “github.com/vearne/mod-multi-version” ) func main() { mmv.PrintVersion() } 代码库的tag列表中包含以下tag v1.0.0… 继续阅读 一个关于go module的有趣话题

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 引言 kt-connect是阿里开源的k8s的调试工具,它的作用类似于VPN,能够打通k8s集群和本地的网络。 传送门: alibaba/kt-connect 它有3种模式 * Connect 本地网络直接访问k8s集群网络 * Exchange 转发集群流量到本地 * Service Mesh 支持 另外它提供了一个Dashboard可以查看k8s集群内的所有可访问的service资源以及正在进行调试的Connect和Exchange数量, 用处不大。 2. 使用介绍 这里萌叔只简单介绍Connect和Exchange2种模式,更详细的使用说明见参考资料1 2.1 Connect模式 sudo ktctl -i ik8share/kt-connect-shadow:stable connect 注意: kt-connect 依赖sshuttle, 且运行时必须拥有root权限。另外sshuttle 又依赖了iptables(linux操作系统), ptctl(macOS) -i 参数指定镜像的地址 这里ik8share/kt-connect-shadow:stable是镜像的名字,阿里默认提供的镜像地址rdc-incubator/kt-connect-shadow在萌叔的测试k8s集群中无法正常拉取。这里提供了一个docker hub的镜像地址。 2.2 Exchange模式 sudo… 继续阅读 聊聊k8s调试工具kt-connect的实现