高精度计算模板的使用
高精度计算有几种常见的类型:
两个很大的整数相加A, B的位数均小于等于10⁶
两个很大的整数相减A, B的位数均小于等于10⁶
一个很大的整数乘以一个比较小的整数A的位数小于等于10⁶,B的数值小于等于10⁹
一个很大的整数除以一个比较小的整数A的位数小于等于10⁶,B的数值小于等于10⁹
还有 两个很大的整数相乘 和 两个很大的整数相除 这两种情况,不过不常用,暂时不学了。
我们写数字习惯从高位开始写,但是模拟加减乘除时由于要做进位的操作,所以从低位开始存比较方便。即:数组第 0 位存个位,第 1 位存十位,第 2 位存百位······
高精度加法C = A + B用变量 t 表示进位,要么是 1 要么是 0 。
123456789101112131415161718192021vector<int> add(vector<int> &A, vector<int> &B) { vector<int> C; // 和 int t = 0; // 1表示进位,0表示不进位 for ...
Redis 笔记(五):分布式缓存-分片集群
1 概述主从和哨兵可以解决 Redis 高可用、高并发读的问题。但是仍有两个问题没有解决:
海量数据存储
高并发写
使用分片集群可以解决上述问题,分片集群的特征是:
集群中有多个 master,每个 master 保存不同数据。
每个 master 都可以有多个 slave 节点
master 之间通过 ping 监测彼此健康状态
客户端请求可以访问集群任意节点,最终都会被转发到正确节点
2 hash slot (散列插槽)Redis 会把每一个 master 节点映射到 0~16383 共 16384 个插槽上
数据 key 不是与节点绑定,而是与插槽绑定。Redis 会根据 key 的有效部分计算插槽值,分两种情况:
key 中包含 “{}”,且 “{}” 中至少包含 1 个字符,”{}” 中的部分是有效部分
key 中不包含 “{}”,整个 key 都是有效部分
例如:key 是 num,那么就根据 num 计算,如果是 {hello}num,则根据 hello 计算。计算方式是利用 CRC16 算法得到一个 hash 值,然后对 16384 取余,得到的结果就是 s ...
Redis 笔记(四):分布式缓存-哨兵机制
1 哨兵的作用和原理哨兵,Sentinel,作用是实现主从集群的自动故障恢复。
哨兵的结构和作用
监控:Sentinel 会不断检查 master 和 slave 是否按预期工作
自动故障恢复:如果 master 故障,Sentinel 会将一个 slave 提升为 master。当故障实例恢复后也以新的 master 为主
通知:Sentinel 充当 Redis 客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给 Redis 的客户端
服务状态监控Sentinel 基于心跳机制监测服务状态,每隔 1 秒向集群的每个实例发送 ping 命令:
主观下线:如果 sentinel 节点发现某实例未在规定时间响应,则认为该实例主管下线。
客观下线:如果超过指定数量(quorum)的 sentinel 都认为该实例主观下线,则该实例客观下线,quorum 值最好超过 Sentinel 实例数量的一半。
选举新的 master一旦发现 master 故障,sentinel 需要在 slave 中选择一个作为新的 master,选择依据是这样的:
首先判断 slave 节点与 ...
JVM 笔记(一):JVM 简介 & 运行时数据区
JVM 简介Java 程序的运行环境(Java 二进制字节码的运行环境)
好处:
一次编写,到处运行
自动内存管理,垃圾回收功能
数组下标越界检查
多态的基石
运行时数据区1 PC Register(程序计数器)PC Register,Program Counter Register,程序计数器
Java 中代码的执行流程Java 代码首先被编译成字节码(JVM 指令),然后这些字节码交由 JVM 执行引擎的解释器进行解释。解释器将字节码转换为机器码,最终交由 CPU 执行。
程序计数器的作用负责记住下一条 JVM 指令的执行地址,从而保证程序执行的有序性
负责记录下一条 JVM 指令的执行地址,从而确保程序执行的有序性。
在多线程环境中,每个线程都有自己的程序计数器,记录该线程上次执行结束的位置。当线程被调度时,程序计数器指示从上次停止的位置继续执行。
程序计数器的实现程序计数器是通过“寄存器”实现的。寄存器是 CPU 中访问速度最快的存储单元,Java 将寄存器作为程序计数器来存储和读取指令的内存地址,因为指令的读取频率很高。
程序计数器的特点
线程私有
唯一一个不会存 ...
Redis 笔记(三):分布式缓存-主从集群
1 主从集群结构单节点 Redis 的并发能力是有上限的,要进一步提高 Redis 的并发能力就需要搭建主从集群,实现读写分离。
搭建流程(TODO:补充)
2 主从数据同步原理两个重要概念master 判断 slave(replica 同义) 是不是第一次同步数据的逻辑涉及到两个重要概念:
Replication Id:简称 replid,是数据集的标记,id 一致则说明是同一个数据集。每一个 master 都有唯一的 replid,slave 则会继承 master 节点的 replid。
offset:偏移量,随着记录在 repl_baklog 中的数据增多而逐渐增大。slave 完成同步时也会记录当前同步的 offset。如果 slave 的 offset < master 的 offset,则说明 slave 数据落后于 master,需要更新。(如果相等则说明当前是数据一致的。)
因此,slave 做数据同步时,必须向 master 声明自己的 replication id 和 offset,master 才可以判断到底需要同步哪些数据。
全量同步
全量同步的流 ...
Redis 笔记(二):分布式缓存-主从集群
1 RDB (数据快照)概念RDB(Redis Data Backup file) = Redis 数据备份文件 = Redis 数据快照
把内存中的所有数据都记录到磁盘中。Redis 实例故障重启后,从磁盘读取快照文件恢复数据。
.rdb 文件默认保存在当前运行目录。
save 命令 和 bgsave 命令
save:由 Redis 主进程来执行 RDB,会阻塞所有命令 完成后返回 “ok”
bgsave:开启子进程异步执行 RDB,避免主进程受到影响 会立刻返回 “background saving started”
配置Redis 会默认在服务停止时触发 RDB,但是也可以在 redis.conf 中配置,格式如下:
123456# 900 秒内如果至少有 1 个 key 被修改,就执行 bgsavesave 900 1save 300 10save 60 10000# save "" 表示禁用 RDB# save ""
其他常用配置:
12345678# 是否压缩,建议不开启,因为也会消耗 CPU,而磁盘相对很 ...
Redis 笔记(一):数据结构
1 Simple Dynamic String (简单动态字符串)因为 C 语言的字符串存在很多问题:
获取字符串长度需要遍历,效率低
非二进制安全(无法处理 ‘\0’ 等特殊字节)
不支持动态扩容
所以 Redis 没有直接使用 C 语言的字符串,而是构建了一种新的字符串结构:SDS(Simple Dynamic Strings),简单动态字符串
SDS 的结构SDS 本质上是一个结构体, char[] 由 SDS 自己来管理
根据字符串长度的不同,SDS 提供多种结构体实现来支持不同大小的字符串(如下图中为 sdsdr8),以节省内存空间
动态扩容——内存预分配当向 SDS 追加字符串超出当前容量时,会自动申请更大的内存:
新字符串长度 < 1MB:新容量 = 扩展后长度 x 2 + 1
新字符串长度 >= 1MB:新容量 = 扩展后长度 + 1MB + 1(每次固定增长 1MB,防止几何增长造成浪费)
结构就分为这两部分:
Header:记录当前字符串的长度等信息,便于读取
buf[]:真实存储字符串的 char[]
SD ...
RocketMQ 笔记(二):进阶知识
消息的特殊处理错乱的消息顺序消息有序指的是可以按照消息的发送顺序来消费(FIFO)。RocketMQ 可以严格地保证消息有序,可以分为分区有序或者全局有序。
顺序消费的原理解析:
在默认情况下,消息发送会采取 Round Robin 轮询方式把消息发送到不同的 queue(分区队列);而消费消息的时候从多个 queue 上拉取消息,这种情况发送和消费是不能保证顺序的。
但是如果控制发送的顺序消息只依次发送到同一个 queue 中,消费的时候只从这个 queue 上依次拉取,就能够保证顺序。
当所有消息都路由到同一个 queue 且被顺序消费时,称为全局有序;若消息被分散到多个 queue,但每个 queue 内部保持顺序,则称为分区有序(或局部有序)。
以订单业务为例,一个订单的顺序流程是:创建、付款、推送、完成。订单号相同的消息会被先后发送到同一个队列中,消费时,同一个 OrderId 获取到的肯定是同一个队列。
(TODO:画图)
顺序消息
订单步骤实体类
12345678910111213141516171819202122232425262728293031/** * 订单的 ...
RocketMQ 笔记(一):基础知识
https://rocketmq.apache.org/
为什么使用 MQ?-> MQ 的优势和劣势优势(作用):
应用解耦
异步提速
削峰填谷
劣势:
系统可用性降低
系统复杂度提高
异步消息机制
消息顺序性
消息丢失
消息一致性
消息重复使用
应用解耦:消费方存活与否不影响生产方系统的耦合性越高,容错性就越低,可维护性就越低。
主流 MQ 产品对比
ActiveMQ:Java 语言实现,万级数据吞吐量,处理速度 ms 级,主从架构,成熟度高
RabbitMQ:Erlang 语言实现,万级数据吞吐量,处理速度 us 级,主从架构
RocketMQ:Java 语言实现,十万级数据吞吐量,分布式架构,功能强大,扩展性强
Kafka:Scala 语言实现,十万级数据吞吐量,处理速度 ms 级,分布式架构,功能较少,应用于大数据较多
RocketMQ 架构图(TODO:画图)
环境搭建(略)消息发送(重点)主要内容
基于 Java 环境构建发送与消息接受基础程序
单生产者-单消费者
单生产者-多消费者
多生产者-多消费者
发送不同类型的消息
同步消息
异步消息
单向消 ...
记录 Docker 设置新源记录解决 Error response from daemon
问题用 Docker 拉取 MySQL 的时候报错:
docker: Error response from daemon: Get “https://registry-1.docker.io/v2/“: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers).
解决方式:编写配置文件(2024/10/17 目前可用)将可用的镜像仓库地址写入 daemon.json 配置文件(没有就新建)
vim /etc/docker/daemon.json写入:
123456789101112131415161718192021222324{ "registry-mirrors": [ "https://2a6bf1988cb6428c877f723ec7530dbc.mirror.swr.myhuaweicloud.com", "htt ...