Java常见问题

本文详细介绍了MyBatis框架的特点、优缺点、应用场景,以及与Hibernate的对比。同时,深入探讨了Redis的数据类型、持久化机制、性能优化策略和集群方案,为读者提供了全面的数据库与缓存解决方案。

Java常见问题

一、Mybatis部分

1. 什么是 Mybatis?
  • Mybatis 是一个半 ORM(对象关系映射)框架,它内部封装了 JDBC,开发时只需要关注 SQL 语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql,可以严格控制 sql执行性能,灵活度高。
  • MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO 映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
  • 通过 xml 文件或注解的方式将要执行的各种 statement配置起来,并通过java 对象和statementsql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql并将结果映射为 java对象并返回。(从执行 sql 到返回 result 的过程)。
2. Mybaits 的优点
  • 基于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL 写在XML 里,解除 sql 与程序代码的耦合,便于统一管理;提供 XML标签,支持编写动态 SQL 语句,并可重用。
  • JDBC 相比,减少了 50%以上的代码量,消除了 JDBC 大量冗余的代码,不需要手动开关连接。
  • 很好的与各种数据库兼容(因为 MyBatis使用 JDBC 来连接数据库,所以只要JDBC 支持的数据库 MyBatis 都支持)。
  • 能够与 Spring 很好的集成。
  • 提供映射标签,支持对象与数据库的 ORM 字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
3. MyBatis 框架的缺点
  • SQL 语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
  • SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
4. MyBatis 框架适用场合
  • MyBatis 专注于 SQL 本身,是一个足够灵活的 DAO 层解决方案。
  • 对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择。
5. MyBatis与Hibernate有哪些不同?
  • Mybatishibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。
  • Mybatis直接编写原生态sql,可以严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,因为这类软件需求变化频繁,一但需求变化要求迅速输出成果。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件,则需要自定义多套sql映射文件,工作量大。
  • Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件,如果用hibernate开发可以节省很多代码,提高效率。
6. #{}和${}的区别是什么?
  • #{}是预编译处理,${}是字符串替换。
  • Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatementset方法来赋值。
  • Mybatis在处理 时 , 就 是 把 {}时,就是把 {}替换成变量的值。
  • 使用#{}可以有效的防止SQL注入,提高系统安全性。
7. 当实体类中的属性名和表中的字段名不一样,怎么办?
  • 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
<select id=”selectorder” parametertype=”int” resultetype=”me.gacl.domain.order”>
	select order_id id, order_no orderno ,order_price price 
	form orders 
	where order_id=#{id};
</select>
  • 通过<resultMap>来映射字段名和实体类属性名的一一对应的关系。
<select id="getOrder" parameterType="int" resultMap="orderresultmap">
	select * from orders where order_id=#{id}
</select>
<resultMap type=”me.gacl.domain.order” id=”orderresultmap”>
	<!-- 用 id 属性来映射主键字段 -->
	<id property=”id” column=”order_id”>
	<!-- result 属性来映射非主键字段,property 为实体类属性名,column为数据表中的属性 -->
	<result property = “orderno” column =”order_no”/>
	<result property=”price” column=”order_price” />
</reslutMap>
8. 模糊查询 like 语句该怎么写?
  • Java 代码中添加 sql 通配符。
String wildcardname = "%smi%";
List<Name> names = mapper.selectlike(wildcardname);
<select id=”selectlike”>
	select * from foo where bar like #{value}
</select>
  • sql语句中拼接通配符,会引起 sql 注入。
String wildcardname = "smi";
List<Name> names = mapper.selectlike(wildcardname);
<select id=”selectlike”>
	select * from foo where bar like "%"#{value}"%"
