java 重点知识

J2se部分

1、重写与重载的区别:

重载:在同一个类中出现的方法名相同、参数列表不同(包括个数,类型,顺序)的行为。
重写:两个类中。子类继承父类,方法名、参数必须统一,修饰符要大于或等于父类的访问修饰符。

2、集合类相关

Util包中的相关两个接口 collection/map ,单纯只列出其熟悉的常用的子类来介绍
Collection
-----List
----ArrayList (添加,查询多时的选择)
由数组实现的List。它允许对元素进行快速随机访问,但是向List中间插入与移除元素的速度很慢。ArrayList,而不是用来插入和删除元素,因为这比LinkedList开销要大很多。
----LinkedList (插入与删除多时的选择)
对顺序访问进行了优化,向List中间插入与删除得开销不大,随机访问则相对较慢(可用ArrayList代替)。它具有方法addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast()等方法
-----Set(存入Set的每个元素必须是唯一的,这也是与List不同的,因为Set不保存重复元素)
----HashSet
HashSet能快速定位一个元素,存入HashSet的对象必须定义hashCode()
----TreeSet
保持次序的Set,底层为树结构。使用它可以从Set中提取有序的序列
Map(键值对key-value形式存储,key不能重复,value可以)
-----hashMap
基于哈希表的 Map 接口的实现(保证键的唯一性)
-----hashTable
hashMap key/value允许null,但是hashTable不允许存在null值,hashTable是同步,是线程安全的,推荐使用ConcurrentHashMap。
-----TreeMap
是一个有序的key-value集合,它是通过红黑树实现的,支持序列化

3、多线程相关
1)一个进程中存在多个线程在运行时,则称为多线程
2)线程开启方式 start(),jvm调用run()方法则会正式开启运行
3)两种多线程的实现方式,一是继承thread方法,二是实现Runnable接口
4)线程安全的产生:当多个线程对同一个资源进行访问时会出现线程问题。
5)解决线程安全的 方法:1、同步代码块(容易产生死锁问题)。2、同步函数  (关键字Synchronized)
4、线程池相关之ThreadPoolExecutor
线程池优点:线程池具有提高系统性能的优点,因为创建线程和清除线程的开销比较大。
ThreadPoolExecutor的常用参数。

1)corePoolSize: 线程池维护线程的核心数量。
2)maximumPoolSize:线程池维护线程的最大数量 。
3)keepAliveTime: 线程池维护线程所允许的空闲时间。
4)unit: 线程池维护线程所允许的空闲时间的单位,与keepAliveTime配合使用 。
5)workQueue: 线程池所使用的缓冲队列。
6)handler: 线程池对拒绝任务的处理策略。
如果线程池中运行的线程 小于corePoolSize ,即使线程池中的线程都处于空闲状态,也要 创建新的线程 来处理被添加的任务。
如果线程池中运行的线程大于等于corePoolSize,但是缓冲队列 workQueue未满 ,那么任务被放入缓冲队列 。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满(即无法将请求加入队列 ),并且线程池中的数量小于maximumPoolSize,建新的线程 来处理被添加的任务。超过空闲时间,该创建的线程就会终止。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量大于或等于maximumPoolSize ,那么通过 handler 所指定的策略来处理此任务(多半指向异常处理)
从顶层到底层:
Excutor ExcutorServerAbstracExcutorThreadPoolExcutor.
重点说明三种workQueue类型
1) SynchronousQueue ,该队列为默认队列。无界的无缓冲队列。即线程先new线程,当达到corePoolSize数量,则会进入queue队列中,如果队列满 了,则会继续new,如果达到maximumPoolSize,则会执行异常策略。该队列需要maximumPoolSize最好是无界的,否则爆缸。
2) LinkedBlockingQueue ,无界的缓冲队列。相比SynchronousQueue它存在一个缓冲区,只有当缓冲区容量满了以后,才会阻塞队列,可以高效的处理并发数据。
3) ArrayBlockingQueue,有界的缓冲队列,采用分离锁的技术保证生产者和消费者的并行运行。

5 、java 8新特性
最常用三个

