后端开发
未读Golang并发度控制在Golang中可以通过channel去控制goroutine的并发度
举个例子:
12345678910111213141516171819202122232425262728293031package mainimport ( "fmt" "sync" "time")func main() { var wg sync.WaitGroup concurrence := 2 semaphore := make(chan struct{}, concurrence) startTime := time.Now() for i := 0; i < 10; i++ { wg.Add(1) go func(i int) { defer wg.Done() // 抢占一个并发槽位 semaphore <- struct{}{} // 模拟任务执行 fmt.Printf("Task ...
后端开发
未读Redis缓存相关解决方案缓存穿透什么是缓存穿透?缓存穿透是指用户请求的数据在缓存中没有命中,同时在数据库也不存在,导致用户的每一次请求都要去数据库中查一遍,然后返回为空。
如果有恶意攻击者不断请求不存在的数据,会导致大量的请求落在数据库上,造成数据库压力过大,甚至击垮数据库。
解决方案
布隆过滤器
布隆过滤器专门用来检测集合中是否存在特定的元素。
布隆过滤器由一个长度为m比特的位数组(bit array)与k个哈希函数(hash function)组成的数据结构。位数组初始化均为0,所有的哈希函数都可以分别把输入数据尽量均匀地散列。
当要向布隆过滤器中插入一个元素时,该元素经过k个哈希函数计算产生k个哈希值,以哈希值作为位数组中的下标,将所有k个对应的比特值由0置为1。
当要查询一个元素时,同样将其经过哈希函数计算产生哈希值,然后检查对应的k个比特值:如果有任意一个比特为0,表明该元素一定不在集合中;如果所有比特均为1,表明该集合有可能性在集合中。为什么不是一定在集合中呢?因为不同的元素计算的哈希值有可能一样,会出现哈希碰撞,导致一个不存在的元素有可能对应的比特位为1,这就是所谓“ ...
固定窗口限流算法
Fixed Window Rate Limiting Algorithm固定窗口限流算法是在固定时间窗口(单位时间)内限制请求的数量。
将时间分成固定的窗口,并在每个窗口内限制请求的数量。
将请求按照时间顺序放入时间窗口,并计算该时间窗口内的请求数量,如果请求数量超出了限制,则拒绝该请求。
假设单位时间(固定时间窗口)是1秒,限流阀值为3。在单位时间1秒内,每来一个请求,计数器就加1,如果计数器累加的次数超过限流阀值3,后续的请求全部拒绝。等到1s结束后,计数器清0,重新开始计数。如下图:
优点: 固定窗口算法非常简单,易于实现和理解。
缺点: 存在明显的临界问题,比如: 假设限流阀值为3个请求,单位时间窗口是1s,如果我们在单位时间内的前0.9-1s和1-1.1s,分别并发3个请求。虽然都没有超过阀值,但是如果算0.9-1.1s,则并发数高达6,已经超过单位时间1s不超过3阀值的定义。
滑动窗口限流算法
滑动窗口限流算法是一种常用的限流算法,用于控制系统对外提供服务的速率,防止系统被过多的请求压垮。
它将单位时间周期分为n个小周期,分别记录每个小周期内接口的 ...
Wire实现Golang依赖注入一、什么是依赖注入简单来说,就是在项目开发中,我们经常遇到一直情况,实例A的创建会依赖于实例B的创建,并且在实例A的生命周期内,持有对实例B的访问权限。
二、为什么要使用依赖注入如果不适用依赖注入的话会有以下风险:
全局变量⼗分不安全,存在覆写的可能。
资源散落在各处,可能重复创建,浪费内存,后续维护能⼒极差。
提⾼循环依赖的⻛险。
全局变量的引⼊提⾼单元测试的成本
在使用依赖注入后,可以方便我们的代码进行维护。
三、Golang依赖注入目前来说我的解决方案是通过Google的Wire去实现Golang依赖注入
Wire对比与其他在运行阶段依靠反射实现依赖注入的方式来说,优势在于能在编译期实现依赖注入,如果依赖注⼊有问题,那么在代码⽣成时就会抛出异常,并不会拖到运⾏时暴露,更便于我们进行debug。
3.1 安装Wire1go install github.com/google/wire/cmd/wire@latest
3.2 代码实现123456789101112131415161718func initWebServer() *gin.Engi ...
后端开发
未读HashMap的底层实现JDK1.8 之前JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列。HashMap 通过 key 的 hashcode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突
所谓扰动函数指的就是 HashMap 的 hash 方法
使用 hash 方法也就是扰动函数是为了防止一些实现比较差的 hashCode() 方法 换句话说使用扰动函数之后可以减少碰撞
JDK 1.7 HashMap 的 hash 方法源码:
12345678static int hash(int h) { // This function ensures that hashCodes that differ only by // constant multiples at each bit posit ...
HashMap和常用集合类的区别HashMap 和 HashTable 的区别
线程是否安全: HashMap 是非线程安全的,HashTable 是线程安全的,因为 HashTable 内部的方法基本都经过synchronized 修饰。(如果要保证线程安全的话推荐使用 ConcurrentHashMap )
效率: 因为线程安全的问题,HashMap 要比 HashTable 效率高一点,HashTable 基本被淘汰,尽量不要在代码中使用它
对 Null key 和 Null value 的支持: HashMap 可以存储 null 的 key 和 value,但 null 作为键只能有一个,null 作为值可以有多个,HashTable 不允许有 null 键和 null 值,否则会抛出NullPointerException
初始容量大小和每次扩充容量大小的不同:
创建时如果不指定容量初始值,HashTable 默认的初始大小为 11,之后每次扩充,容量变为原来的 2n + 1,HashMap 默认的初始化大小为 16。之后每次扩充,容量变为原来的 2 倍
创建时如果给定了 ...
大数据常用集群脚本一、集群分发同步脚本1.1 在/bin目录下创建xsync文件1cd /bin && vim xsync
1.2 xsync集群分发同步Shell脚本12345678910111213141516171819202122232425262728#!/bin/bash#1. 判断参数个数if [ $# -lt 1 ]then echo Not Enough Arguement! exit;fi#2. 遍历集群所有机器for host in master slave1 slave2do echo ==================== $host ==================== #3. 遍历所有目录,挨个发送 for file in $@ do #4 判断文件是否存在 if [ -e $file ] then #5. 获取父目录 pdir=$(cd -P $(dirname $file); pwd) #6. 获取当前文件的名称 fname=$(basename $file ...
数仓分层数据仓库理论上一般分为三层
ODS 数据运营层
DW 数据仓库层
ADS 数据服务层
ODS 数据运营层OperationDataStore数据准备区,也称为贴源层。数据仓库源头系统的数据表通常会原封不动的存储一份,称为 ODS 层,是后续数据仓库加工数据的来源。ODS 层数据的来源方式:
业务库: 离线方面经常会使用 Sqoop 来抽取,例如每天定时抽取一次。实时方面可以考虑用 Canal 监听 MySQL 的 binlog,实时接入即可。
埋点日志: 日志一般以文件的形式保存,可以选择用 Flume 定时同步,可以用 SparkStreaming 或者 Flink 来实时接入
消息队列: 即来自 ActiveMQ、Kafka 的数据等。
DW 数据仓库层DW 数据仓库层,由下到上可以分为 DWD(数据明细层),DWM(数据中间层),DWS(数据服务层)。从 ODS 层中获得的数据将按照主题建立各种数据模型。这一层和维度建模会有比较深的联系。
DWD 细节数据层DWD: Data Warehouse Details 细节数据层,是业务层与数据仓库的隔离层。主要对 OD ...
后端开发
未读Java 多线程什么是并发和并行
并发:同一时刻多个指令在单个 CPU 上交替执行
并行:同一时刻多个指令在多个 CPU 上同时执行
线程实现方式Thread 实现通过将类继承 Thread 类,并重写 Run 方法
优点:实现简单,可以直接使用Thread 类中的方法
缺点:可扩展性差,不能继承其他的类
123456789101112131415161718class ExtendThread extends Thread { @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println(getName() + " : " + "ExtendThread-Thread"); } super.run(); }}private static void runExtendThread() { ...
什么是Arthas(阿尔萨斯)Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。
Arthas(阿尔萨斯)的用途
查找类加载jar包,类相关的Exception
反编译线上jar包,查找与本地代码不一致的地方
线上debug
全局视角查看系统的运行状况
监控JVM的实时运行状态
快速定位应用的热点,生成火焰图
直接从JVM内查找某个类的实例
安装Arthas
点击下载Arthas
解压后,在文件夹里有arthas-boot.jar,直接用java -jar的方式启动:1java -jar arthas-boot.jar
打印帮助信息:1java -jar arthas-boot.jar -h
Arthas基础入门启动 math-game 进行测试math-game是一个简单的程序,每隔一秒生成一个随机数,再执行质因数分解,并打印出分解结果。
mat ...