Spring Boot中starter到底是什么?
spring-boot-starter-parent有什么用?
定义了Java编译版本为1.8 。 使用UTF-8格式编码。 继承自spring-boot-dependencies,这个里边定义了依赖的版本,也正是因为继承了这个依赖,所以我们在写依赖时才不需要写版本号。 执行打包操作的配置。 自动化的资源过滤。 自动化的插件配置。 针对application.properties和application.yml的资源过滤,包括通过 profile定义的不同环境的配置文件,例如applicationdev.properties和 application-dev.yml。
Spring Boot打成的jar和普通的jar有什么区别 ?
<select id="listUserLikeUsername" resultType="com.jourwon.pojo.User"><bind name="pattern" value="'%' + username + '%'" />select id,sex,age,username,password from personwhere username LIKE #{pattern}</select>
public User selectUser(String name, int deptId);<select id="selectUser" resultMap="UserResultMap">select * from userwhere user_name = #{0} and dept_id = #{1}</select>
public User selectUser(@Param("userName") String name,@Param("deptId") int deptId);<select id="selectUser" resultMap="UserResultMap">select * from userwhere user_name = #{userName} and dept_id = #{deptId}</select>
public User selectUser(Map<String, Object> params);<select id="selectUser" parameterType="java.util.Map" resultMap="UserResultMap">select * from userwhere user_name = #{userName} and dept_id = #{deptId}</select>
public User selectUser(User user);<select id="selectUser" parameterType="com.jourwon.pojo.User" resultMap="UserResultMap">select * from userwhere user_name = #{userName} and dept_id = #{deptId}</select>
Hot key
问题描述:
对于大多数互联网系统,数据是分冷热的。在突发事件发生时,大量用户同时去访问突发热点信息( Hot key ),这个突发热点信息所在的缓存节点就很容易出现过载和卡顿现象,甚至会被Crash。
业务场景:
明星结婚、离婚、出轨这种特殊突发事件,奥运、春节这些重大活动或节日,秒杀、双12、618 等线上促销活动。
解决方案:
1.利用大数据找出Hot key,将这些Hotkey进行分散处理,比如一个Hot key名字叫hotkey,可以被分散为hotkey#1、hotkey#2、hotkey#3,……hotkey#n,这n个key分散存在多个缓存节点,然后 client端请求时,随机访问其中某个后缀的hotkey,这样就可以把热key 的请求打散,避免一个缓存节点过载。
2. key的名字不变,对缓存提前进行多副本+多级结合的缓存架构设计。
3. 如果热key较多,还可以通过监控体系对缓存的SLA实时监控,通过快速扩容来减少Hot key的冲击。
4. 业务端还可以使用本地缓存,将这些Hot key记录在本地缓存,来减少对远程缓存的冲击。
Big key
问题描述:
在缓存访问时,部分Key的Value过大,读写、加载易超时的现象。
业务场景:
互联网系统中需要保存用户最新1万个粉丝的业务,一个用户个人信息缓存,包括基本资料、关系图谱计数、发feed统计等,微博用户发表1千字甚至更长的微博内容。
解决方案
1.如果数据存在memcached中,可以设计一个缓存阀值,当value的长度超过阀值,则对内容启用压缩。
2.如果数据存在Redis中,对Big key拆分,如下big list:list1、list2、...listN;big hash:可以做二次的hash,例如hash%100;日期:key20190320、key20190321、key_201903223。对Big key设置较长的过期时间,缓存内部在淘汰key时,同等条件下,尽量不淘汰这些大 key。
<mappers><mapper resource="mapper.xml 文件的地址" /><mapper resource="mapper.xml 文件的地址" /></mappers>
<bean id=" " class="mapper接口的实现"><property name="sqlSessionFactory" ref="sqlSessionFactory"></property></bean>
<mappers><mapper resource="mapper.xml 文件的地址" /><mapper resource="mapper.xml 文件的地址" /></mappers>
<bean id="" class="org.mybatis.spring.mapper.MapperFactoryBean"><property name="mapperInterface" value="mapper接口地址" /><property name="sqlSessionFactory" ref="sqlSessionFactory" /></bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="mapper接口包地址"></property><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/></bean>
性质一:节点是红色或者是黑色;在树里面的节点不是红色的就是黑色的,没有其他颜色。 性质二:根节点是黑色;根节点总是黑色的。它不能为红色。 性质三:每个叶节点(NIL或空节点)是黑色; 性质四:每个红色节点的两个子节点都是黑色的(也就是说不存在两个连续的红色节点);就是连续的两个节点不能是连续的红色,连续的两个节点的意思就是父节点与子节点不能是连续的红色。 性质五:从任一节点到其每个叶节点的所有路径都包含相同数目的黑色节点。从根节点到每一个NIL节点的路径中,都包含了相同数量的黑色节点。
bootstrap (. yml 或者 . properties):由父ApplicationContext 加载的,比applicaton优先加载,配置在应用程序上下文的引导阶段生效。一般来说我们在Spring Cloud Config或者Nacos中会用到它。且 boostrap里面的属性不能被覆盖;
application (. yml 或者 . properties):由ApplicatonContext加载,用于 spring boot项目的自动化配置。
21:rdd怎么区分宽依赖和窄依赖
宽依赖:父RDD的分区被子RDD的多个分区使用sortByKey等操作会产生宽依赖,会产生 shuffle;例如 groupByKey、reduceByKey;
窄依赖:父RDD的每个分区都只被子RDD的一个分区使用;例如 map、filter、union等操作会产生窄依赖。
22:spark streaming读取kafka数据的两种方式
这两种方式分别是:
1 Receiver-base
使用Kafka的高层次Consumer API来实现。receiver从Kafka中获取的数据都存储在Spark Executor的内存中,然后Spark Streaming启动的job会去处理那些数据。然而,在默认的配置下,这种方式可能会因为底层的失败而丢失数据。如果要启用高可靠机制,让数据零丢失,就必须启用Spark Streaming 的预写日志机制(Write Ahead Log,WAL)。该机制会同步地将接收到的Kafka数据写入分布式文件系统(比如 HDFS)上的预写日志中。所以,即使底层节点出现了失败,也可以使用预写日志中的数据进行恢复。
2 Direct
Spark1.3中引入Direct方式,用来替代掉使用Receiver接收数据,这种方式会周期性地查询Kafka,获得每个topic+partition的最新的offset,从而定义每个batch的offset的范围。当处理数据的job启动时,就会使用Kafka的简单 consumer api来获取Kafka指定offset范围的数据。
3 Kafka最核心的思想是使用磁盘,而不是使用内存,可能所有人都会认为,内存的速度一定比磁盘快,我也不例外。在看了Kafka 的设计思想,查阅了相应资料再加上自己的测试后, 发现磁盘的顺序读写速度和内存持平。
而且Linux对于磁盘的读写优化也比较多,包括read-ahead和write-behind,磁盘缓存等。如果在内存做这些操作的时候,一个是JAVA对象的内存开销很大,另一个是随着堆内存数据的增多,JAVA的GC时间会变得很长,使用磁盘操作有以下几个好处:
磁盘缓存由Linux系统维护,减少了程序员的不少工作。磁盘顺序读写速度超过内存随机读写。
JVM的GC效率低,内存占用大。使用磁盘可以避免这一问题。系统冷启动后,磁盘缓存依然可用。
23:怎么解决 kafka 的数据丢失
producer端:
宏观上看保证数据的可靠安全性,肯定是依据分区数做好数据备份,设立副本数。
broker端:
topic设置多分区,分区自适应所在机器,为了让各分区均匀分布在所在的 broker中,分区数要大于broker数。分区是kafka进行并行读写的单位,是提升kafka速度的关键。
Consumer端
consumer端丢失消息的情形比较简单:如果在消息处理完成前就提交了offset,那么就有可能造成数据的丢失。由于Kafka consumer默认是自动提交位移的,所以在后台提交位移前一定要保证消息被正常处理了,因此不建议采用很重的处理逻辑,如果处理耗时很长, 则建议把逻辑放到另一个线程中去做。为了避免数据丢失,现给出两点建议:
1)enable.auto.commit=false 关闭自动提交位移
2)在消息被完整处理之后再手动提交位移
24:fsimage和edit的区别?
大家都知道namenode与secondary namenode的关系,当他们要进行数据同步时叫做checkpoint时就用到了fsimage与edit,fsimage是保存最新的元数据的信息,当fsimage数据到一定的大小是会去生成一个新的文件来保存元数据的信息,这个新的文件就是edit,edit会回滚最新的数据。
25:列举几个配置文件优化?
1)Core-site.xml文件的优化
a、fs.trash.interval,默认值: 0;说明: 这个是开启hdfs文件删除自动转移到垃圾箱的选项,值为垃圾箱文件清除时间。一般开启这个会比较好,以防错误删除重要文件。单位是分钟。
b、dfs.namenode.handler.count,默认值:10;说明:hadoop系统里启动的任务线程数,这里改为40,同样可以尝试该值大小对效率的影响变化进行最合适的值的设定。
c、mapreduce.tasktracker.http.threads,默认值:40;说明:map和reduce是通过http进行数据传输的,这个是设置传输的并行线程数。
26:datanode首次加入cluster的时候,如果log报告不兼容文件版本,那需要namenode执行格式化操作,这样处理的原因是?
1)这样处理是不合理的,因为那么namenode格式化操作,是对文件系统进行格式化, namenode格式化时清空dfs/name两个目录下的所有文件,之后,会在目录dfs.name.dir下创建文件。
2)文本不兼容,有可能是namenode与datanode的数据里的namespaceID、 clusterID不一致,找到两个ID 位置,修改为一样即可解决。
27:MapReduce中排序发生在哪几个阶段?这些排序是否可以避免?为什么?
1)一个MapReduce作业由Map阶段和Reduce阶段两部分组成,这两阶段会对数据排序,从这个意义上说,MapReduce框架本质就是一个Distributed Sort。
2)在Map阶段,Map Task会在本地磁盘输出一个按照key排序(采用的是快速排序)的文件(中间可能产生多个文件,但最终会合并成一个),在Reduce阶段,每个Reduce Task会对收到的数据排序,这样,数据便按照Key分成了若干组,之后以组为单位交给reduce()处理。
3)很多人的误解在Map阶段,如果不使用Combiner便不会排序,这是错误的,不管你用不用Combiner,Map Task均会对产生的数据排序(如果没有 Reduce Task,则不会排序,实际上Map阶段的排序就是为了减轻Reduce端排序负载)。
4)由于这些排序是MapReduce自动完成的,用户无法控制,因此,在 hadoop 1.x中无法避免,也不可以关闭,但hadoop2.x是可以关闭的。
28:hadoop 的优化?
1)优化的思路:
可以从配置文件和系统以及代码的设计思路来优化 ;
2)配置文件的优化:
调节适当的参数,在调参数时要进行测试 ;
3)代码的优化:
combiner的个数尽量与reduce的个数相同,数据的类型保持一致,可以减少拆包与封包的进度;
4)系统的优化:
可以设置linux系统打开最大的文件数预计网络的带宽MTU的配置 ;
5)为job添加一个Combiner,可以大大的减少shuffer阶段的maoTask拷贝过来给远程的reduce task的数据量,一般而言combiner与reduce相同。
6)在开发中尽量使用stringBuffer而不string,string 的模式是read-only的,如果对它进行修改,会产生临时的对象,而stringBuffer是可修改的,不会产生临时对象。
7)修改一下配置:
以下是修改mapred-site.xml 文件;
a、修改最大槽位数:槽位数是在各个tasktracker上的mapred-site.xml上设置的, 默认都是2;
<property><name>mapred.tasktracker.map.tasks.maximum</name><value>2</value></property><property><name>mapred.tasktracker.reduce.tasks.maximum</name> <value>2</value></property>
b、调整心跳间隔:集群规模小于300时,心跳间隔为300毫秒;
c、启动带外心跳mapreduce.tasktracker.outofband.heartbeat默认是false;
d、配置多块磁盘mapreduce.local.dir;
e、配置RPC hander数目,mapred.job.tracker.handler.count 默认是10,可以改成 50,根据机器的能力;
f、配置HTTP线程数目tasktracker.http.threads 默认是40,可以改成100根据机器的能力;
g、选择合适的压缩方式,以snappy为例:
<property><name>mapred.compress.map.output</name><value>true</value></property><property><name>mapred.map.output.compression.codec</name><value>org.apache.hadoop.io.compress.SnappyCodec</value></property>
29:设计题
采集nginx产生的日志,日志的格式为user ip time url htmlId每天产生的文件的数据量上亿条,请设计方案把数据保存到HDFS上,并提供一下实时查询的功能(响应时间小于 3s)
A、某个用户某天访问某个URL的次数
B、某个URL某天被访问的总次数
实时思路:
使用Logstash + Kafka + Spark-streaming + Redis + 报表展示平台 ;
离线的思路:
Logstash + Kafka + Elasticsearch + Spark-streaming + 关系型数据库;A、B、数据在进入到Spark-streaming中进行过滤,把符合要求的数据保存到 Redis 中。
30:有10个文件,每个文件1G,每个文件的每一行存放的都是用户的 query,每个文件的query都可能重复。要求你按照query的频度排序。还是典型的TOP K算法。
解决方案如下:
1)方案 1:
顺序读取10个文件,按照 hash(query)%10 的结果将query写入到另外10个文件中。这样新生成的文件每个的大小大约也1G(假设hash函数是随机的)。找 一台内存在2G左右的机器,依次对用hash_map(query, query_count)来统计每个query出现的次数。利用快速/堆/归并排序按照出现次数进行排序。将排序好的query和对应的query_cout输出到文件中。这样得到了10个排好序的文件。对这10个文件进行归并排序(内排序与外排序相结合)。
2)方案 2:
一般query的总量是有限的,只是重复的次数比较多而已,可能对于所有的 query,一次性就可以加入到内存了。这样,我们就可以采用trie 树/hash_map等直接来统计每 个query出现的次数,然后按出现次数做快速/堆/归并排序就可以了。
3)方案 3:
与方案 1 类似,但在做完hash,分成多个文件后,可以交给多个文件来处理,采用分 布式的架构来处理(比如MapReduce),最后再进行合并。