1)、接口中可以存在一个非抽象的默认方法,用default关键字,且该方法不用要求实现该接口必须实现该方法。
啊 private interface Defaulable {
// Interfaces now allow default methods, the implementer may or
// may not implement (override) them.
default String notRequired() {
return “Default implementation”;

2)、lambda表达式
Lambda表达式(也称为闭包)是Java 8中最大和最令人期待的语言改变。它允许我们将函数当成参数传递给某个方法,或者把代码本身当作数据处理。 Lambda常用作取代匿名内部类。
简化为lambda则可以表述为:
Lambda表达式使用模式 参数 表达式
Arrays.asList( “a”, “b”, “d” ).forEach( e -> System.out.println( e ) );
Arrays.asList( “a”, “b”, “d” ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );

3)、新增的Stream API
1、Stream是元素的集合,这点让Stream看起来用些类似Iterator;
2、可以支持顺序和并行的对原Stream进行汇聚的操作;
大家可以把Stream当成一个高级版本的Iterator。原始版本的Iterator,用户只能一个一个的遍历元素并对其执行某些操作;高级版本的Stream,用户只要给出需要对其包含的元素执行什么操作,比如“过滤掉长度大于10的字符串”、“获取每个字符串的首字母”等,具体这些操作如何应用到每个元素上,就给Stream就好了!
Stream中存在很多api对元素进行操作,从而提供更加方便快捷的元素操作指令。
(Stream常用于与Lambda表达式结合使用)
Stream的常用方法 :
distinct: 对于Stream中包含的元素进行去重操作(去重逻辑依赖元素的equals方法),新生成的Stream中没有重复的元素;
filter: 对于Stream中包含的元素使用给定的过滤函数进行过滤操作,新生成的Stream只包含符合条件的元素;
map: 对于Stream中包含的元素使用给定的转换函数进行转换操作,新生成的Stream只包含转换生成的元素;这个方法有三个对于原始类型的变种方法,分别是:mapToInt,mapToLong和mapToDouble。这三个方法也比较好理解,比如mapToInt就是把原始Stream转换成一个新的Stream,这个新生成的Stream中的元素都是int类型。之所以会有这样三个变种方法,可以免除自动装箱/拆箱的额外消耗;
limit: 对一个Stream进行截断操作,获取其前N个元素,如果原Stream中包含的元素个数小于N,那就获取其所有的元素;
skip: 返回一个丢弃原Stream的前N个元素后剩下元素组成的新Stream,如果原Stream中包含的元素个数小于N,那么返回空Stream;
peek: 生成一个包含原Stream的所有元素的新Stream,同时会提供一个消费函数(Consumer实例),新Stream每个元素被消费的时候都会执行给定的消费函数;

给定一个Integer类型的List,获取其对应的Stream对象,然后进行过滤掉null,再去重,再每个元素乘以2,再每个元素被消费的时候打印自身,在跳过前两个元素,最后去前四个元素进行加和运算

常用框架部分

1、 Spring相关
spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和Struts框架,ibatis框架等组合使用。
1) IoC(Inversion of Control)控制反转,对象创建责任的反转,在spring中BeanFacotory是IoC容器的核心接口,负责实例化,定位,配置应用程序中的对象及建立这些对象间的依赖。XmlBeanFacotory实现BeanFactory接口,通过获取xml配置文件数据,组成应用对象及对象间的依赖关系。
spring中有三种注入方式,一种是set注入(不推荐),一种是接口注入(比价常用),另一种是构造方法注入(死应用)。
Set注入
构造器注入

  1.    <bean id="userManager" class="com.tgb.spring.manager.UserManagerImpl">        
    
  2.           <constructor-arg ref="userDao4Oracle"/>    
    
  3.      </bean>    
    
  4. public class UserManagerImpl implements UserManager{

  5.      private UserDao userDao;    
    
  6.      //使用构造方式赋值    
    
  7.     public UserManagerImpl(UserDao userDao) {    
    
  8.         this.userDao = userDao;    
    
  9.     }    
    
  10.     @Override    
    
  11.     public void addUser(String userName, String password) {    
    
  12.         userDao.addUser(userName, password);    
    
  13.     }    
    
  14. }    
    

接口注入

  1. public class ClassA {
  2. private InterfaceB clzB;
  3. public void doSomething() {
  4.  Ojbect obj = Class.forName(Config.BImplementation).newInstance();  
    
  5.  clzB = (InterfaceB)obj;  
    
  6.  clzB.doIt();   
    
  7. }
  8. ……
  9. }
    其中加载clzB接口时,预先在配置文件中设定的实现类的类名(Config.BImplementation),动态加载实现类,然后强制转化为clzB
    从而实现注入。