</select>
9. 通常一个 Xml 映射文件,都会写一个 Dao 接口与之对应,请问,这个 Dao 接口的工作原理是什么?Dao 接口里的方法,参数不同时,方法能重载吗?
  • Dao 接口即 Mapper 接口。接口的全限名,就是映射文件中的 namespace 的值;接口的方法名,就是映射文件中 MapperStatementid 值;接口方法内的参数,就是传递给 sql 的参数。
  • Mapper 接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为 key 值,可唯一定位一个 MapperStatement。在 Mybatis 中,每一个< select>< insert>< update>< delete>标签,都会被解析为一个MapperStatement对象。
  • Mapper 接口里的方法,是不能重载的,因为是使用 全限名+方法名 的保存和寻找策略。Mapper 接口的工作原理是 JDK 动态代理,Mybatis 运行时会使用 JDK动态代理为 Mapper 接口生成代理对象 proxy,代理对象会拦截接口方法,转而执行 MapperStatement所代表的 sql,然后将 sql执行结果返回。
10. Mybatis 是如何进行分页的?分页插件的原理是什么?
  • Mybatis 使用 RowBounds 对象进行分页,它是针对ResultSet 结果集执行的内存分页,而非物理分页。可以在 sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
  • 分页插件的基本原理是使用 Mybatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的 sql,然后重写 sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
11. Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
  • 使用<resultMap>标签,逐一定义数据库列名和对象属性名之间的映射关系。
  • 使用 sql列的别名功能,将列的别名书写为对象属性名。
  • 有了列名与属性名的映射关系后,Mybatis 通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。
12. 如何执行批量插入?
  • 创建一个简单的 insert 语句:
