- 博客(47)
- 收藏
- 关注
原创 分布式id(3)— snowflake(雪花算法)的问题
我们算极端情况下,workerIdBits=10,即1024个节点的情况下,可以支持到两次发版中间第一个pod一直不重启,其余5个pod一直重启的极端情况下,也能支持204次。当时间回拨较大时,可以对序列化的初始值设置步长,每次触发时钟回拨事件,则其初始步长就加1w,可以在下面代码的第85行来实现,将sequence的初始值设置为10000。提到工作机器Id的作用,就是用于解决分布式Id重复的问题,这个workerId是通过构造方法传入的,如果我们用10位来存储这个值,那就是最多支持1024个节点。....
2022-07-19 15:57:49 3315
原创 分布式id(2)— snowflake(雪花算法)
一般地,我们会选用系统上线的时间作为时间戳的相对起点,而不使用JDK默认的时间戳起点(1970-01-01000000)。一般地,我们会选用系统上线的时间作为时间戳的相对起点,而不使用JDK默认的时间戳起点(1970-01-01000000)。这个数字就可以作为数据库的主键,他既可以保证是连续的也可以保证在分布式系统中是唯一的。该算法生成的是一个64位的ID,故在Java下正好可以通过8字节的long类型存放。最高位是符号位,为保证生成的ID是正数,故不使用,其值恒为0。.........
2022-07-19 15:40:22 695
原创 分布式id(1)
例如之前单体项目中一个表中的数据主键id都是自增的,mysql是利用autoincrement来实现自增,而oracle是利用序列来实现的,但是当单表数据量上来以后就要进行水平分表,阿里java开发建议是单表大于500w的时候就要分表,但是具体还是得看业务,如果索引用的号的话,单表千万的数据也是可以的。比如说,现在我们的商品数据已经堆积到2.5亿,新的数据在插入的时候,所有的数据都被插入到了分片3中,之前的分片12都不会有写入操作,所以表分片3中库的压力是非常大的。......
2022-07-19 15:34:55 325
原创 自增主键用完了该怎么办
此法极其麻烦,需要专业水平的选手进行操作。因为我们的mysql架构一般是读写分离架构,从机是用来读的。我们直接在从库上进行表结构修改,不会阻塞从库的读操作。改完之后,进行主从切换即可。唯一需要注意的是,主从切换过程中可能会有数据丢失的情况!将自增ID设为BigInt类型,你是不用考虑自增ID达到最大值这个问题!业内有一些第三方工具可以支持在线修改表结构,使用这些第三发工具,能够让你在执行。方式一使用mysql5.6+提供的在线修改功能。操作的时候,表不会阻塞!方式三改从库表结构,然后主从切换。......
2022-07-19 15:17:27 413
原创 Redis的数据结构(1)
Redis会确保Intset中的元素唯一、有序具备类型升级机制,可以节省内存空间底层采用二分查找方式来查询类似java的HashTable,底层是数组加链表来解决哈希冲突Dict包含两个哈希表,ht[0]平常用,ht[1]用来rehash当LoadFactor大于5或者LoadFactor大于1并且没有子进程任务时,Dict扩容当LoadFactor小于0.1时,Dict收缩扩容大小为第一个大于等于used+1的2^𝑛收缩大小为第一个大于等于used的2^𝑛https。.........
2022-07-17 18:22:38 1085
原创 Redis的数据结构(2)
当元素数量不多时,HT和SkipList的优势不明显,而且更耗内存。因此,zset底层数据结构必须满足键值存储、键必须唯一、可排序这几个需求。Redis中会根据存储的数据类型不同,选择不同的编码方式。Set是Redis中的集合,不一定确保元素有序,可以满足元素唯一、查询效率要求极高。可以看出,Set对查询元素的效率要求非常高,思考一下,什么样的数据结构可以满足?SkipList可以排序,并且可以同时存储score和ele值(member)HT(Dict)可以键值存储,并且可以根据key找value。....
2022-07-17 17:45:23 272
原创 JAVA线程池
系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互。在这种情形下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池。与数据库连接池类似的是,线程池在系统启动时即创建大量空闲的线程,程序将一个Runnable对象或Callable对象传给线程池,线程池就会启动一个空闲的线程来执行它们的run()或call()方法,当run()或call()方法执行结束后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个Runnable对象的run(
2022-07-06 21:00:24 223
原创 Java多线程之间的通信方式
在Java中线程通信主要有以下三种方式:如果线程之间采用synchronized来保证线程安全,则可以利用wait()、notify()、notifyAll()来实现线程通信。这三个方法都不是Thread类中所声明的方法,而是Object类中声明的方法。原因是每个对象都拥有锁,所以让当前线程等待某个对象的锁,当然应该通过这个对象来操作。并且因为当前线程可能会等待多个线程的锁,如果通过线程来操作,就非常复杂了。另外,这三个方法都是本地方法,并且被final修饰,无法被重写。wait()方法可以让当前线程释放对
2022-07-06 15:44:55 3342
原创 JAVA如何实现线程同步?
即有synchronized关键字修饰的方法,由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。需要注意, synchronized关键字也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类。即有synchronized关键字修饰的语句块,被该关键字修饰的语句块会自动被加上内置锁,从而实现同步。需值得注意的是,同步是一种高开销的操作,因此应该尽量减少同步的内容。通常没有必要同步整个方法,使用synchronized
2022-07-06 15:35:31 565
原创 Thread类的常用方法
Thread()Thread(String name)Thread(Runnable target)Thread(Runnable target, String name)其中,参数 name为线程名,参数 target为包含线程体的目标对象。currentThread():返回当前正在执行的线程;interrupted():返回当前执行的线程是否已经被中断;sleep(long millis):使当前执行的线程睡眠多少毫秒数;yield():使当前执行的线程自愿暂时放弃对处理器的使用权并允许其他线程执行;
2022-07-06 15:20:03 1077
原创 JAVA创建线程的几种方式
通过继承Thread类来创建并启动线程的步骤如下:定义Thread类的子类,并重写该类的run()方法,该run()方法将作为线程执行体。创建Thread子类的实例,即创建了线程对象。调用线程对象的start()方法来启动该线程。通过实现Runnable接口来创建并启动线程的步骤如下:定义Runnable接口的实现类,并实现该接口的run()方法,该run()方法将作为线程执行体。创建Runnable实现类的实例,并将其作为Thread的target来创建Thread对象,Thread对象为线程对象。调用线
2022-07-06 15:02:51 1249
原创 Java的序列化与反序列化相关问题
序列化机制可以将对象转换成字节序列,这些字节序列可以保存在磁盘上,也可以在网络中传输,并允许程序将这些字节序列再次恢复成原来的对象。其中,对象的序列化(Serialize),是指将一个Java对象写入IO流中,对象的反序列化(Deserialize),则是指从IO流中恢复该Java对象。若对象要支持序列化机制,则它的类需要实现Serializable接口,该接口是一个标记接口,它没有提供任何方法,只是标明该类是可以序列化的,Java的很多类已经实现了Serializable接口,如包装类、String、Da
2022-07-06 11:31:05 384
原创 CopyOnWriteArrayList原理
CopyOnWriteArrayList的原理参考答案CopyOnWriteArrayList是Java并发包里提供的并发类,简单来说它就是一个线程安全且读操作无锁的ArrayList。正如其名字一样,在写操作时会复制一份新的List,在新的List上完成写操作,然后再将原引用指向新的List。这样就保证了写操作的线程安全。CopyOnWriteArrayList允许线程并发访问读操作,这个时候是没有加锁限制的,性能较高。而写操作的时候,则首先将容器复制一份,然后在新的副本上执行写操作,这个时候写操作是上
2022-07-06 10:37:41 164
原创 JAVA的集合类
Java中的集合类主要由Collection和Map这两个接口派生而出,其中Collection接口又派生出三个子接口,分别是Set、List、Queue。所有的Java集合类,都是Set、List、Queue、Map这四个接口的实现类,这四个接口将集合分成了四大类,其中Set代表无序的,元素不可重复的集合;List代表有序的,元素可以重复的集合;Queue代表先进先出(FIFO)的队列;Map代表具有映射关系(key-value)的集合。这些接口拥有众多的实现类,其中最常用的实现类有HashSet、Tre
2022-07-06 09:33:58 447
原创 volatile 关键字
大家都应该知道 volatile 的主要作用有两点: - 保证变量的内存可见性 - 禁止指令重排序那么,什么是内存可见性,什么是指令重排序,以及它们涉及了那些机制呢?下面就让我们来看看吧。 我们知道声明了volatile关键字的变量可以在多线程处理环境下,确保内存的可见性。计算机硬件层会保证对被volatile关键字修饰的共享变量进行写操作后的内存可见性,而这种内存可见性是由Lock前缀指令以及缓存一致性协议(MESI控制协议)共同保证的。在现代计算机中,CPU 的速度是极高的,如果 CPU
2022-06-30 08:19:40 107
原创 一条sql的执行流程
先建立连接。每个客户端进程连接到服务器进程的时候,服务器进程都会创建一个线程去处理与这个客户端的一个交互。然后去查询查询缓存。查询缓存中会缓存最近访问的sql语句和数据。mysql8已经将查询缓存删除了,因为每次查询都需要去查询缓存中查,缓存中的数据修改了就需要删除对应的缓存,性能一般。然后就是解析 。解析语法,比如判断语法是否正确,将文本中将要查询的表和各种字段提取处理放到内部的某些数据结构上查询优化(优化器)对语句进行一个优化。用不用索引、用哪一个索引,生成一个执行计划,我们可以用explain查看某个
2022-06-27 14:55:32 251
原创 索引设计规则
1). 针对于数据量较大,且查询比较频繁的表建立索引。2). 针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索 引。3). 尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。4). 如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。5). 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间, 避免回表,提高查询效率。6). 要控制索引的数量,索引并不是多多益善,索引越
2022-06-27 14:48:22 112
原创 jdk7 和jdk8中的hashmap变化:
7中是Entry数组,8中是Node数组7中数组中放的是链表,8中放的是红黑树或链表、7扩容时是正序遍历原来的链表,将节点依次放在链表头,而8是正序遍历原来的链表,将节点放在链表尾;在并发的情况下,7可能出现并发死链的情况。7扩容时在size > threshold的前提下,还要判断null!=table[bucketIndex],即判断要放的那个桶是不是为空,如果都满足,才扩容;而8只要满足size > threshold就扩容。7在插入新节点时,是插在链表头的;8是插在链表尾的,还要判断是不是数量大于8
2022-06-24 16:41:10 322
原创 JAVA集合问题(2)
HashMap底层是一个数组,数组中元素是链表或者红黑树。hashMap补充:注意,自己写的hashmap的key会被覆盖(两个key的hashcode相等,且equals),而java里面的不会;value都会被覆盖jdk8实现懒惰初始化,用到的时候才创建,此时threshold会变为其容量大小,数组在用到的时候才会创建hashmap初始化容量都会转为2的次幂; 没定义容量则初始容量为16map允许key和value为nullhashMap里面得node和treenode都直接继承或间接继承了Ent
2022-06-24 16:38:35 138
原创 JAVA集合问题(1)
Vector底层也是一个Object数组,初始容量也是10,但它扩容是扩容2倍,他的方法都使用synchronized锁住了。LinkedList底层是一个双向链表,它继承了Deque和List。HashMap底层是一个数组,数组中元素是链表或者红黑树。Hashtable和HashMap一样,底层都是哈希表数据结构。Hashtable的初始化容量是11,默认加载因子是:0.75fHashtable的扩容是:原容量 * 2 + 1目前只需要掌握Properties属性类对象的相关方法即可。Properties
2022-06-24 16:32:02 144
原创 JUC相关问题(1)
线程安全集合类可以分为三大类:遗留的线程安全集合如 Hashtable , Vector使用 Collections 装饰的线程安全集合,如:Collections.synchronizedCollectionCollections.synchronizedListCollections.synchronizedMapCollections.synchronizedSetCollections.synchronizedNavigableMapCollections.synchronizedNavigable
2022-06-24 16:28:22 151
原创 JAVA的引用类型
在Java程序中,最常见的引用类型是强引用(普通系统99%以上都是强引用),也就是我们最常见的普通对象引用,也是默认的引用类型。相对的,软引用、弱引用和虚引用的对象是软可触及、弱可触及和虚可触及的,在一定条件下,都是可以被回收的。所以,强引用是造成Java内存泄漏的主要原因之一强引用具备以下特点:强引用可以直接访问目标对象。强引用所指向的对象在任何时候都不会被系统回收,虚拟机宁愿抛出OOM异常,也不会回收强引用所指向对象。强引用可能导致内存泄漏软引用是用来描述一些还有用,但非必需的对象。只被软引用关联着的对
2022-06-24 16:05:36 81
原创 STW和safe point
STWstop-the-world,简称STw,指的是GC事件发生过程中,会产生应用程序的停顿。停顿产生时整个应用程序线程都会被暂停,没有任何响应,有点像卡死的感觉,这个停顿称为STW。可达性分析算法中枚举根节点(GC Roots)会导致所有Java执行线程停顿。被STW中断的应用程序线程会在完成GC之后恢复,频繁中断会让用户感觉像是网速不快造成电影卡带一样,所以我们需要减少STw的发生。STW事件和采用哪款GC无关,所有的GC都有这个事件。安全点与安全区域安全点程序执行时并非在所有地方都能停顿下来开始GC
2022-06-23 21:46:29 302
原创 JAVA中的字符编码
Unicode(统一码、万国码、单一码)是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode 是为了解决传统的字符编码方案的局限而产生的(ASCII码),它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布.一个叫 ISO (国际标谁化组织)的国际组织决定着手解决这个问题。他们采用的方法很简单:废了所有的地区性编码方案,重新搞一个包括了地球上所有文化、所有字母和符号的编码!他们打算叫它”Univers
2022-06-23 18:35:04 1615
原创 JVM类加载之初始化
类加载的定义: JVM把描述类的数据从Class文件加载到内存,并对数据进行校验,解析和初始化,最终变成可以被JVM直接使用的Java类型(因为可以动态产生,这里的Class文件并不是具体存在磁盘中的文件,而是二进制数据流)一个类型被加载到内存使用 到 结束卸载出内存,它的生命周期分为7个阶段: 加载->验证->准备->解析->初始化->使用->卸载其中重要阶段一般的开始顺序: 加载->验证->准备->解析->初始化验证,准备,解析合起来又称为链接所以也可以是加载->链接->初始化注意这里的顺序是一般的开始
2022-06-23 17:54:27 309
原创 JVM类加载之解析
类加载的定义: JVM把描述类的数据从Class文件加载到内存,并对数据进行校验,解析和初始化,最终变成可以被JVM直接使用的Java类型(因为可以动态产生,这里的Class文件并不是具体存在磁盘中的文件,而是二进制数据流)一个类型被加载到内存使用 到 结束卸载出内存,它的生命周期分为7个阶段: 加载->验证->准备->解析->初始化->使用->卸载其中重要阶段一般的开始顺序: 加载->验证->准备->解析->初始化验证,准备,解析合起来又称为链接所以也可以是加载->链接->初始化注意这里的顺序是一般的开始
2022-06-23 17:51:37 265
原创 JVM类加载之准备
类加载的定义: JVM把描述类的数据从Class文件加载到内存,并对数据进行校验,解析和初始化,最终变成可以被JVM直接使用的Java类型(因为可以动态产生,这里的Class文件并不是具体存在磁盘中的文件,而是二进制数据流)一个类型被加载到内存使用 到 结束卸载出内存,它的生命周期分为7个阶段: 加载->验证->准备->解析->初始化->使用->卸载其中重要阶段一般的开始顺序: 加载->验证->准备->解析->初始化验证,准备,解析合起来又称为链接所以也可以是加载->链接->初始化注意这里的顺序是一般的开始
2022-06-23 17:44:13 181
原创 JVM类加载之验证
类加载的定义: JVM把描述类的数据从Class文件加载到内存,并对数据进行校验,解析和初始化,最终变成可以被JVM直接使用的Java类型(因为可以动态产生,这里的Class文件并不是具体存在磁盘中的文件,而是二进制数据流)一个类型被加载到内存使用 到 结束卸载出内存,它的生命周期分为7个阶段: 加载->验证->准备->解析->初始化->使用->卸载其中重要阶段一般的开始顺序: 加载->验证->准备->解析->初始化验证,准备,解析合起来又称为链接所以也可以是加载->链接->初始化注意这里的顺序是一般的开始
2022-06-23 17:41:23 426
原创 JVM的类加载之加载
类加载的定义: JVM把描述类的数据从Class文件加载到内存,并对数据进行校验,解析和初始化,最终变成可以被JVM直接使用的Java类型(因为可以动态产生,这里的Class文件并不是具体存在磁盘中的文件,而是二进制数据流)一个类型被加载到内存使用 到 结束卸载出内存,它的生命周期分为7个阶段: 加载->验证->准备->解析->初始化->使用->卸载其中重要阶段一般的开始顺序: 加载->验证->准备->解析->初始化验证,准备,解析合起来又称为链接所以也可以是加载->链接->初始化注意这里的顺序是一般的开始
2022-06-23 17:35:50 70
原创 读书笔记(1)
HTTP/1.1规范允许一台HTTP服务器搭建多个Web站点。比如,提供Web托管服务(Web Hosting Service)的供应商,可以用一台服务器为多位客户服务,也可以以每位客户持有的域名运行各自不同的网站。这是因为利用了虚拟主机(Virtual Host,又称虚拟服务器)的功能。即使物理层面只有一台服务器,但只要使用虚拟主机的功能,则可以假想已具有多台服务器。 在相同的IP地址下,由于虚拟主机可以寄存多个不同主机名和域名的Web网站,因此在发送HTTP请求时,必须在Host首部内完整
2022-06-21 08:32:28 56
原创 Mysql的快照读和当前读
读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加 锁。对于我们日常的操作,如:select ... lock in share mode(共享锁),select ... for update、update、insert、delete(排他锁)都是一种当前读。由此可知,当前读通过next-key来解决幻读问题。 简单的select(不加锁)就是快照读,快照读,读取的是记录数据的可见版本,有可能是历史数据, 不加锁,是非阻塞读。 快照读sql提
2022-06-17 21:22:23 3960
原创 HTTP 常见的状态码,有哪些?
状态码的职责是当客户端向服务器端发送请求时,描述返回的请求结果。借助状态码,用户可以知道服务器端是正常处理了请求,还是出现了错误。1xx 类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。2xx 类状态码表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。「200 OK」是最常见的成功状态码,表示一切正常。如果是非 HEAD 请求,服务器返回的响应头都 会有 body 数据。「204 No Content」也是常见的成功状态码,与 200 OK 基本相同,但响应头没有 body 数
2022-06-13 09:00:07 531
原创 UDP和TCP的对比
用户数据报协议UDP(User Datagram Protocol)、传输控制协议TCP(Transmission Control Protocol)UDP和TCP是TCP/IP体系结构运输层中的两个重要协议,其使用频率仅次于网际层的IP协议运输层采用面向连接的 TCP 协议时,尽管下面的网络是不可靠的(只提供尽最大努力服务),但TCP协议就相当于在逻辑上建立了一条通信信道,该信道是全双工的可靠信道。当运输层采用无连接的 UDP 协议时,这种逻辑通信信道是一条不可靠信道。接下来,我们从以下几个方面对比UDP
2022-06-13 08:12:42 2213
原创 Spring IOC和AOP
IoC (Inversion of control )控制反转/反转控制。它是一种思想不是一个技术实现。描述的是:Java 开发领域对象的创建以及管理的问题。例如:现有类 A 依赖于类 B传统的开发方式 :往往是在类 A 中手动通过 new 关键字来 new 一个 B 的对象出来。使用 IoC 思想的开发方式 :不通过 new 关键字来创建对象,而是通过 IoC 容器(Spring 框架) 来帮助我们实例化对象。我们需要哪个对象,直接从 IoC 容器里面过去即可。从以上两种开发方式的对比来看:我们 “丧
2022-06-12 16:42:46 96
原创 new String()创建几个对象?
下面代码中创建了几个对象?答案众说纷纭,有说创建了1个对象,也有说创建了2个对象。答案对,也不对,关键是要学到问题底层的原理。String的两种初始化形式是有本质区别的。当直接赋值时,字符串“abc”会被存储在常量池中,只有1份,此时的赋值操作等于是创建0个或1个对象。如果常量池中已经存在了“abc”,那么不会再创建对象,直接将引用赋值给str1;如果常量池中没有“abc”,那么创建一个对象,并将引用赋值给str1。那么,通过new String(“abc”);的形式又是如何呢?答案是1个或2个。当JV
2022-06-11 16:25:27 1166
原创 String.intern()的用法
String.intern()官方给的定义:When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the
2022-06-11 16:16:18 312
原创 Http协议的短连接和长连接
HTTP协议的初始版本中,每进行一次HTTP通信就要断开一次TCP连接。以当年的通信情况来说,因为都是些容量很小的文本传输,所以即使这样也没有多大问题。可随着HTTP的普及,文档中包含大量图片的情况多了起来。比如,使用浏览器浏览一个包含多张图片的HTML页面时,在发送请求访问HTML页面资源的同时,也会请求该HTML页面里包含的其他资源。因此,每次的请求都会造成无谓的TCP连接建立和断开,增加通信量的开销。为解决上述TCP连接的问题,HTTP/1.1和一部分的HTTP/1.0想出了持久连接(HTTPPers
2022-06-11 08:59:03 399
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人