AOP面向切面
当多个业务需要一个共同的操作或者代码块时,与其往每个业务中添加同样的代码,不如写一遍这个代码,然后让多个业务使用这个代码,这就是面向切面的思想。
AOP技术利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
Spring创建AOP代理的两种模式
1)默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了
timeHandler类作为helloWorldImpl1与helloWorldImpl2的切面,当helloWorldImpl1与helloWorldImpl2方法执行时,timeHandler的addAllMethod就会执行。
2)当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB
高版本的Spring会自动选择是使用动态代理还是CGLIB生成代理内容,当然我们也可以强制使用CGLIB生成代理,那就是aop:config里面有一个"proxy-target-class"属性,这个属性值如果被设置为true,那么基于类的代理将起作用,如果proxy-target-class被设置为false或者这个属性被省略,那么基于接口的代理将起作用

注解
使用注解编程,主要是为了替代xml文件,使开发更加快速。但是,xml文件的使用就是解决修改程序修改源代码,现在又不去使用xml文件,那么不就违背了开闭原则了么,得确是。不过么,注解也有注解的好,使用注解就不用配置那么多的xml文件啦,最重要的是开发效率高。。
在没有使用注解时,spring框架的配置文件applicationContext.xml文件中需要配置很多的标签,用来声明类对象。使用注解,则不必在配置文件中添加标签。
例如@AutoWired注解则可以代替xml配置的set注入,构造器注入等,极大的优化了开发效率。

REST

REST(REpresentational State Transfer )即一种架构风格(表现层状态转移)就是选择通过使用http协议和uri利用client/server 模型对资源进行CURD.
其中Resource是指统一资源 Representational值资源表现层 (xml格式的。或者html格式的)
State Transfer指状态转移。服务器在表现层(html里)中加入uri超链接将各种之后状态加入就是表现层状态传输

REST的优点:
1、 客户端-服务器端分离 提高了用户界面的便携性(操作简单)
2、 REST的无状态性 从客户端的每个请求要包含服务器所需要的所有信息
优点:提高了可见性(可以单独考虑每个请求)
提高了可靠性(更容易从局部故障中修复)
提高了可拓展性(降低了服务器资源使用)
3、 缓存 服务器返回信息被标记是否可以缓存,如果缓存,客户端可能会重用之前的信息发送请求。
优点:减少交互次数 减少交互的平均延迟
4 、分层系统 系统组件不需要知道与他交流组件之外的事情,封装服务,引入中间层
优点:限制了系统的复杂性
5、 统一接口 优点:提高交互的可见性 鼓励单独改善组件
REST描述的是在网络中client和server的一种交互形式;REST本身不实用,实用的是如何设计RESTful API(REST风格的网络接口)API中,URL中只实用名词来指定资源,原则上不使用动词来指定资源。

SpringMVC对restful服务有着良好的支持
所涉及到的注解:
@RequestMapping @PathVariable @ResponseBody

JMS相关之activeMQ
Jms(java Message Server)java消息服务,是一个java标准,定义了使用消息代理的通用API,Spring通过基于模板的抽象为JMS提供了支持,而aciveMQ是目前spring支持最良好JMS异步消息传递选择。
第一步:配置连接工厂:

第二步:配置生产者:
生产者负责产生消息并发送到JMS服务器。但是我们要怎么进行消息发送呢?通常是利用Spring为我们提供的JmsTemplate类来实现的,所以配置生产者其实最核心的就是配置消息发送的JmsTemplate。对于消息发送者而言,它在发送消息的时候要知道自己该往哪里发,为此,我们在定义JmsTemplate的时候需要注入一个Spring提供的ConnectionFactory对象。
在利用JmsTemplate进行消息发送的时候,我们需要知道发送哪种消息类型:一个是点对点的ActiveMQQueue,另一个就是支持订阅/发布模式的ActiveMQTopic。
第三步:配置目的地
生产者往指定目的地Destination发送消息后,接下来就是消费者对指定目的地的消息进行消费了。那么消费者是如何知道有生产者发送消息到指定目的地Destination了呢?每个消费者对应每个目的地都需要有对应的MessageListenerContainer。对于消息监听容器而言,除了要知道监听哪个目的地之外,还需要知道到哪里去监听,也就是说它还需要知道去监听哪个JMS服务器,通过配置MessageListenerContainer的时候往里面注入一个ConnectionFactory来实现的。所以我们在配置一个MessageListenerContainer的时候有三个属性必须指定:一个是表示从哪里监听的ConnectionFactory;一个是表示监听什么的Destination;一个是接收到消息以后进行消息处理的MessageListener。

