雪花算法

1. 历史 snowflake是由 twitter 开源的分布式 id 生成算法,采 用 Scala 语言实现,是把一个 64 位的 long 型的 id,1 个 bit 是不用的,用其中的 41 bits 作为毫秒数,用 10 bits 作为工作机器 id,12 bits 作为序列号。 小插曲:世界上没有两片相同的雪花,所以使用雪花来表示唯一 2. 算法内容 1:第一位不使用:为什么这里第一位不使用,因为对于long类型,如果第一位是1 则说明是负数 2~42:表示时间戳,最多可以表示2^41-1次方的数值,可以是毫秒级。 43~52:表示工作机器ID,最多支持2^10机器,也就是1024的机器。可以自己定义前几位为机房ID。 53~64:表示自增ID,同一毫秒如果超过2^12次方的增长量,应该算非常大的了 3. 代码实现 public class SnowFlake { private final long workerId; private final long datacenterId; private long sequence; public SnowFlake(long workerId, long datacenterId, long sequence) { // sanity check for workerId // 这儿不就检查了一下,要求就是你传递进来的机房id和机器id不能超过32,不能小于0 // 这个是二进制运算,就是 5 bit最多只能有31个数字,也就是说机器id最多只能是32以内 // 这个是一个意思,就是 5 bit最多只能有31个数字,机房id最多只能是32以内 long maxWorkerId = ~(-1L << workerIdBits); if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException( String....

June 29, 2022

图片服务整体架构

1.背景 面向海外用户设计图片类app的后端架构。 2. 目标 考虑跨地区访问图片列表。 图片容灾和备份服务。 用户访问突增的解决方案。 海外服务政策相关注意事项。 3. 方案(图片) ps:这里先统一考虑图片的设计过程,图片解决后,再考虑业务后台过程 3.1 自研 方案设计 分布式文件系统:采用开源系统进行搭建分布式文件系统 文件系统服务:可以新增图片时可以生成索引返回给业务,当业务只需要根据索引,就能查询到对应的文件内容 业务层:上传服务主要负责图片的上传、而列表服务则是需要根据请求,获取列表及数据 接入层:接收用户的请求,把请求代理到业务上 这么设计,可以实现一个图片类的应用。在实际中会有什么问题? 不同区域的用户,体验不一样,用户离部署的节点越近,用户体验更好 因为根据之前的经验,地域对于网络的延迟影响很大。大致从ping上就能体现 地区1 地区2 ping时间 上海 广州 30ms 上海 上海 10ms 上海 美国 100ms 从终端的成功率上看,由于网络上的丢包、延迟,成功率会低很多,特别是图片(目前图片1~3M都是比较正常的),这么大的图片,在过程中,发生丢包、延迟,失败率可想而知,会特别的高。 这种场景,我们可以考虑下,访问国外某些网站的时候,经常是失败,体验非常差 改进点 那么需要怎么改进呢? 比较容易想到的就是,既然是距离远,那么直接在对应的地方部署一个服务,不就行了么? 这样各地的用户,通过dns的调度,访问对应的接入层,接入层只访问当前区域的服务(同一个区域),这样就减少了网络上的问题。解决了用户体验。但是,好像跟需求不是太耦合。。。需求是跨区域访问。 那么要怎么样实现跨区域访问呢? 从图上可以看出来,如果底层数据实现了数据同步,那么是不是就可以了? 比如亚洲用户发布内容,那么我们把数据同步给其他集群,这样其他集群就可以访问到亚洲用户的信息了 要怎么实现同步呢?目前了解到**FastDFS**可以实现分布式任务系统的,他是采用binlog进行同步,在log中有个标志位用户记录该条记录是C: 增加 D: 删除 A: 添加 M: 修改 U: 更新整个文件 T: 截断文件 等,当亚洲区域进行添加时,会发送日志给美洲、欧洲,他们也会根据binlog的日志添加,这里需要注意:同步数据采用的标识与写入的是不一样的,采用小写,目的是为了区别是否需要同步给其他集群。 这里还没有对FastDFS跨区同步进行测试过,还不确定具体的延迟能够到达多少(有待验证)。 理论上,上面的方案是可以实现的,那么我们会有什么问题呢? 所有图片数据,都存在多份,每个数据都需要进行公网的同步。 文件传入与数据传输需要保证一致,不能有数据了,没有文件 那么我们有没有其他方案进行呢?下面我们来看下 对于图片,可以采用CDN加速。 对于API接口了解到市面上,有一种产品,叫做“全站加速”或者“动态加速”,也就是cdn不进行缓存,直接访问,这样的话,我们可以直接让用户访问,这样的话,所有数据都访问了中心区域的数据,通过“动态加速”把用户和源进行连接,核心是增加了数据传输的稳定性,降低失败率。 这种方式存在什么问题: 数据量问题: a) 扩容问题:这个也不算特别问题,是项目一般都会遇到 b) 冷热数据:如果统一的采用一套文件系统,那么会导致数据积累越来越多,文件系统会不停的扩大 当然还有其他的一些需要考虑的点,比如高请求量下“文件内容缓存”、容灾备份等还没有详细讲 3.2 外部功能 既然自研中,考虑了外部功能,那么市面上是否有外部的功能,可以实现全球图片访问问题呢?...

