|
|
|
@ -86,7 +86,7 @@ Redis默认是快照RDB的持久化方式。对于主从同步来说,主从刚
|
|
|
|
|
3. 用底层模型不同:它们之间底层实现方式以及与客户端之间通信的应用协议不一样。redis直接自己构建了VM机制,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
|
|
|
|
|
4. value的大小:redis可以达到1GB,而memcache只有1MB。
|
|
|
|
|
|
|
|
|
|
### redis并发竞争key的解决方案
|
|
|
|
|
### Redis并发竞争key的解决方案
|
|
|
|
|
|
|
|
|
|
1. 分布式锁+时间戳
|
|
|
|
|
2. 利用消息队列
|
|
|
|
@ -203,6 +203,12 @@ HotSpot JVM把年轻代分为了三部分:1个Eden区和2个Survivor区(分
|
|
|
|
|
3. 方法区中常量引用的对象。
|
|
|
|
|
4. 本地方法栈中JNI(即一般说的Native方法)引用的对象。
|
|
|
|
|
|
|
|
|
|
### GC中Stop the world(STW)
|
|
|
|
|
|
|
|
|
|
在执行垃圾收集算法时,Java应用程序的其他所有除了垃圾收集收集器线程之外的线程都被挂起。此时,系统只能允许GC线程进行运行,其他线程则会全部暂停,等待GC线程执行完毕后才能再次运行。这些工作都是由虚拟机在后台自动发起和自动完成的,是在用户不可见的情况下把用户正常工作的线程全部停下来,这对于很多的应用程序,尤其是那些对于实时性要求很高的程序来说是难以接受的。
|
|
|
|
|
|
|
|
|
|
但不是说GC必须STW,你也可以选择降低运行速度但是可以并发执行的收集算法,这取决于你的业务。
|
|
|
|
|
|
|
|
|
|
### 垃圾回收算法
|
|
|
|
|
|
|
|
|
|
1. 停止-复制:先暂停程序的运行,然后将所有存活的对象从当前堆复制到另一个堆,没有被复制的对象全部都是垃圾。当对象被复制到新堆时,它们是一个挨着一个的,所以新堆保持紧凑排列,然后就可以按前述方法简单,直接的分配了。缺点是一浪费空间,两个堆之间要来回倒腾,二是当程序进入稳定态时,可能只会产生极少的垃圾,甚至不产生垃圾,尽管如此,复制式回收器仍会将所有内存自一处复制到另一处。
|
|
|
|
@ -240,18 +246,6 @@ HotSpot JVM把年轻代分为了三部分:1个Eden区和2个Survivor区(分
|
|
|
|
|
3. 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
|
|
|
|
|
4. 当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。
|
|
|
|
|
|
|
|
|
|
### CAS操作
|
|
|
|
|
|
|
|
|
|
CAS是英文单词CompareAndSwap的缩写,中文意思是:比较并替换。CAS需要有3个操作数:内存地址V,旧的预期值A,即将要更新的目标值B。CAS指令执行时,当且仅当内存地址V的值与预期值A相等时,将内存地址V的值修改为B,否则就什么都不做。整个比较并替换的操作是一个原子操作。如 Intel 处理器,比较并交换通过指令的 cmpxchg 系列实现。
|
|
|
|
|
|
|
|
|
|
### CAS操作ABA问题:
|
|
|
|
|
|
|
|
|
|
如果在这段期间它的值曾经被改成了B,后来又被改回为A,那CAS操作就会误认为它从来没有被改变过。Java并发包为了解决这个问题,提供了一个带有标记的原子引用类“AtomicStampedReference”,它可以通过控制变量值的版本来保证CAS的正确性。
|
|
|
|
|
|
|
|
|
|
### AQS理论的数据结构
|
|
|
|
|
|
|
|
|
|
AQS内部有3个对象,一个是state(用于计数器,类似gc的回收计数器),一个是线程标记(当前线程是谁加锁的),一个是阻塞队列。
|
|
|
|
|
|
|
|
|
|
### i++操作的字节码指令
|
|
|
|
|
|
|
|
|
|
1. 将int类型常量加载到操作数栈顶
|
|
|
|
@ -281,6 +275,27 @@ HashMap的环:若当前线程此时获得ertry节点,但是被线程中断
|
|
|
|
|
|
|
|
|
|
volatile在多处理器开发中保证了共享变量的“ 可见性”。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。(共享内存,私有内存)
|
|
|
|
|
|
|
|
|
|
### Atomic类的CAS操作
|
|
|
|
|
|
|
|
|
|
CAS是英文单词CompareAndSwap的缩写,中文意思是:比较并替换。CAS需要有3个操作数:内存地址V,旧的预期值A,即将要更新的目标值B。CAS指令执行时,当且仅当内存地址V的值与预期值A相等时,将内存地址V的值修改为B,否则就什么都不做。整个比较并替换的操作是一个原子操作。如 Intel 处理器,比较并交换通过指令的 cmpxchg 系列实现。
|
|
|
|
|
|
|
|
|
|
### CAS操作ABA问题:
|
|
|
|
|
|
|
|
|
|
如果在这段期间它的值曾经被改成了B,后来又被改回为A,那CAS操作就会误认为它从来没有被改变过。Java并发包为了解决这个问题,提供了一个带有标记的原子引用类“AtomicStampedReference”,它可以通过控制变量值的版本来保证CAS的正确性。
|
|
|
|
|
|
|
|
|
|
### Synchronized和Lock的区别
|
|
|
|
|
|
|
|
|
|
1. 首先synchronized是java内置关键字在jvm层面,Lock是个java类。
|
|
|
|
|
2. synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁,并且可以主动尝试去获取锁。
|
|
|
|
|
3. synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁。
|
|
|
|
|
4. 用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了。
|
|
|
|
|
5. synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可)
|
|
|
|
|
6. Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。
|
|
|
|
|
|
|
|
|
|
### AQS理论的数据结构
|
|
|
|
|
|
|
|
|
|
AQS内部有3个对象,一个是state(用于计数器,类似gc的回收计数器),一个是线程标记(当前线程是谁加锁的),一个是阻塞队列。
|
|
|
|
|
|
|
|
|
|
### 死锁的4个必要条件
|
|
|
|
|
|
|
|
|
|
1. 互斥条件:一个资源每次只能被一个线程使用;
|
|
|
|
@ -317,12 +332,6 @@ HashSet的value存的是一个static finial PRESENT = newObject()。而HashSet
|
|
|
|
|
|
|
|
|
|
未精确定义字节。Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替,而boolean数组将会被编码成Java虚拟机的byte数组,每个元素boolean元素占8位。
|
|
|
|
|
|
|
|
|
|
### GC中Stop the world(STW)
|
|
|
|
|
|
|
|
|
|
在执行垃圾收集算法时,Java应用程序的其他所有除了垃圾收集收集器线程之外的线程都被挂起。此时,系统只能允许GC线程进行运行,其他线程则会全部暂停,等待GC线程执行完毕后才能再次运行。这些工作都是由虚拟机在后台自动发起和自动完成的,是在用户不可见的情况下把用户正常工作的线程全部停下来,这对于很多的应用程序,尤其是那些对于实时性要求很高的程序来说是难以接受的。
|
|
|
|
|
|
|
|
|
|
但不是说GC必须STW,你也可以选择降低运行速度但是可以并发执行的收集算法,这取决于你的业务。
|
|
|
|
|
|
|
|
|
|
## 消息队列
|
|
|
|
|
|
|
|
|
|
### 为什么需要消息队列
|
|
|
|
@ -455,6 +464,7 @@ void quick_sort(int a[], int low, int high){
|
|
|
|
|
* 缓存:缓存比较好理解,在大型高并发系统中,如果没有缓存数据库将分分钟被爆,系统也会瞬间瘫痪。使用缓存不单单能够提升系统访问速度、提高并发访问量,也是保护数据库、保护系统的有效方式。大型网站一般主要是“读”,缓存的使用很容易被想到。在大型“写”系统中,缓存也常常扮演者非常重要的角色。比如累积一些数据批量写入,内存里面的缓存队列(生产消费),以及HBase写数据的机制等等也都是通过缓存提升系统的吞吐量或者实现系统的保护措施。甚至消息中间件,你也可以认为是一种分布式的数据缓存。
|
|
|
|
|
* 降级:服务降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。降级往往会指定不同的级别,面临不同的异常等级执行不同的处理。根据服务方式:可以拒接服务,可以延迟服务,也有时候可以随机服务。根据服务范围:可以砍掉某个功能,也可以砍掉某些模块。总之服务降级需要根据不同的业务需求采用不同的降级策略。主要的目的就是服务虽然有损但是总比没有好。
|
|
|
|
|
* 限流:限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行,一旦达到的需要限制的阈值,就需要限制流量并采取一些措施以完成限制流量的目的。比如:延迟处理,拒绝处理,或者部分拒绝处理等等。
|
|
|
|
|
|
|
|
|
|
### 常见的限流算法:
|
|
|
|
|
|
|
|
|
|
常见的限流算法有计数器、漏桶和令牌桶算法。漏桶算法在分布式环境中消息中间件或者Redis都是可选的方案。发放令牌的频率增加可以提升整体数据处理的速度,而通过每次获取令牌的个数增加或者放慢令牌的发放速度和降低整体数据处理速度。而漏桶不行,因为它的流出速率是固定的,程序处理速度也是固定的。
|
|
|
|
|