/usr/local/java8/bin/java -server -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djava.io.tmpdir=/tmp -Djava.net.preferIPv6Addresses=false -Djava.io.tmpdir=/tmp -Duser.timezone=GMT+08 -Xss512k -Xmx4096m -Xms4096m -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=512m -XX:+AlwaysPreTouch -XX:+HeapDumpOnOutOfMemoryError -XX:+UseG1GC -XX:G1HeapRegionSize=4M -XX:InitiatingHeapOccupancyPercent=40 -XX:MaxGCPauseMillis=100 -XX:+TieredCompilation -XX:CICompilerCount=4 -XX:-UseBiasedLocking -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintStringTableStatistics -XX:+PrintAdaptiveSizePolicy -XX:+PrintGCApplicationStoppedTime -XX:+PrintFlagsFinal -XX:-UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=10M -Xloggc:/var/gc.log.20230208 -XX:ErrorFile=/vmerr.log.20230208 -XX:HeapDumpPath=/var/heaperr.log.20230208 -Xbootclasspath/a:BOOT-INF/lib/hexo 1.2.3.jar -javaagent:BOOT-INF/lib/agent-1.2.3.jar -Dspring.profiles.active=prod -jar ./2.0.0-SNAPSHOT.jar
Rocketmq-nameserver数据一致性分析
NameServer保障数据一致性分析
简介
NameServer:名称服务,充当路由消息的提供者。生产者或消费者能够通过名字服务查找各主题相应的Broker IP列表。多个Namesrv实例组成集群,但相互独立,无状态,没有信息交换。
NameServer是一个非常简单的Topic路由注册中心,其角色类似Dubbo或者kafka中的zookeeper,Spring Cloud 中的 Eureka,NameServer支持Broker的动态注册与发现。主要包括两个功能:
Broker管理,NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活。
路由信息管理,每个NameServer将保存关于Broker集群的整个路由信息和用于客户端查询的队列信息。Producer在投递消息之前和Conumser在拉取消息之前,都会通过NameServer获取整个Broker集群的路由信息,从而进行消息的投递和消费。
设计考量
作为命名服务,有些组件会选用zk作为一致性存储的中间件,保障数据的强一致性。
但NameServer保障数据的最终一致性,以提升系统可用性,因此,RocketMQ自制的NameServer实现的是AP。
由此,RocketMQ的架构设计决定了只需要一个轻量级的元数据服务器就足够了,只需要保持最终一致,因此,RocketMQ决定使用自制的NameServer来实现简单的路由管理服务,将元数据存储在RocketMQ内部,设计很简单,非常的轻量级。NameServer 集群间互不通信,因此它们之间的注册信息可能会不一致,这是一种去中心化的架构,所有注册信息保存在内存中(无状态),一台NameServer挂了也没关系,从另一台NameServer上拉取数据即可。
如何做到nameserver不去做信息交换?
总体流程
启动NameServer,NameServer起来后监听端口,等待Broker、Producer、Consumer连上来,相当于一个路由控制中心。
Broker启动,跟所有的NameServer保持长连接,定时发送心跳包。心跳包中包含当前Broker信息(IP+端口等)以及存储所有Topic信息。注册成功后,NameServer集群中就有Topic跟Broker的映射关系。
收发消息前,先创建Topic,创建Topic时需要指定该Topic要存储在哪些Broker上,也可以在发送消息时自动创建Topic。
Producer发送消息,启动时先跟NameServer集群中的其中一台建立长连接,并从NameServer中获取当前发送的Topic存在哪些Broker上,轮询从队列列表中选择一个队列,然后与队列所在的Broker建立长连接从而向Broker发消息。
Consumer跟Producer类似,跟其中一台NameServer建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,开始消费消息。
MYSQL-MVCC的实现机制
什么是MVCC
MVCC,全称Multi-Version Concurrency Control,即多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存
我的一句话概括:提升数据库并发读的能力,不加锁的并发读
实现路径是通过undo log,记录当前事务的历史修改版本,并基于事务id顺序,实现snapshot读取
innodb 的可重复读是基于MVCC实现的
什么是当前读和快照读?
当前读
像select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁
快照读
像不加锁的select操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即MVCC,可以认为MVCC是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本,比如用于可重复读的场景
RC和RR 使用MVCC有啥不同
原因:对于 RR 、RC级别来说,其实整个过程几乎一样,唯一不同的是生成 ReadView 的时机,RR 级别只在事务开始时生成一次,之后一直使用该 ReadView。而 RC 级别则在每次 select 时,都会生成一个 ReadView。
所以RR永远保持同一个readview