June 9, 2022

Java线程

线程 概念 Java线程是什么 Java的线程,是运行在JVM的程序上的基本执行单元, Java针对线程抽象出Thread对象的概念。 Java线程分类 Thread分为守护线程和非守护线程,当JVM启动时,伴随一个非守护线程的运行,我们称之为主线程/main函数,当JVM所有的非守护线程都销毁时,JVM实例也会销毁; Java线程生命周期 Java线程包含6个状态:NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED 多线程优缺点 JVM支持多线程,正确使用多线程能大大提高程序的服务能力,同时也引入程序的复杂度和线程安全问题(不正确使用)。 状态Thread.State 一个线程在指定的时刻上,只能存在一个状态;JVM的线程状态和操作系统的线程状态不是一一对应的。了解线程状态可用于分析线程问题/监控,不建议通过判断线程状态来进行逻辑处理 NEW (新建) 一个尚未启动的线程处于这一状态。(A thread that has not yet started is in this state.) 尚未启动的线程处于这一状态,即尚未调用start() Theard t = new Theard(); RUNNABLE (可运行) 一个正在 Java 虚拟机中执行的线程处于这一状态。(A thread executing in the Java virtual machine is in this state.) JVM中可执行的线程处于这一状态 Theard t = new Theard(); t.start(); BLOCKED (阻塞) 一个正在阻塞等待一个监视器锁的线程处于这一状态。(A thread that is blocked waiting for a monitor lock is in this state....

June 2, 2022

Java内存模型

Java内存模型(JMM) 概念 Java内存模型(Java Memory Model,JMM),用于屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的并发效果,JMM规范了Java虚拟机与计算机内存是如何协同工作的:规定了一个线程如何和何时可以看到由其他线程修改过后的共享变量的值,以及在必须时如何同步的访问共享变量。 Java内存模型(不仅仅是JVM内存分区):调用栈和本地变量存放在线程栈上,对象存放在堆上。 堆栈存放规则 一个本地变量可能是原始类型,在这种情况下,它总是“呆在”线程栈上。 一个本地变量也可能是指向一个对象的一个引用。在这种情况下,引用(这个本地变量)存放在线程栈上,但是对象本身存放在堆上。 一个对象可能包含方法,这些方法可能包含本地变量。这些本地变量仍然存放在线程栈上,即使这些方法所属的对象存放在堆上。 一个对象的成员变量可能随着这个对象自身存放在堆上。不管这个成员变量是原始类型还是引用类型。 静态成员变量跟随着类定义一起也存放在堆上。 存放在堆上的对象可以被所有持有对这个对象引用的线程访问。当一个线程可以访问一个对象时,它也可以访问这个对象的成员变量。如果两个线程同时调用同一个对象上的同一个方法,它们将会都访问这个对象的成员变量,但是每一个线程都拥有这个成员变量的私有拷贝。 资料地址 EnjoyMoving

June 2, 2022

阿里云盘mac本地挂在

主要参考文档:https://blog.51cto.com/xuedingmaojun/4815572 采用方式: https://github.com/zxbu/webdav-aliyundriver#jar包运行 挂在地址代码 cd /Users/xxx/Workspaces/WebRoot/logs/webdav;nohup java -jar /Users/xxx/Workspaces/Env/WebDAV/PATH/bin/webdav-aliyundriver-2.4.2.jar --aliyundrive.refresh-token="aaa" --server.port=aaa --aliyundrive.work-dir=/usr/local/etc/webdav/aliyundriver --aliyundrive.auth.user-name=aaa --aliyundrive.auth.password=aaa > /Users/aaa/Workspaces/WebRoot/logs/webdav/webdav.log 2>&1 &; # nohup切换前台停止 fg

March 19, 2022