2、 Hibernate相关
hibernate是一个开源框架,它是对象关联关系映射的框架,它对JDBC做了轻量级的封装,而我们java程序员可以使用面向对象的思想来操纵数据库。
hibernate核心接口
session:负责被持久化对象CRUD操作
sessionFactory:负责初始化hibernate,创建session对象
configuration:负责配置并启动hibernate,创建SessionFactory
Transaction:负责事物相关的操作
Query和Criteria接口:负责执行各种数据库查询

hibernate工作原理:
1.通过Configuration config = new Configuration().configure();//读取并解析hibernate.cfg.xml配置文件
2.由hibernate.cfg.xml中的读取并解析映射信息
3.通过SessionFactory sf = config.buildSessionFactory();//创建SessionFactory
4.Session session = sf.openSession();//打开Sesssion
5.Transaction tx = session.beginTransaction();//创建并启动事务Transation
6.persistent operate操作数据,持久化操作
7.tx.commit();//提交事务
8.关闭Session
9.关闭SesstionFactory

Hibernate是如何延迟加载?get与load的区别

  1. 对于Hibernate get方法,Hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查询数据库,数据 库中没有就返回null。这个相对比较简单,也没有太大的争议。主要要说明的一点就是在这个版本(bibernate3.2以上)中get方法也会查找二级缓存!
  2. Hibernate load方法加载实体对象的时候,根据映射文件上类级别的lazy属性的配置(默认为true),分情况讨论:
    (1)若为true,则首先在Session缓存中查找,看看该id对应的对象是否存在,不存在则使用延迟加载,返回实体的代理类对象(该代理类为实体类的子类,由CGLIB动态生成)。等到具体使用该对象(除获取OID以外)的时候,再查询二级缓存和数据库,若仍没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
    (2)若为false,就跟Hibernateget方法查找顺序一样,只是最终若没发现符合条件的记录,则会抛出一个ObjectNotFoundException。
    这里get和load有两个重要区别:
    如果未能发现符合条件的记录,Hibernate get方法返回null,而load方法会抛出一个ObjectNotFoundException。
    load方法可返回没有加载实体数据的代 理类实例,而get方法永远返回有实体数据的对象。
    (对于load和get方法返回类型:好多书中都说:“get方法永远只返回实体类”,实际上并不正 确,get方法如果在session缓存中找到了该id对应的对象,如果刚好该对象前面是被代理过的,如被load方法使用过,或者被其他关联对象延迟加 载过,那么返回的还是原先的代理对象,而不是实体类对象,如果该代理对象还没有加载实体数据(就是id以外的其他属性数据),那么它会查询二级缓存或者数 据库来加载数据,但是返回的还是代理对象,只不过已经加载了实体数据。)
    总之对于get和load的根本区别,一句话,hibernate对于 load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方 法,hibernate一定要获取到真实的数据,否则返回null。

Hibernate缓存的作用:
Hibernate是一个持久层框架,经常访问物理数据库,为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据
Hibernate缓存分类:
Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存
Hibernate一级缓存又称为“Session的缓存”,它是内置的,意思就是说,只要你使用hibernate就必须使用session缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存。在第一级缓存中,持久化类的每个实例都具有唯一的OID。
Hibernate二级缓存又称为“SessionFactory的缓存”,由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。第二级缓存是可选的,是一个可配置的插件,在默认情况下,SessionFactory不会启用这个插件。

什么样的数据适合存放到第二级缓存中?   
1 很少被修改的数据   
2 不是很重要的数据,允许出现偶尔并发的数据   
3 不会被并发访问的数据   
4 常量数据   
Hibernate查找对象如何应用缓存?
当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;如果都查不到,再查询数据库,把结果按照ID放入到缓存
删除、更新、增加数据的时候,同时更新缓存

