引用计数(循环引用)和可达性分析找到无用的对象
标记-清除:简单,内存碎片,大对象找不到空间
标记-复制:分成两半,清理一半,没有碎片,如果存活多效率低(适合新生代)
标记-整理:将存活对象向一端移动,清除边界外(适合老年代)
分代收集:老年代回收少,新生代回收多;对新生代使用复制算法,一个较大的eden和两个较小的survivor,提高空间利用的效率
反射是一种在程序运行时可以动态访问,修改某个类中任意属性和方法的机制(包括private)
功能包括:
1.判断对象所属的类
2.构造一个类的对象
3.判断类具有的变量和方法
4.调用任意一个对象方法
核心类包括四个:
1.java.lang.Class.java:类对象
2.java.lang.reflect.Constructor.java:类的构造器对象
3.java.lang.reflect.Method.java:类的方法对象
4.java.lang.reflect.Field.java:类的属性对象
工作原理:
java变成.class后有类的所有信息,父类接口构造函数方法属性;在运行时会被classLoader加载到虚拟机。类被加载后,jvm自动产生一个class对象,new就是通过这些class对象创建。
用户进程想执行io,需要发起系统调用访问内核空间,包括:
1.内核等待io准备好数据
2.内核将数据从内核空间拷贝到用户空间
NIO(Non-blocking io)是只同步非阻塞io,使用轮询
1.如果kernel没有数据,调用失败,不需要等待
2.如果kernel有数据,阻塞,复制完成后才返回成功
NIO优点:无序等待无数据
NIO缺点:轮询占用cpu;定时轮训不及时;read导致用户态内核态频繁转换
IO多路复用(也就是java中的NIO, newIO)
1.一个线程监视多个描述符socket,一旦某个描述符就绪(kernel可读可写),可以通知程序进行io,系统调用包括select,poll, epoll
2.select会阻塞到socket有数据就绪,再调用read
io多路复用优点:改为select轮询,查找可io的操作;可同时管理多条连接
io多路缺点:select也属于同步阻塞io
select和poll:线性结构存储socket集合,需要遍历文件描述符集合找到可用socket
epoll:用红黑树跟踪文件描述符(logn),事件驱动维护链表记录就绪事件
适合:
1.唯一性限制
2.频繁where,order by和group by
3.多表join的连接字段创建索引,类型必须一致(否则隐式转换导致索引失效)
4.字符串前缀创建索引,使用最频繁放联合索引左侧
5.多个字段维护索引,联合索引更优
不合适:
1.数据量小没有效果
2.大量重复数据高于10%例如性别
3.经常更新的表索引影响效率
4.无序的值不要做索引
5.每张表索引不超过6个
MySQL 事务具有四个特性:原子性、一致性、隔离性、持久性,这四个特性简称 ACID 特性
一、原子性(Atomicity ):一个事务是一个不可再分割的整体,要么全部成功,要么全部失败
事务在数据库中就是一个基本的工作单位,事务中包含的逻辑操作(SQL 语句),只有两种情况:成功和失败。事务的原子性其实指的就是这个逻辑操作过程具有原子性,不会出现有的逻辑操作成功,有的逻辑操作失败这种情况
二、一致性(Consistency ):一个事务可以让数据从一种一致状态切换到另一种一致性状态
举例说明:张三给李四转账 100 元,那么张三的余额应减少 100 元,李四的余额应增加 100 元,张三的余额减少和李四的余额增加这是两个逻辑操作具有一致性
三、隔离性(Isolution ):一个事务不受其他事务的影响,并且多个事务彼此隔离
一个事务内部的操作及使用的数据,对并发的其他事务是隔离的,并发执行的各个事务之间不会互相干扰
四、持久性(Durability ):一个事务一旦被提交,在数据库中的改变就是永久的,提交后就不能再回滚
一个事务被提交后,在数据库中的改变就是永久的,即使系统崩溃重新启动数据库数据也不会发生改变
唯一标识
雪花算法:
号段模式:也是基于数据库,但分段,每次可以获得多个id,性能提升
remote procedure call,远程过程调用,使得分布式应用更容易
rpc一般都有长链接,都有注册中心,协议效率更高
1.client发起调用给client stub
2.client stub序列化后找到地址发给server stub
3.server stub解码后调用本地服务处理
4.得到返回结果后发给stub序列哈再发给client stub
5.client stub解码后发给client得到结果
涉及到的技术:
1.动态代理,stub的生成需要java动态代理
2.序列化,例如fastjson,数据都转化为字节
3.nio通信,例如dubbo
4.服务注册中心,client连接server发布的服务,dubbo用zookeeper
5.负载均衡多节点集群
6.探活:client心跳和server主动探测
队列:list,例如将爬虫失败的存到redis队列,再启动一个线程自旋的方式阻塞式取出
签到:bitmap,二进制数组,setbit, bitcount获取结果
原子扣减库存:lua脚本保证原子性
分布式锁:setnx + 过期事件用lua保证原子性;锁有心跳检测,防止未解锁,锁失效问题;线程自旋获取锁;redisson框架
延迟队列,排行榜:zset,用score作为延迟的时间点,顺序获得端口的值,如果时间戳大于等于score可以取出
分布式id递增等等
string:sds,获取长度o1,不会溢出,二进制安全
列表:双端链表
字典:类似hashmap
跳表:查询插入删除logn,zset
压缩列表:一块连续的内存空间,没有空隙(当lsit数据较少时,多了就linkedlist)
快速列表:由于每个节点都有prev和next指针,内存单独分配,使用quicklist代替。它是ziplist和linkedlist的混合,将linkedlist切分,每一段数据使用ziplist紧凑存储,多个ziplist之间用指针串联
自动装配:通过注解或者一些简单的配置就可以在springboot的帮助下实现某块功能
@springbootapplicaiton = @configuration + @enableautoConfiguration + @ComponentScan
@EnableAutoConfiguration:实现自动装配的核心注解,importSelector获取所有符合条件的类的全限定类名,这些类需要被加载到ioc容器中
@configuration:允许在上下文注册额外的bean或导入其他配置类
@componentScan:扫描被@Component注解的bean,启动类所在包下的所有类,可以通过filter排除不扫描的包
ioc=控制反转,把创建对象的控制交给spring进行管理,原来自己要new现在直接从spring获取
减低了代码的耦合度,降低程序的维护成本。
spring提供了一个beanFactory,他还有一个ApplicationContext,通过工厂+反射实现
都可以卸载字段or setter上
autowired只能byTpye注入,如果希望byName可以结合@Qualifier一起使用或者@Primary
resource默认通过ByName注入,spring会把@resource注解的name属性解析为bean的名字
多副本负载均衡可以用加权轮询,但是对于数据分片分布式系统不适用
例如某个key只能在某些node上获取
如果使用hash(key) % n进行映射,当n变化时会迁移数据,成本高
用一致性哈希会有一个2**32-1的空间,将节点和data都映射到一个哈希环上
数据i存储节点就是hash顺时针找到的第一个节点
加入节点只影响相邻节点
但是,一致性哈希不保证分布均匀
可能会导致数据的全体迁移
通过引入虚拟节点解决不均匀问题
原有节点多复制一些可以提高节点的均衡度,使得某个节点不会负载特别高