<insert id=”insertname”>
	insert into names (name) values (#{value})
</insert>
  • java代码中执行批处理插入:
List<String> names = new ArrayList();
names.add("fred");
names.add("barney");
names.add("betty");
names.add("wilma");
// 注意这里 ExecutorType.BATCH
SqlSession session = getSqlSessionFactory().openSession(ExecutorType.BATCH);
try {
    Namemapper mapper = sqlsession.getmapper(Namemapper.class);
    for (String name : names) {
        mapper.insertname(name);
    }
    sqlsession.commit();
} catch (Exception e) {
    e.printStackTrace();
    throw e;
} finally {
    sqlsession.close();
}
13. 如何获取自动生成的(主)键值?
  • insert 方法总是返回一个int值 ,这个值代表的是插入的行数。
  • 如果采用自增长策略,自动生成的键值在insert方法执行完后可以被设置到传入
    的参数对象中。
<insert id="insertName" useGeneratedKeys="true" keyProperty="id">
    insert into names (name) values (#{name})
</insert>

Names name = new Names();
name.setName("fred");
int rows = mapper.insertName(name);
//完成后,id 已经被设置到对象中
System.out.println("rows inserted = " + rows);
System.out.println("generated key value = " + name.getId());
14. 在 mapper 中如何传递多个参数?
  • DAO层的函数(实验未成功)。
<!--对应的 xml,#{0}代表接收的是 dao 层中的第一个参数,#{1}代表 dao 层中第二
    参数,更多参数一致往后加即可。-->
<select id="selectUser" resultType="com.cy.entity.User">
   select * from user
    where username=#{0} and address = #{1}
</select>
User selectUser(String name,String address);
  • 使用 @Param 注解。
<select id="selectUser2" resultType="com.cy.entity.User">
   select * from user
   where username=#{username} and address = #{address}
</select>

User selectUser2(@Param("username") String username, @Param("address") String address);
  • 多个参数封装成 map
<select id="findRolesByMap" parameterType="map" resultType="role">
    select id,role_name as roleName,note 
    from t_role
    where role_name like concat('%',#{roleName},'%')
    and note like concat('%',#{note},'%')
</select>
//测试
RoleMapper roleMapper=sqlSession.getMapper(RoleMapper.class);
Map<String,Object> paramenterMap=new HashMap<String,Object>();
parameterMap.put("roleName","1");
parameterMap.put("note","1");
List<Role> roles=roleMapper.findRolesByMap(parameterMap);
//DAO
List findRolesByMap(Map<String,Object> paramenterMap);
15. Mybatis 动态 sql 有什么用?执行原理?有哪些动态 sql?
  • Mybatis 动态 sql可以在 Xml 映射文件内,以标签的形式编写动态 sql,执行原理
    是根据表达式的值 完成逻辑判断并动态拼接 sql的功能。
  • Mybatis 提供了 9 种动态 sql 标签:trim | where | set | foreach | if | choose
    | when | otherwise | bind
16. Xml 映射文件中,除了常见的 select | insert | updae | delete 标签之外,还有哪些标签?

<resultMap><parameterMap><sql><include><selectKey>,加上动态 sql 的 9 个标签,其中<sql>sql片段标签,通过<include>标签引入 sql片段,<selectKey>为不支持自增的主键生成策略标签。

17. Mybatis 的 Xml 映射文件中,不同的 Xml 映射文件,id 是否可以重复?
  • 不同的 Xml 映射文件,如果配置了 namespace,那么id 可以重复;如果没有配置 namespace,那么id 不能重复。
  • 原因就是 namespace+id是作为 Map<String, MapperStatement>key使用的,如果没有 namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。有了 namespace,自然 id 就可以重复namespace 不同,namespace+id 自然也就不同。
18. 为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?
  • Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。
  • Mybatis在查询关联对象或关联集合对象时,需要手动编写 sql来完成,所以,称之为半自动 ORM 映射工具。
19. 一对一、一对多的关联查询 ?
<!--association 一对一关联查询 -->
<!-- 建立对应关系 -->
<resultMap type="account" id="accountMap">
    <id column="aid" property="id"/>
    <result column="uid" property="uid"/>
    <result column="money" property="money"/>
    <!-- 它是用于指定从表方的引用实体属性的 -->
    <association property="user" javaType="user">
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="sex" property="sex"/>
        <result column="birthday" property="birthday"/>
        <result column="address" property="address"/>
    </association>
</resultMap>
<!-- 配置查询所有操作-->
<select id="findAll" resultType="accountuser">
    select a.*,u.username,u.address from account a,user u where a.uid =u.id;
</select>
<!--collection 一对多关联查询 -->
<!-- 建立对应关系 -->
<resultMap type="user" id="userMap">
    <id column="id" property="id"></id>
    <result column="username" property="username"/>
    <result column="address" property="address"/>
    <result column="sex" property="sex"/>
    <result column="birthday" property="birthday"/>
    <!-- collection 是用于建立一对多中集合属性的对应关系
    ofType 用于指定集合元素的数据类型
    -->
    <collection property="accounts" ofType="account">
        <id column="aid" property="id"/>
        <result column="uid" property="uid"/>
        <result column="money" property="money"/>
    </collection>
</resultMap>
<!-- 配置查询所有操作 -->
<select id="findAll" resultMap="userMap">
    select u.*,a.id as aid ,a.uid,a.money from user u left outer join account
    a on u.id =a.uid
</select>
20. MyBatis 实现一对一有几种方式?具体怎么操作的?
  • 有联合查询和嵌套查询。
  • 联合查询是几个表联合查询,只查询一次, 通过在resultMap 里面配置 association 节点配置一对一的类就可以完成;
  • 嵌套查询是先查一个表,根据这个表里面的结果的外键 id,去再另外一个表里面查询数据,也是通过 association 配置,但另外一个表的查询通过select属性配置。
21. MyBatis 实现一对多有几种方式,怎么操作的?
  • 有联合查询和嵌套查询。
  • 联合查询是几个表联合查询,只查询一次,通过在resultMap里面的 collection 节点配置一对多的类就可以完成。
  • 嵌套查询是先查一个表,根据这个表里面的结果的外键 id,去再另外一个表里面查询数据,也是通过配置 collection,但另外一个表的查询通过 select 节点配置。
22. Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?
  • Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association 指的就是一对一,collection 指的就是一对多查询。在 Mybatis配置文件中,可以配置是否启用延迟加载 lazyLoadingEnabled=true|false
  • 它的原理是,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke()方法发现 a.getB()null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询出来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。
  • 当然了,不光是 Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。
23. Mybatis 的一级、二级缓存
  • 一级缓存: 基于 PerpetualCacheHashMap本地缓存,其存储作用域为Session,当 Session flushclose之后,该 Session 中的所有Cache就将清空,默认打开一级缓存。
  • 二级缓存与一级缓存其机制相同,默认也是采用PerpetualCacheHashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现 Serializable 序列化接口(可用来保存对象的状态),可在它的映射文件中配置<cache/>
  • 对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有select中的缓存将被 clear
24. 什么是 MyBatis 的接口绑定?有哪些实现方式?
  • 接口绑定,就是在 MyBatis 中任意定义接口,然后把接口里面的方法和 SQL 语句绑定, 我们直接调用接口方法就可以,这样比起原来了SqlSession 提供的方法我们可以有更加灵活的选择和设置。
  • 接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加上@Select@Update 等注解,里面包含 Sql 语句来绑定;另外一种就是通过 xml里面写 SQL 来绑定, 在这种情况下,要指定 xml 映射文件里面的 namespace 必须为接口的全路径名。当 Sql语句比较简单时候,用注解绑定, 当 SQL 语句比较复杂时候,用 xml 绑定,一般用 xml绑定的比较多。
24. 使用 MyBatis 的 mapper 接口调用时有哪些要求?
  • Mapper 接口方法名和 mapper.xml 中定义的每个 sqlid 相同。
  • Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sqlparameterType 的类型相同。
  • Mapper 接口方法的输出参数类型和mapper.xml中定义的每个 sqlresultType 的类型相同。
  • Mapper.xml 文件中的 namespace 即是 mapper 接口的类路径。
25. Mapper 编写有哪几种方式?
  1. 接口实现类继承 SqlSessionDaoSupport:使用此种方法需要编写mapper 接口,mapper接口实现类、mapper.xml 文件。
    a. 在 sqlMapConfig.xml 中配置 mapper.xml 的位置。

    <mappers>
    	<mapper resource="mapper.xml 文件的地址" />
    	<mapper resource="mapper.xml 文件的地址" />
    </mappers>
    

    b. 定义 mapper 接口。
    c. 实现类集成 SqlSessionDaoSupport
    d. mapper 方法中可以this.getSqlSession()进行数据增删改查。
    e. spring 配置。

    <bean id=" " class="mapper 接口的实现">
    	<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
    </bean>
    
  2. 使用 org.mybatis.spring.mapper.MapperFactoryBean
    a. 在 sqlMapConfig.xml中配置 mapper.xml的位置,如果mapper.xmlmapper接口的名称相同且在同一个目录,这里可以不用配置。

    <mappers>
    	<mapper resource="mapper.xml 文件的地址" />
    	<mapper resource="mapper.xml 文件的地址" />
    </mappers>
    

    b. 定义 mapper 接口,mapper.xml中的 namespacemapper 接口的地址,mapper接口中的方法名和 mapper.xml中的定义的 statementid 保持一致。
    c. Spring 中定义。

    <bean id="" class="org.mybatis.spring.mapper.MapperFactoryBean">
    	<property name="mapperInterface" value="mapper 接口地址" />
    	<property name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>
    
  3. 使用 mapper 扫描器。
    a. mapper.xml 文件编写

    mapper.xml 中的 namespace 为 mapper 接口的地址;
    mapper 接口中的方法名和 mapper.xml 中的定义的 statement 的 id 保持一致;
    如果将 mapper.xml 和 mapper 接口的名称保持一致则不用在 sqlMapConfig.xml中进行配置。
    

    b. 定义 mapper 接口:mapper.xml 的文件名和 mapper 的接口名称保持一致,且放在同一个目录。
    c. 配置 mapper扫描器:

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    	<property name="basePackage" value="mapper 接口包地址"></property>
    	<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>
    

    d. 使用扫描器后从 spring容器中获取 mapper 的实现对象。

27. 简述 Mybatis 的插件运行原理,以及如何编写一个插件。
  • Mybatis 仅可以编写针对 ParameterHandlerResultSetHandlerStatementHandlerExecutor 这 4 种接口的插件,Mybatis 使用 JDK 的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这 4 种接口对象的方法时,就会进入拦截方法,具体就是 InvocationHandlerinvoke()方法,当然,只会拦截那些你指定需要拦截的方法。
  • 编写插件:实现 MybatisInterceptor 接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。

二、Zookeeper部分

1. 什么是Zookeeper?
  • ZooKeeper 是一个开放源码的分布式协调服务,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
  • 分布式应用程序可以基于 Zookeeper实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。
  • Zookeeper 保证了如下分布式一致性特性:
    • ① 顺序一致性(有序性)
      从同一个客户端发起的事务请求,最终将会严格地按照其发起顺序被应用到 Zookeeper 中去。
      有序性是 Zookeeper 中非常重要的一个特性。
        所有的更新都是全局有序的,每个更新都有一个唯一的时间戳,这个时间戳称为 zxid(Zookeeper Transaction Id)。
        而读请求只会相对于更新有序,也就是读请求的返回结果中会带有这个 Zookeeper 最新的 zxid 。
      
    • ② 原子性:所有事务请求的处理结果,在整个集群中所有机器上的应用情况是一致的,即整个集群要么都成功应用了某个事务,要么都没有应用。
    • ③ 单一视图:无论客户端连接的是哪个Zookeeper 服务器,其看到的服务端数据模型都是一致的。
    • ④ 可靠性:一旦服务端成功地应用了一个事务,并完成对客户端的响应,那么该事务所引起的服务端状态变更将会一直被保留,除非有另一个事务对其进行了变更。
    • ⑤ 实时性:Zookeeper 保证在一定的时间段内,客户端最终一定能够从服务端上读取到最新的数据状态。
2. ZooKeeper 提供了什么?
  • 文件系统
  • 通知机制
3. Zookeeper 文件系统
  • Zookeeper提供一个多层级的节点命名空间(节点称为znode)。与文件系统不同的是,这些节点都可以设置关联的数据,而文件系统中只有文件节点可以存放数据而目录节点不行。
  • Zookeeper 为了保证高吞吐和低延迟,在内存中维护了这个树状的目录结构,这种特性使得 Zookeeper 不能用于存放大量的数据,每个节点的存放数据上限为1M
4. ZAB 协议?
  • ZAB 协议是为分布式协调服务 Zookeeper 专门设计的一种支持崩溃恢复的原子广播协议。
  • ZAB 协议包括两种基本的模式:崩溃恢复和消息广播。
  • 当整个 zookeeper 集群刚刚启动或者 Leader 服务器宕机、重启或者网络故障导致不存在过半的服务器与 Leader 服务器保持正常通信时,所有进程(服务器)进入崩溃恢复模式,首先选举产生新的Leader 服务器,然后集群中 Follower 服务器开始与新的Leader服务器进行数据同步,当集群中超过半数机器与该 Leader服务器完成数据同步之后,退出恢复模式进入消息广播模式,Leader 服务器开始接收客户端的事务请求生成事物提案来进行事务请求处理。
5. 四种类型的数据节点 Znode
  • PERSISTENT-持久节点:
    除非手动删除,否则节点一直存在于 Zookeeper 上。
  • EPHEMERAL-临时节点:
    临时节点的生命周期与客户端会话绑定,一旦客户端会话失效(客户端与zookeeper 连接断开不一定会话失效),那么这个客户端创建的所有临时节点都会被移除。
  • PERSISTENT_SEQUENTIAL-持久顺序节点:
    基本特性同持久节点,只是增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字。
  • EPHEMERAL_SEQUENTIAL-临时顺序节点:
    基本特性同临时节点,增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字。
6. Zookeeper Watcher 机制 – 数据变更通知
7. 客户端注册 Watcher 实现
8. 服务端处理 Watcher 实现
9. 客户端回调 Watcher
10. ACL 权限控制机制
11. Chroot 特性
12. 会话管理
13. 服务器角色
  • Leader
    • 事务请求的唯一调度和处理者,保证集群事务处理的顺序性。
    • 集群内部各服务的调度者。
  • Follower
    • 处理客户端的非事务请求,转发事务请求给 Leader 服务器。
    • 参与事务请求Proposal 的投票。
    • 参与 Leader 选举投票。
  • Observer
    • 3.0 版本以后引入的一个服务器角色,在不影响集群事务处理能力的基础上提升集群的非事务处理能力。
    • 处理客户端的非事务请求,转发事务请求给 Leader 服务器。
    • 不参与任何形式的投票。
14. Zookeeper 下 Server 工作状态

服务器具有四种状态,分别是 LOOKING、FOLLOWING、LEADING、OBSERVING。

  • LOOKING:寻找 Leader 状态。当服务器处于该状态时,它会认为当前集群中没有 Leader,因此需要进入 Leader 选举状态。
  • FOLLOWING:跟随者状态。表明当前服务器角色是 Follower
  • LEADING:领导者状态。表明当前服务器角色是 Leader
  • OBSERVING:观察者状态。表明当前服务器角色是 Observer

三、Dubbo部分

四、Elasticsearch部分

五、Memcached部分

六、Redis部分

1. 什么是 Redis?
  • Redis 是完全开源免费的,遵守 BSD 协议,是一个高性能的 key-value 数据库。

  • Redis 与其他 key - value 缓存产品有以下三个特点:

    • Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
    • Redis 不仅仅支持简单的key-value 类型的数据,同时还提供 listsetzsethash 等数据结构的存储。
    • Redis 支持数据的备份,即 master-slave 模式的数据备份。
  • Redis 优势:

    • 性能极高 – Redis 能读的速度是 110000 次/s,写的速度是 81000 次/s 。
    • 丰富的数据类型 – Redis 支持二进制案例的 Strings, Lists, Hashes, SetsOrdered Sets 数据类型操作。
    • 原子 – Redis 的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过 MULTIEXEC指令包起来。
    • 丰富的特性 – Redis 还支持 publish/subscribe, 通知, key过期等等特性。
  • Redis 与其他 key-value 存储有什么不同?

    • Redis 有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其
      他数据库的进化路径。Redis 的数据类型都是基于基本数据结构的同时对程序员透
      明,无需进行额外的抽象。
    • Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时
      需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点
      是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样 Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。
2. Redis 的数据类型?
  • Redis 支持五种数据类型:String(字符串),Hash(哈希),List(列表),
    Set(集合)及 Zset (sorted set:有序集合)。
  • 我们实际项目中比较常用的是 StringHash 如果你是 Redis 中高级用户,还需要加上下面几种数据结构 HyperLogLogGeoPub/Sub
  • 如果你说还玩过 Redis Module,像 BloomFilterRedisSearchRedis-ML,面试官得眼睛就开始发亮了。
3. 使用 Redis 有哪些好处?
  • 速度快,因为数据存在内存中,类似于 HashMapHashMap 的优势就是查找和操作的时间复杂度都是 O(1)
  • 支持丰富数据类型,支持 StringListSetZsetHash 等 。
  • 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行。
  • 丰富的特性:可用于缓存,消息,按 key 设置过期时间,过期后将会自动删除。
4. Redis 相比 Memcache 有哪些优势?
  • Memcached所有的值均是简单的字符串,redis 作为其替代者,支持更为丰富的数据类。
  • Redis 的速度比 Memcached 快。
  • Redis 可以持久化其数据。
5. Memcache 与 Redis 的区别都有哪些?
  • 存储方式 Memecache 把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。 Redis 有部份存在硬盘上,这样能保证数据的持久性。
  • 数据支持类型 Memcache 对数据类型支持相对简单。 Redis 有复杂的数据类型。
  • 使用底层模型不同 它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。 Redis 直接自己构建了 VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
6. Redis 是单进程单线程的?
  • Redis 是单进程单线程的,redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销。
7. 一个字符串类型的值能存储最大容量是多少?
  • 512M
8. Redis 的持久化机制是什么?各自的优缺点?
  1. RDB( Redis DataBase)持久化方式: 是指用数据集快照的方式(半持久化模式)记录 redis 数据库的所有键值对,在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。
    优点:

    • 只有一个文件 dump.rdb,方便持久化。
    • 容灾性好,一个文件可以保存到安全的磁盘。
    • 性能最大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO最大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis的高性能。
    • 相对于数据集大时,比 AOF 的启动效率更高。

    缺点:

    • 数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候。
  2. AOF(Append-only file)持久化方式: 是指所有的命令行记录以 redis 命令请求协议的格式完全持久化存储保存为 aof 文件。
    优点:

    • 数据安全,aof 持久化可以配置 appendfsync 属性,有 always,每进行一次命令操作就记录到 aof 文件中一次。
    • 通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof工具解决数据一致性问题。
    • AOF 机制的 rewrite 模式。AOF 文件没被 rewrite之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的 flushall)。

    缺点:

    • AOF 文件比 RDB文件大,且恢复速度慢。
    • 数据集大的时候,比 rdb 启动效率低。
9. Redis 常见性能问题和解决方案
10. redis 过期键的删除策略?
11. Redis 的回收策略(淘汰策略)?
12. 为什么 Redis 需要把所有数据放到内存中?
  • Redis 为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以 redis 具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘 I/O 速度为严重影响 redis 的性能。在内存越来越便宜的今天,redis 将会越来越受欢迎。如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。
13. Redis 的同步机制了解么?
  • Redis 可以使用主从同步,从从同步。第一次同步时,主节点做一次 bgsave,并同时将后续修改操作记录到内存 buffer,待完成后将 rdb 文件全量同步到复制节点,复制节点接受完成后将 rdb镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。
14. Pipeline 有什么好处,为什么要用 pipeline?
15. 是否使用过 Redis 集群,集群的原理是什么?
  • Redis Sentinal 着眼于高可用,在 master 宕机时会自动将 slave 提升为master,继续提供服务。
  • Redis Cluster 着眼于扩展性,在单个 redis 内存不足时,使用 Cluster 进行分片存储。
16. Redis 集群方案什么情况下会导致整个集群不可用?
  • ABC 三个节点的集群,在没有复制模型的情况下,如果节点 B 失败了,那么整个集群就会以为缺少 5501-11000 这个范围的槽而不可用。
17. Redis 支持的 Java 客户端都有哪些?官方推荐用哪个?
  • RedissonJedislettuce 等等,官方推荐使用 Redisson
18. Jedis 与 Redisson 对比有什么优缺点?
  • JedisRedisJava 实现的客户端,其 API 提供了比较全面的 Redis 命令的支持。
  • Redisson 实现了分布式和可扩展的 Java 数据结构,和 Jedis 相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等 Redis 特性。
  • Redisson 的宗旨是促进使用者对 Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。
19. Redis 如何设置密码及验证密码?
  • 设置密码:config set requirepass 123456
  • 授权密码:auth 123456
20. 说说 Redis 哈希槽的概念?
  • Redis集群没有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽,集群的每个节点负责一部分 hash 槽。
21. Redis 集群的主从复制模型是怎样的?
  • 为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有 N-1 个复制品。
22. Redis 集群会有写操作丢失吗?为什么?
  • Redis 并不能保证数据的强一致性,这意味这在实际中集群在特定的条件下可能会丢失写操作。
23. Redis 集群之间是如何复制的?
  • 异步复制

七、MySQL部分

1. MySQL 中有哪几种锁?
  • 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最
    高,并发度最低。
  • 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最
    低,并发度也最高。
  • 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表
    锁和行锁之间,并发度一般。
2. MySQL 中有哪些不同的表格?

共有 5 种类型的表格:

  • MyISAM
  • Heap
  • Merge
  • INNODB
  • ISAM
3. 简述在 MySQL 数据库中 MyISAM 和 InnoDB 的区别

MyISAM

  • 不支持事务,但是每次查询都是原子的;
  • 支持表级锁,即每次操作是对整个表加锁;
  • 存储表的总行数;
  • 一个MYISAM 表有三个文件:索引文件、表结构文件、数据文件;
  • 采用非聚集索引,索引文件的数据域存储指向数据文件的指针。辅索引与主索引基本一致,但是辅索引不用保证唯一性。
    InnoDb
  • 支持 ACID 的事务,支持事务的四种隔离级别;
  • 支持行级锁及外键约束:因此可以支持写并发;
  • 不存储总行数;
  • 一个 InnoDb 引擎存储在一个文件空间(共享表空间,表大小不受操作系统控制,一个表可能分布在多个文件里),也有可能为多个(设置为独立表空,表大小受操作系统文件大小限制,一般为 2G),受操作系统文件大小的限制;
  • 主键索引采用聚集索引(索引的数据域存储数据文件本身),辅索引的数据域存储主键的值;因此从辅索引查找数据,需要先通过辅索引找到主键值,再访问辅索引;最好使用自增主键,防止插入数据时,为维持 B+树结构,文件的大调整。
4. MySQL 中 InnoDB 支持的四种事务隔离级别名称,以及逐级之间的区别?

SQL 标准定义的四个隔离级别为:

  • read uncommited :读到未提交数据。
  • read committed:脏读,不可重复读。
  • repeatable read:可重读。
  • serializable :串行化。
5. CHAR 和 VARCHAR 的区别?
  • CHARVARCHAR 类型在存储和检索方面有所不同
  • CHAR 列长度固定为创建表时声明的长度,长度值范围是 1 到 255 当 CHAR值被存储时,它们被用空格填充到特定长度,检索 CHAR 值时需删除尾随空格。
6. myisamchk 是用来做什么的?
  • 它用来压缩 MyISAM 表,这减少了磁盘或内存使用。
  • MyISAM StaticMyISAM Dynamic 有什么区别?
    • MyISAM Static 上的所有字段有固定宽度。动态 MyISAM 表将具有像 TEXTBLOB 等字段,以适应不同长度的数据类型。
    • MyISAM Static 在受损情况下更容易恢复。
7. 主键和候选键有什么区别?
  • 表格的每一行都由主键唯一标识,一个表只有一个主键。
  • 主键也是候选键。按照惯例,候选键可以被指定为主键,并且可以用于任何外键
    引用。
8. 如果一个表有一列定义为 TIMESTAMP,将发生什么?
  • 每当行被更改时,时间戳字段将获取当前时间戳。
  • 列设置为 AUTO INCREMENT 时,如果在表中达到最大值,会发生什么情况?
    • 它会停止递增,任何进一步的插入都将产生错误,因为密钥已被使用。
  • 怎样才能找出最后一次插入时分配了哪个自动增量?
    • LAST_INSERT_ID 将返回由 Auto_increment 分配的最后一个值,并且不需要指定表名称。
9. 你怎么看到为表格定义的所有索引?
  • 索引是通过以下方式为表格定义的:SHOW INDEX FROM <tablename>;
10. LIKE 声明中的%和_是什么意思?
  • 对应于 0 个或更多字符,_只是LIKE 语句中的一个字符。
  • 如何在 UnixMySQL 时间戳之间进行转换?
    • UNIX_TIMESTAMP 是从 MySQL 时间戳转换为 Unix 时间戳的命令。
    • FROM_UNIXTIME 是从 Unix时间戳转换为 MySQL 时间戳的命令。
11. 列对比运算符是什么?
  • 在 SELECT 语句的列比较中使用=,<>,<=,<,> =,>,<<,>>,<=>,AND,OR 或 LIKE 运算符。
12. BLOB 和 TEXT 有什么区别?
  • BLOB 是一个二进制对象,可以容纳可变数量的数据。TEXT 是一个不区分大小写的 BLOB
  • BLOBTEXT 类型之间的唯一区别在于对 BLOB 值进行排序和比较时区分大小写,对 TEXT 值不区分大小写。

八、Java并发编程1

九、Java并发编程2

十、Java基础1

十一、Java基础2

十二、Spring部分1

十三、Spring部分2

十四、微服务部分

十五、Linux部分

十六、SpringBoot部分

十七、SpringCloud部分

十八、RabbitMQ部分

十九、Kafka部分

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值