Hibernate管理缓存实例
无论何时,我们在管理Hibernate缓存(Managing the caches)时,当你给save()、update()或saveOrUpdate()方法传递一个对象时,或使用load()、 get()、list()、iterate() 或scroll()方法获得一个对象时, 该对象都将被加入到Session的内部缓存中。
当随后flush()方法被调用时,对象的状态会和数据库取得同步。 如果你不希望此同步操作发生,或者你正处理大量对象、需要对有效管理内存时,你可以调用evict() 方法,从一级缓存中去掉这些对象及其集合。
3、 Mybatis相关
MyBatis应用程序根据XML配置文件创建SqlSessionFactory,SqlSessionFactory再根据配置,配置来源于两个地方,一处是配置文件,一处是Java代码的注解,获取一个SqlSession。SqlSession包含了执行sql所需要的所有方法,可以通过SqlSession实例直接运行映射的sql语句,完成对数据的增删改查和事务提交等,用完之后关闭SqlSession。
MyBatis的优缺点
优点:
1、简单易学。mybatis本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
2、灵活,mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
3、解除sql与程序代码的耦合,通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
4、提供映射标签,支持对象与数据库的orm字段关系映射
5、提供对象关系映射标签,支持对象关系组建维护
6、提供xml标签,支持编写动态sql。
缺点:
1、编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。
2、SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库 。
3、框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
4、二级缓存机制不佳
mybatis的优点同样是mybatis的缺点,正因为mybatis使用简单,数据的可靠性、完整性的瓶颈便更多依赖于程序员对sql的使用水平上了。sql写在xml里,虽然方便了修改、优化和统一浏览,但可读性很低,调试也非常困难,也非常受限。
mybatis没有hibernate那么强大,但是mybatis最大的优点就是简单小巧易于上手,方便浏览修改sql语句。

Nginx相关
Nginx是一个高性能的HTTP和反向代理服务器,属于异步非阻塞的方式处理高并发. 当nginx在unix系统中以daemon方式在后台运行时,后台包含一个master进程和多个worker进程。  一般来说,Nginx都是以多进程的方式来工作的。通过管理master进程来控制各个worker进程与client交互。

Nginx实现负载均衡
Nginx最常见的功能配置就是实现其负载均衡。分摊到多个操作单元上进行执行。例如web服务器。FTP服务器。共同完成工作任务,从而减少服务器压力过大问题。
Nginx的反向代理通常与其负载均衡搭配使用,从而实现高可用。
在nginx的config.xml中通过upstream指令指定一个负载均衡的名称并配置一组tomcat服务器
通过proxy_pass指令指定反向代理的地址

Nginx的常用四种调度算法
1、轮询(默认)每个请求按时间顺序逐一分配到不同的后端服务器上。
2、weight指定轮询权值。weight越大。分配到的访问几率越高
3、ip_hash每个请求按访问的IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题
4、fair 这是比上面两个更加智能的负载均衡算法。此算法可以依据页面大小和加载时间长短智能进行负载均衡
Nginx的动静分离
在java中动态文件包括jsp、servlet等,而js、css、图片png等则属于静态文件。通过配置动静态分离可以很有效的处理不同的请求,比如静态文件进行缓存,动态文件提交给tomcat处理
从这里可以看出动态文件会被反向代理给一组tomcat名称为webservers的服务器,而html,gif等结尾的静态请求会被拦截 并去根目录为/usr/share/nginx/html中取查找。 expires 3d表示会在客户端进行拦截,缓存时间为三天。

keepalived+nginx实现负载均衡高可用(复杂难点,可不看)

     nginx作为负载均衡器,所有请求都到了nginx,可见nginx处于非常重点的位置,如果nginx服务器宕机后端web服务将无法提供服务,影响严重。
为了屏蔽负载均衡服务器的宕机,需要建立一个备份机。主服务器和备份机上都运行高可用(High Availability)监控程序,通过传送诸如“I am alive”这样的信息来监控对方的运行状况。当备份机不能在一定的时间内收到这样的信息时,它就接管主服务器的服务IP并继续提供负载均衡服务;当备份管理器又从主管理器收到“I am alive”这样的信息时,它就释放服务IP地址,这样的主服务器就开始再次提供负载均衡服务。
keepalived是集群管理中保证集群高可用的一个服务软件,用来防止单点故障。Keepalived的作用是检测web服务器的状态,如果有一台web服务器死机,或工作出现故障,Keepalived将检测到,并将有故障的web服务器从系统中剔除,当web服务器工作正常后Keepalived自动将web服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的web服务器。
keepalived主要有三个模块,分别是core、check和VRRP。core模块为keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。check负责健康检查,包括常见的各种检查方式。VRRP模块是来实现VRRP协议的。
初始状态:

