1、用maven插件maven-assembly-plugin打包时,如果代码修改了,必须recompile主类or rebuild项目,才能再打包,否则修改不生效
2、打jar包部署到远程私服仓库
3、sqoop作为很常用的数据同步工具,用于RDBMS和HDFS的数据迁移,但是不支持NoSql,比如说MongoDB
4、引用net.sf.json包:
net.sf.json-lib
json-lib
2.4
上面的引用是用不了的!!!要用下面的
net.sf.json-lib
json-lib
2.4
jdk15
6、Linux环境下非root用户安装Python及相关库
https://blog.csdn.net/dream_angel_z/article/details/51338546
7、少量数据去重:hash表去重
海量数据下去重:使用bitmap和布隆过滤器去重
8、三范式
9、调度平台执行shell脚本,需要捕获脚本成功或失败状态,则需要加exit 状态码,而且exit状态码需要跟在最关键的执行代码后面,这个关键代码执行成功,表示整个任务执行成功
10、调度平台有依赖功能,即任务A依赖于任务B,那么只有B执行成功了,A才会执行,那么调度平台必须能捕获到任务真正的执行成功失败状态。
如20点10分执行A这个天任务,依赖于18点10分执行的B天任务,那么调度平台应该提供一个依赖时间范围,如当天18点到19点的依赖时间,表示当天这个时间B任务运行成功了,才会执行A任务
11、任务调度系统:https://blog.csdn.net/a331685690/article/details/81814000
12、在 2.5 亿个整数中找出不重复的整数,注,内存不足以容纳这 2.5 亿个整数 。
13、dp算法:动态规划算法也可以说是 ‘记住求过的解来节省时间’"
public static int fib(int n)
{
if(n<=0)
return n;
int []Memo=new int[n+1];
Memo[0]=0;
Memo[1]=1;
for(int i=2;i<=n;i++)
{
Memo[i]=Memo[i-1]+Memo[i-2];
}
return Memo[n];
}
14、正则匹配手机号:^1[3578]\d{9}$
^1表示以1开头,[3578]表示第二位的数字为3578中的任意一个,\d{9}表示0~9范围内的数字匹配九次,$表示结束,12位以上的数字不匹配。
15、vim模式下查找:输入/,按下n查找下一个,按下N查找上一个
18、MQ-----ActiveMQ、RabbitMQ,Kafka,RocketMQ
RabbitMq比kafka成熟,在可用性上,稳定性上,可靠性上,RabbitMq超过kafka。但是吞吐量上远不及kafka,因为rabbitmq的架构跟zk很像,读写请求只能由master
queue处理,如果连接到非master queue,则会路由到master queue处理。非master
queue只是起到了同步备份功能
Kafka 定位是日志消息队列,可以看做是一个日志系统。吞吐量最大
KAFKA 有丢数据的情况 做日志系统可以,做数据系统别用了,还是用rabbit。rabbitmq在金融场景中经常使用,具有较高的严谨性,数据丢失的可能性更小,同时具备更高的实时性,常用于金融场景交易数据传输
19、执行jar包的时候,如果要在命令里面添加依赖jar,则在后面加:xxx.jar
java -cp xxx.jar:mysql-connector-java-5.1.8.jar
20、对于通过调度平台分发的spark任务,因为分发到的spark执行机器不确定是哪台。一般是将sparkjar包放到hdfs上,然后在启动脚本里面将hdfs上的jar包下载到本地,这样就可以在分发的机器上执行这个jar包了
21、边缘计算方案–服务器端部署轻量级解析服务,边缘容器化部署,类似于Python里面的docker容器化部署。提高服务的鲁棒性
对于延时主要耗在网络传输的业务场景
物联网(IoT)技术出现,尤其是在5G以后,数据爆发式增长,集中式的计算处理模式将面临难解的瓶颈和压力:因为大量的数据经过网络传输会受带宽,网络等影响
此时,在靠近数据产生的网络边缘设备开始提供数据的一些处理的能力和服务,我们将这种数据网络边缘提供的处理能力叫做边缘计算。简单来说,是指在靠近物或数据源头的一侧,采用网络、计算、存储、
应用核心能力为一体的开放平台,就近提供最近端服务。
23、多数情况下,一个汉字=2个英文字母=2字节=16个二进制位。但是不同的编码格式汉字占的字节其实是不一样的
24、递归和迭代的区别
//求n个连续正整数的和值
//迭代
int GetSum_1(int m) {
int i = 1, sum = 0;
while (i <= m) {
sum = sum + i;
i++;
}
return sum;
}
//递归
int GetSum_2(int n) {
if (n <= 0) {
return 0;
} else {
求n个连续正整数和=n +(求n-1个正整数的和)
return n + GetSum_2(n - 1);
}
小结
从写法上
迭代:循环结构,例如for,while循环
递归:选择结构,例如if else 调用自己,并在合适时机退出
从代码量上
迭代:多
递归:少
从性能上
迭代:快
递归:慢
推荐:能不用递归就不用递归,递归一般都可以用迭代来代替。
25、快速排序
它的基本思想是:通过一趟排序(这趟排序包含多次比较:包括多次从左边开始找到第一个比基准数大的数,多次从右边开始找到第一个比基准数小的数)将要排序的数据分割成独立的两部分,
其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
26、Apache beam是一个集合了flink,spark等实时框架的框架,这样可以让每个人可以用自己喜欢的语言,擅长的技术去做项目里的一部分模块,然后最后集成到beam里面
27、Metrics:让微服务的运行状态更透明
在应用程序中,通常会记录日志以便事后分析,在很多情况下是产生了问题之后,再去查看日志,是一种事后的静态分析。在很多时候,我们可能需要了解整个系统在当前,或者某一时刻运行的情况,比如一个系统后台服务,我们可能需要了解一些实时监控的数据
例如,利用Metrics+ElasticSearch/druid+grafana/kibana来构建监控平台
Metrics 采集数据。ElasticSearch/druid 存储数据。Grafana/kibana 显示数据
也可以用Metrics去监控go微服务接口,比如监控服务的请求数,内存,cpu的使用率等
28、大数据实时展示:用flink或者spark把数据写到es或者hbase,再通过kibana或者grafana去查询es数据进行展示
29、kibana想要制作一个x轴为时间的图表,那么index里面必须有一个字段是date类型。且flink写数据到es的时候,这个字段也必须是Date类型数据
30、实时数据服务,一般还要通过离线etl进行离线修正,步数
31、实时数仓在应用层,存储方案可选MySQL,es,druid等
32、spark写hdfs,orc格式不能像text格式一样,建表的时候指定分隔符,然后spark写hive的时候,直接写一个字符串,这样子orc表是不会根据分隔符拆分的,其实orc的表分隔符是没用的
33、bitmap原理
在java中:bits就表示一个二进制位,int型变量使用32bit存储数据,其中最高位是符号位,0表示正数,1表示负数,可通过Integer.toBinaryString()转换为bit字符串。比如9,在Java里面其实是1001这样二进制位存储的
byte -> 8 bits -->1字节
char -> 16 bit -->2字节
short -> 16 bits -->2字节
int -> 32 bits -->4字节
float -> 32 bits -->4字节
long -> 64 bits -->8字节
Bit-map的基本思想就是用一个bit位来标记某个元素对应的Value。一个int整数占32个bit,即原来32bit才能表示一个整数,现在一个bit就可以表示一个整数,即32个数字只需要一个int类型所占内存空间大小就够了,这样在大数据量的情况下会节省很多内存。
具体思路:
假设有N个整数,那么我们只需要申请一个int数组长度为 int tmp[1+N/32]即可存储完这些数据, 这个数组的每一个元素都是一个32bit。所以可得到BitMap表:
tmp[0]:可表示0~31
tmp[1]:可表示32~63
tmp[2]可表示64~95
如何判断int数字在tmp数组的哪个下标,这个其实可以通过直接除以32取整数部分,例如:整数8除以32取整等于0,那么8就在tmp[0]上。另外,我们如何知道了8在tmp[0]中的32个位中的哪个位,这种情况直接mod上32就ok,又如整数8,在tmp[0]中的第8 mod上32等于8,那么整数8就在tmp[0]中的第八个bit位(从右边数起)。
如果一共有1亿的数据:1、2、5、7、33、35……,那么具体的BitMap表示为:
array[0] 0000 0000 0000 0000 0000 0000 0101 0011
array[1] 0000 0000 0000 0000 0000 0000 0100 0101
Roaring bitmaps是一种超常规的压缩BitMap。它的速度比未压缩的BitMap快上百倍。
38、东八区时间:“2018-05-23T16:05:52+08:00”
utc时间:“2018-05-23T16:05:52.123Z”
39、布隆过滤器
本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构
判断某个元素是否存在可以用HashMap,可以将值映射到 HashMap 的 Key,然后可以在 O(1) 的时间复杂度内返回结果,效率奇高。但是 HashMap 的实现也有缺点,例如存储容量占比高
布隆过滤器是一个 bit 向量或者说 bit 数组,如果我们要映射一个值到布隆过滤器中,我们需要使用多个不同的哈希函数生成多个哈希值,并对每个生成的哈希值指向的 bit 位置 1。所以布隆过滤器整合了hash和bitmap技术
使用场景
40、 javabean 就是一个很简单的类,这个类就定义一系列 get 和 set 方法。 javaBean在MVC设计模型中是model,又称模型层,在一般的程序中,我们称它为数据层,就是用来设置数据的属性和一些行为,然后我会提供获取属性和设置属性的get/set方法
41、如果一个类只有一个无参的构造函数,那么我们new这个类的时候,也只能new 类()
43、热部署,就是在应用正在运行的时候升级软件(修改代码,修改配置文件等等),却不需要重新启动应用而能立即生效。flume就属于一种热部署,当启动flume后,去修改配置文件,能立即生效
44、maven中provided作用: provided意味着打包的时候可以不用包进去,因为provided表明该包只在编译和测试的时候用
45、javascript, ajax, jquery的关系:
JS是一门前端语言。
Ajax是一门技术,它提供了异步更新的机制,使用客户端与服务器间交换数据而非整个页面文档,实现页面的局部更新。
jQuery是一个框架,它对JS和Ajax进行了封装
46、Java中equals和的区别
java中的数据类型,可分为两类:(不管是哪一类,我们做比较,是为了比较值,而不是为了比较它们在内存中的地址)
(1)基本数据类型,也称原始数据类型。byte,short,char,int,long,float,double,boolean
他们之间的比较,应用双等号(),比较的是他们的值。
(2)复合数据类型(类)
当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,
否则比较后结果为false。 JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地址,但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。
也就是string类型的比较用equals
47、HDFS架构:namenode,datanode,secondary namenode
mapreduce作业运行架构:yarn(RM,AM,NM…)
48、websocket
1)websocket协议和http协议都是基于TCP协议的
2)浏览器和服务器只需要做一个握手的动作,然后浏览器和服务器之间就形成了一条长连接快速通道, 两者之间就直接可以数据互相传送
websocket 握手连接过程:
客户端向服务器发送请求websocket的http报文,然后服务器来验证这个http报文是不是符合websocket的协议。
如果符合,服务器返回握手报文,给客户端连接成功
3)建立连接后,客户端就可以通过onmessage监控服务器端过来的数据,一有数据过来就执行onmessage对应的方法
48、散列函数(又称哈希函数):把任意长度的输入转换成固定长度的输出(hash值)的一个函数。散列值通常用一个短的随机字母和数字组成的字符串来代表。好的散列函数在输入域中很少出现散列冲突。
49、取模运算(%),即取余数运算
50、在做分布式集群的负载均衡(一个请求进来了,是分配给A服务器还是B或者C)时,传统的取模方式以及hash方式在节点增加时,会产生大量数据搬迁
而用一致性hash就能保证在节点数量变化的时候影响尽可能小
51、一致性hash:对节点和数据,都做一次哈希运算,然后比较节点和数据的哈希值。将hash值与节点hash值相近的数据放在此节点上
https://blog.csdn.net/gerryke/article/details/53939212
https://www.cnblogs.com/color-my-life/p/5799903.html
53、栈,堆,队列
栈内存:存储的都是局部变量,包括基本数据类型变量和对象的引用变量(方法中的都是局部变量,方法外的是全局变量),栈内存存放的变量生命周期一旦结束(超过变量的作用域)就会被释放。栈内存的更新速度很快,因为局部变量的生命周期都很短。
在堆中产生一个对象后,可以在栈中定义一个引用变量(相当于指针),让栈中这个引用变量的取值等于数组或对象在堆内存中的首地址
堆内存:存储的是数组和对象(其实数组就是对象),凡是new建立的都是在堆中,数组和对象在没有引用变量指向它的时候,才变成垃圾,不能被继续使用,但是仍然会占用堆内存空间,然后在一个不确定的时间内,由java虚拟机自动垃圾回收器回收,这也是java程序为什么会占用很大内存的原因。
队列是先进先出。队列只能在队头做删除操作,在队尾做插入操作
栈是先进后出。而栈只能在栈顶做插入和删除操
堆无所谓顺序。可以随心所欲的进行增加变量和删除变量
54、两个栈实现一个队列:例如对于1,2,3,4 :先把数据push进栈1,再pop出数据,再把数据push进栈2,再pop出数据,最后结果就是1,2,3,4了
55、十进制整数转二进制:除2取余,逆序排列
十进制小数转二进制:乘2取整,顺序排列
77、简历查重:就是根据一定规则,提取出解析好的简历 json 中的特定字段组合,例如 姓名+邮箱+学校 就是一个组合,学校+公司+职位名 又是一个组合,一封简历可以有多个组合,每个组合的值转换成一个 md5 值,这样一封简历就对应多个 md5 值
两封简历只要有一个 md5 值相同,就认为这两m封简历实际上是一个人的简历
78、simhash与传统hash的区别
传统hash描述两个内容是否一样,因为即使原始内容只相差一个字节,所产生的签名也很可能差别很大。
simhash描述两个内容是否相似。
做个测试,两个相差只有一个字符的文本串,“你妈妈喊你回家吃饭哦,回家罗回家罗” 和 “你妈妈叫你回家吃饭啦,回家罗回家罗”。
通过simhash计算结果为:
1000010010101101111111100000101011010001001111100001001011001011
1000010010101101011111100000101011010001001111100001101010001011
通过传统hash计算为:
0001000001100110100111011011110
1010010001111111110010110011101
大家可以看得出来,相似的文本只有部分 01 串变化了,而普通的hash却不能做到,这个就是局部敏感哈希的魅力。
79、simhash原理:
1)分词(通过结巴,hanlp分词)
2)提取关键词(通过结巴,hanlp提取关键词,一般利用TF-IDF算法原理)
3)将每个关键词进行hash,加权,合并
4)降维
80、simhash在实际项目中的应用
81、知识图谱
1)其实百度百科就可以看作是一个知识图谱,我们往ES里面加载的公司学校数据(公司的名字,行业,历史,懂事,英文名。。。)也类似于一个知识图谱
2)构建知识图谱,首先要进行数据收集,预处理。比如不同的人对同一家公司可能有不同的写法,这时候就要对公司名进行实体对齐(normalize)
82、词性标注是做动词或名词这种词性标注的
命名实体识别是识别一个 token 是什么实体
比如:
#NLPTokenizer会进行实体识别
#首先分词,然后进行实体识别(将公司这个实体识别出来),最后还会进行词性标注
NLPTokenizer = JClass(‘com.hankcs.hanlp.tokenizer.NLPTokenizer’)
print(NLPTokenizer.segment(‘李嘉诚创建了成都科技公司’)) 输出:[李嘉诚/nr, 创建/v, 了/u, 成都科技公司/nt]
#HanLP不会进行实体识别:首先分词,然后进行词性标注
HanLP = JClass(‘com.hankcs.hanlp.HanLP’)
print(HanLP.segment(‘李嘉诚创建了成都科技公司’)) 输出:[李嘉诚/nr, 创建/v, 了/ule, 成都/ns, 科技/n, 公司/nis]
83、JD解析逻辑
1)人工整理多个词典:比如证书词典,主要包括词和词性(nerName: ncert),这其实也是词性标注的工作
2)词典用于三个方面:
3)通过hanlp(词典)以及trie树进行分词,实体识别后。根据短文识别的基于上下文的语意理解,还要将token组合成句子,句子再组合成段落,段落组合成section等等。再通过在前端配置需要寻找的词的词性,比如location:nsct,然后利用token_query工具从上述处理结果中查询出地点
84、秒杀系统
一个秒杀活动开启之前,首先会在数据库表goods_info插入一条要秒杀的商品及其数量
迷你版秒杀系统
每个用户请求(一个线程)过来,传来两个参数-商品编号和购买数量:code1和buy_count。然后执行数据库更新:
update good_info set amount=amount - buy_count where code=code1
由于秒杀系统都是高并发,所以执行数据库更新的Java代码必须加锁,否则线程不安全造成超卖。加锁有悲观锁–syncronize和乐观锁,对于秒杀系统这种读多写少,需要高吞吐的场景,需要加乐观锁,乐观锁有以下几种实现:
1)基于MySQL加版本号实现:数据库表增加一个version字段,每个线程进来,首先将当前version1和amount1读出来,然后判断amount 1- buy_count是否大于0,如果大于0,再检查读出来的version与此时数据库里面的version是否一致,一致则更新数据库数据,并且version+1(其实就是CAS乐观锁的实现!)。粗体这几个步骤需要保证原子性,可通过一句sql保证原子性:
update good_info set amount=amount - buy_count, version=version + 1 where code=code1 and version=version1
ps:如果version不一致,那么将线程休眠5秒范围内的随机秒数,随机的目的是打散线程请求,尽量避免高并发,实现错峰。休眠完之后继续递归上述操作。
2)上述基于数据库实现的乐观锁,虽然简单易行,但是并发能力低,MySQL的并发能力不到1000,并且做不到分布式,即分布式下MySQL无法保证数据一致性。所以对于超大并发的场景,要用redis或者memcached等分布式缓存实现乐观锁,那么此时对应的,库存扣减是在缓存中完成的。主要 有以下两种方式:
生产上千万级秒杀系统
数据库的性能是瓶颈,所以在请求打到数据库之前,尽量拦截掉大部分流量。
在页面层,每次用户点击购买都要输入验证码,可以过滤掉很多请求。
在应用层,对于一些恶意脚本发送的大量请求,可以在用nginx进行限流:如一个ip在10秒内只能请求一次
服务层的减库存操作也要做成分布式的,所以要用redis或者memcached。并且对于上面提到的如果version不一致的情况,此时不是在Java代码里面让线程休眠这么简单,而是将请求放到mq队列里面,分批执行,达到削峰的目的。当然了,将请求放到队列里面,也可以是在操作redis库存之前,即请求先放队列里面,按顺序取出,去操作redis库存。当遇到version不一致的情况,再将请求放到另外一个队列里面…
最终到达数据库层,也要进行读写分离,分库分表等等操作
85、nginx限流
Nginx官方版本限制IP的连接和并发分别有两个模块:
limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 “leaky bucket”。
limit_req_conn 用来限制同一时间连接数,即并发限制。
86、负载均衡设计
从大的方向上讲,负载均衡分为硬负载均衡,和软负载均衡。
硬负载均衡:
硬负载均衡,也就是使用专用的负载均衡设备。主流的硬负载均衡器有如下几种:
F5:最主流的硬负载均衡器。便宜的20万以上,贵的100多万。
深信服:乞丐版低配12万元起价。
A10:基本都在100万元以上。
软负载均衡:
软软负载均衡,也就是,不使用专用的负载均衡设备,而是通过软件来实现负载均衡。常用的有如下几种:
DNS:最原始的负载均衡方式,名字就已经说明了一切,不用细说了。
LVS:最常用的软件负载均衡。我见过的国内百万级用户的架构,基本都是靠它顶的。
Nginx:也是现在流行的、常用的负载均衡方案之一。
87、LVS
LVS(Linux Virtual Server)即Linux虚拟服务器
LVS负载均衡调度算法
静态调度算法:不考虑真实服务器上的当前负载情况
动态算法,其会考虑后端服务器的实际负载情况,并选择负载小的进行请求分发
LC:Least Connection,最少连接数;此算法会根据后端每台RealServer的连接数多少来分发请求,对于连接数少的服务器,会多分发客户端请求,以尽可能利用资源占用较少的服务器
连接数计算方法:active * 256 + inactive
注解:active表示正处于HTTP正发送请求或处理请求过程中;inactive表示该连接非请求和处理过程中,只是长连接释放结算,或四次挥手阶段;
WLC:Weight Least Connection,加权最少连接数;后端Real
Server可能性能差异较大,WLC算法可以动态的获取不同服务器的真实负载情况,并调整对应的加权值,从而始终保证将请求分发到性能优异且较空闲的机器,从而提高处理效率
连接数计算方法:( active * 256 + inactive ) / weight
SED: Shortest Expect Delay,最短期望延迟;此算法是对WLC的一种改进,和WLC的不同在于其连接数计算方法的不同
SED连接数计算方法:( active + 1 ) * 256 / weight
和WLC不同在于两点:
(1)、不将非活动连接数计算在内
(2)、将active做+1处理
NQ: Never Queue,永不排队算法;此种算法,当客户端请求到达时,会首先根据SED算法进行选择一个RS,然后把请求分配给这个服务器,同时从算法列表中将此台服务器排除,下次请求到达时,只会在剩下的服务器列表中根据SED进行选择,等到每一台主机都分配到连接后,调度器此后每次都会根据SED算法在所有的服务器中进行计算选择;
LBLC:Locality-Based Least Connections,基于局部性的最少链接
基于局部性的最少链接”调度算法是针对目标IP地址的负载均衡,目前主要用于Cache集群系统。该算法根据请求的目标IP地址找出该目标IP地址最近使用的服务器,若该服务器是可用的且没有超载,将请求发送到该服务器;若服务器不存在,或者该服务器超载且有服务器处于一半的工作负载,则用“最少链接”的原则选出一个可用的服务器,将请求发送到该服务器。
总结:LVS的负载均衡算法,不同的应用场景,应选择合适的负载均衡算法,只有在充分了解了每一种算法的思想之后,才能根据自己的业务需求结合应用场景来做选择;
如果你实在不知道该如何选择,那么推荐选择WLC算法是一个不错的选择;WLC算法在实际的生产环境中,应用还是挺多的。