主机怠机:

当主机恢复以后则会再次恢复到初始状态。
高可用环境:两台nginx(要求多台,以便于高可用),两台tomcat(要求多台,以便于负载均衡)。keepAlived配置在nginx中,需要修改nginx下的/etc/keepalived/keepalived.conf文件
修改备Nginx
配置备nginx时需要注意:需要修改state为BACKUP , priority比MASTER低,virtual_router_id和master的值一致。

Redis相关

Redis是基于C开发的一款高性能的存储型Nosql数据库,它以key-value形式进行数据存储。将数据写入内存中,不仅利于存储,大大缩减了访问数据库的压力,而且它会异步的的将数据写入磁盘,保证了数据的持久化。适用于高并发的应用场景。
Redis的优点:
速度快,因为数据储存在内存中,类似于hashmap形式的key-value高性能存储和查询速度
支持丰富的数据类型,如string,list,set,hash等
支持事务,操作都是原子性,要么全部运行,要么全部不执行
可用于缓存,消息存储按照key可以设置其过期时间,过期会自动删除
redis会将数据存进内存,且会异步写入磁盘,保证了数据的持久化。
Redis与memcached的比较
Memcached是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。Memcached通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。
从介绍可以知道,Memcached与redis非常类似,而redis则是作为其替代品出现的。
1) memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型
2) redis的速度比memcached快很多.
3) Redis支持数据的备份,即master-slave模式的数据备份
4) Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。redis可以持久化其数据(即写入磁盘)
5) redis最大可以达到1GB,而memcache只有1MB
6) 异步的方式将数据写入磁盘
7) 与Memcached一样,为了保证效率,数据都是缓存在内存中。区别的是Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从 )同步(数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。)。
Redis集群
Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。

Key:a
计算a的hash值,例如值为100,100这个槽在server1上,所以a应该放到server1.
Key:hello
Hash值:10032,此槽在server2上。Hell可以应该存在server2.
redis-cluster投票:容错

(1)领着投票过程是集群中所有master参与,如果半数以上master节点与master节点通信超过(cluster-node-timeout),认为当前master节点挂掉.
(2):什么时候整个集群不可用(cluster_state:fail)?
a:如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成集群的slot映射[0-16383]不完成时进入fail状态. ps : redis-3.0.0.rc1加入cluster-require-full-coverage参数,默认关闭,打开集群兼容部分失败.
b:如果集群超过半数以上master挂掉,无论是否有slave集群进入fail状态.
ps:当集群不可用时,所有对集群的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down)错误。
Jedis与Redisson对比有什么优缺点? (redis的客户端)
Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持;Redisson实现了分布式和可扩展的Java数据结构,和Jedis相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等Redis特性。Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。
Redis持久化方式
Redis由于支持非常丰富的内存数据结构类型,如何把这些复杂的内存组织方式持久化到磁盘上是一个难题,所以Redis的持久化方式与传统数据库的方式有比较多的差别,Redis一共支持两种种持久化方式,分别是:
• 定时快照方式(snapshot)
• 基于语句追加文件的方式(aof)
定时快照方式(snapshot):
该持久化方式实际是在Redis内部一个定时器事件,每隔固定时间去检查当前数据发生的改变次数与时间是否满足配置的持久化触发的条件,如果满足则通过操作系统fork调用来创建出一个子进程,这个子进程默认会与父进程共享相同的地址空间,这时就可以通过子进程来遍历整个内存来进行存储操作,而主进程则仍然可以提供服务,当有写入时由操作系统按照内存页(page)为单位来进行copy-on-write保证父子进程之间不会互相影响。
基于语句追加方式(AOF):
AOF方式实际类似mysql的基于语句的binlog方式,即每条会使Redis内存数据发生改变的命令都会追加到一个log文件中,也就是说这个log文件就是Redis的持久化数据。
AOF的方式的主要缺点是追加log文件可能导致体积过大,当系统重启恢复数据时如果是AOF的方式则加载数据会非常慢,几十G的数据可能需要几小时才能加载完,当然这个耗时并不是因为磁盘文件读取速度慢,而是由于读取的所有命令都要在内存中执行一遍。另外由于每条命令都要写log,所以使用AOF的方式,Redis的读写性能也会有所下降。

Redis的高可用配置
Redis的高可用一般都会配置主从复制或者数据持久化机制。这里不再进行阐述。
Spring引入Redis
Spring-data-redis是spring大家族的一部分,提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。
此处不再对spring-data-redis进行解释,有兴趣的同事可以去百度。又是一个宏大且轻量的框架

搜索引擎相关之solr
**Solr是什么?**
     Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化。 

Solr是一个全文检索服务器,只需要进行配置就可以实现全文检索服务。
配置问题: solr依托于web容器才能运行,我们需要将solrhome的位置告诉给solr服务器,因此需要在web.Xml中配置solrhome

中文分析器:IK-Analyzer作为最常用的中文分析器,将其上次到solr服务器中,才能进行智能分词断句。

前面说过solr是一个可配置的搜索引擎。为了更好的分词,搜索,我们可以自己进行配置如:

Solr客户端之solrJ
引入solrj的jar包,连接solr的ip地址即可使用。

Solr与spring的整合
Solr与spring整合十分简单。(所有spring的整合配置都是万变不离其宗)。
第一步:编写maven项目的pom文件,导入依赖

  1. <project xmlns=“http://maven.apache.org/POM/4.0.0” xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
  2.  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
    
  3.  <modelVersion>4.0.0</modelVersion>  
    
  4.  <groupId>com.millery.spring_solr</groupId>  
    
  5.  <artifactId>spring-solr</artifactId>  
    
  6.  <version>0.0.1-SNAPSHOT</version>  
    
  7.  <packaging>war</packaging>  
    
  8. <!-- 添加依赖 -->  
    
  9. <dependencies>  
    
  10.     <!-- Spring依赖 -->  
    
  11.     <dependency>  
    
  12.         <groupId>org.springframework</groupId>  
    
  13.         <artifactId>spring-context</artifactId>  
    
  14.         <version>4.1.3.RELEASE</version>  
    
  15.     </dependency>  
    
  16.     <dependency>  
    
  17.         <groupId>org.springframework</groupId>  
    
  18.         <artifactId>spring-beans</artifactId>  
    
  19.         <version>4.1.3.RELEASE</version>  
    
  20.     </dependency>  
    
  21.     <dependency>  
    
  22.         <groupId>org.springframework</groupId>  
    
  23.         <artifactId>spring-jdbc</artifactId>  
    
  24.         <version>4.1.3.RELEASE</version>  
    
  25.     </dependency>  
    
  26.     <dependency>  
    
  27.         <groupId>org.springframework</groupId>  
    
  28.         <artifactId>spring-aspects</artifactId>  
    
  29.         <version>4.1.3.RELEASE</version>  
    
  30.     </dependency>  
    
  31.     <!--solr客户端solrj的依赖 -->  
    
  32.     <dependency>  
    
  33.         <groupId>org.apache.solr</groupId>  
    
  34.         <artifactId>solr-solrj</artifactId>  
    
  35.         <version>4.10.1</version>  
    
  36.     </dependency>  
    
  37. </dependencies>  
    

第二步:编写applicationContext-solr.xml和solr.properties配置文件
applicationContext-solr.xml配置文件的内容:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns=“http://www.springframework.org/schema/beans”
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"  
    
  4.  xmlns:context="http://www.springframework.org/schema/context"  
    
  5.  xmlns:mvc="http://www.springframework.org/schema/mvc"  
    
  6.  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
    
  7.      http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd  
    
  8.      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">  
    
  9. <!--定义solr的server-->  
    
  10. <bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">  
    
  11.     <constructor-arg index="0" value="${solr.Url}"/>  
    
  12. <!-- 设置响应解析器 -->    
    
  13.    <property name="parser">  
    
  14.       <bean class="org.apache.solr.client.solrj.impl.XMLResponseParser"/>  
    
  15.    </property>  
    
  16.     <!-- 设置重试次数-->  
    
  17.     <property name="maxRetries" value="${solr.maxRetries}"/>  
    
  18.     <!-- 建立连接的最长时间 -->  
    
  19.    <property name="connectionTimeout" value="${solr.connectionTimeout}"/>  
    
  20. </bean>  
    

solr.properties配置文件的内容:
[html] view plain copy

  1. solr.Url=http://127.0.0.1:8983/millery
  2. solr.maxRetries=1
  3. solr.connectionTimeout=500
    SpringSolr类:
  4. @Component
  5. public class SpringSolr {
  6.  @Autowired  
    
  7.  private HttpSolrServer httpSolrServer;  
    
  8.  public User getUser(Long id) throws SolrServerException {  
    
  9.      //创建查询条件  
    
  10.     SolrQuery query = new SolrQuery();  
    
  11.     query.setQuery("id:" + id);  
    
  12.     //查询并返回结果  
    
  13.     QueryResponse queryResponse = this.httpSolrServer.query(query);  
    
  14.     return (User) queryResponse.getBeans(User.class);  
    
  15. }  
    
  16. }
    SpringSolrTest类
  17. public class SpringSolrTest {
  18.  private SpringSolr springSolr;  
    
  19.  @Before  
    
  20.  public void setUp() throws Exception {  
    
  21.      // 初始化Spring容器  
    
  22.      ApplicationContext applicationContext = new ClassPathXmlApplicationContext(  
    
  23.              "applicationContext.xml", "applicationContext-solr.xml");  
    
  24.     //获取对象  
    
  25.     this.springSolr = applicationContext.getBean(SpringSolr.class);  
    
  26. }  
    
  27. @Test  
    
  28. public void test() throws SolrServerException {  
    
  29.     // 测试方法,输出结果  
    
  30.     User user = springSolr.getUser((long) 1);  
    
  31.     System.out.println(user);  
    
  32. }  
    
  33. }

Solr进阶之solrColud
SolrCloud(solr 云)是Solr提供的分布式搜索方案,当你需要大规模,容错,分布式索引和检索能力时使用 SolrCloud。当一个系统的索引数据量少的时候是不需要使用SolrCloud的,当索引量很大,搜索请求并发很高,这时需要使用SolrCloud来满足这些需求。
SolrCloud是基于Solr和Zookeeper的分布式搜索方案,它的主要思想是使用Zookeeper作为集群的配置信息中心。
它有几个特色功能:
1)集中式的配置信息
2)自动容错
3)近实时搜索
4)查询时自动负载均衡
ZooKeeper是什么?
Zookeeper 分布式服务框架是Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。
简单的说,zookeeper=文件系统+通知机制(不讲深了,主要还是讲solrCloud)
Zookeeper可以用来做很多事情。
1) 配置管理:对一些配置文件提供一致性协议服务。
2) 名字服务:类似于DNS,将多个IP地址映射的域名进行统一管理。
3) 分布式锁:协调多个分布式进程之间的活动。
4) 集群管理:对新老节点集群进行统一管理。
solr集群的结构

solrCloud的结构图如下:

solrCloud的环境搭建太过麻烦。我新建一个文档。如果感兴趣的同事可以点开结合自己环境进行搭建。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在开发五子棋的小程序时,主要涉及以下几个Java知识点: 1. 面向对象的思想:通过创建一个名为Chess的类,将棋子对象化,使用该类的对象来表示棋子的行、列和标识。这样可以更方便地进行悔棋操作和棋盘的重绘。 2. 使用数组和二维数组:通过使用数组和二维数组来表示棋盘和棋子的状态。可以根据棋子对象所在的行、列信息,在二维数组中设置对应位置的值来表示棋子的存在。同时,可以根据数组中的值来判断游戏的胜负。 3. 事件监听器(Listener):使用GoListener类来监听玩家的操作,如鼠标点击棋盘的位置来下棋。该类中的相关方法负责处理玩家的操作,并更新棋盘和棋子的状态。例如,实现悔棋功能时,根据棋盘上的棋子顺序数组,删除最后一颗棋子,并在棋盘和棋子数组中相应位置进行更新。 4. 图形界面的绘制:通过使用Java的图形库,可以实现五子棋的可视化界面。绘制棋盘和棋子的图形,并随着玩家的操作进行更新。 5. 网络编程:在开发五子棋游戏大厅时,可能还涉及到Socket编程的相关知识点。这可以用来实现游戏大厅的功能,如动态加载游戏,让玩家选择进入游戏等。 总结来说,五子棋的Java知识重点包括面向对象的思想、数组和二维数组的使用、事件监听器、图形界面的绘制以及可能的网络编程。这些知识点是开发五子棋小程序的关键所在。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值