<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Kyle_Ng</title>
    <description>prictice make perfect.</description>
    <link>https://kyleng.github.io/</link>
    <atom:link href="https://kyleng.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 03 Sep 2020 16:47:59 +0000</pubDate>
    <lastBuildDate>Thu, 03 Sep 2020 16:47:59 +0000</lastBuildDate>
    <generator>Jekyll v3.9.0</generator>
    
      <item>
        <title>线性代数（LinearAlgebra）</title>
        <description>&lt;script type=&quot;text/javascript&quot; src=&quot;http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default&quot;&gt;&lt;/script&gt;

&lt;h1 id=&quot;线性代数笔记-01&quot;&gt;&lt;strong&gt;线性代数笔记 01&lt;/strong&gt;&lt;/h1&gt;

&lt;h2 id=&quot;1向量vector&quot;&gt;1，向量（Vector）&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;vector就是一组数字，有两种，一种是row vector，一种是column vector。一般而言，我们没有特殊声明，说一个vector就是一个column vector。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;\(row \quad vector:\begin{vmatrix}{a_{1}}&amp;amp;{a_{2}}&amp;amp;{\cdots}&amp;amp;{a_{n}}\end{vmatrix}\)
\(column \quad vector:\begin{vmatrix}{a_{1}}\\\\{a_{2}}\\\\{\vdots}\\\\{a_{n}}\end{vmatrix}\)&lt;/p&gt;

&lt;h2 id=&quot;2-向量空间spaces-of-vectors&quot;&gt;2, 向量空间（Spaces of Vectors）&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;空间表示有很多向量，一整个空间的向量，但并不是任意向量的组合，能称为空间的，空间本身必须满足一定的规则。必须能够进行加法和数乘运算，也就是说，必须能够线性组合。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;二维向量空间&lt;/p&gt;

    &lt;p&gt;\( R^2 \) = All 2 dimensional real vectors.
  \(v=\begin{vmatrix}{x_{1}}\\\\{x_{2}}\end{vmatrix}\)
  \((x_1 , x_2\in R)\)&lt;/p&gt;

    &lt;p&gt;由上面的公式不难理解\( R^2 \)就是整个二维平面，那么就不难理解\( R^3 \)就包含了整个三维空间的所有向量。&lt;/p&gt;

    &lt;p&gt;\( R^n \) = all column vectors with n real components.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;3-向量的性质properties-of-vector&quot;&gt;3, 向量的性质（Properties of Vector）&lt;/h2&gt;

&lt;p&gt;对于向量 &lt;strong&gt;u&lt;/strong&gt;, &lt;strong&gt;v&lt;/strong&gt; 和 &lt;strong&gt;w&lt;/strong&gt; 都属于 \( R^n \), 任意标量 a和 b 则有以下性质&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;交换性 (commutativity)：
    &lt;ul&gt;
      &lt;li&gt;\( u + v = v + u \)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;结合性 (associativity)：
    &lt;ul&gt;
      &lt;li&gt;\( (u + v) + w = u + (v + w) \)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;加法单位元 (additive identity)：
    &lt;ul&gt;
      &lt;li&gt;\( 𝟎 + u = u \)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;加法逆元素 (additive inverse)：
    &lt;ul&gt;
      &lt;li&gt;\( u’ + u = 0 \)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;乘法单位元 (multiplicative identity)：
    &lt;ul&gt;
      &lt;li&gt;\( 1u = u \)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;分配性 (distributivity)：
    &lt;ul&gt;
      &lt;li&gt;\( a(u+v) = au + av \)&lt;/li&gt;
      &lt;li&gt;\( (ab)u = a(bu) \)&lt;/li&gt;
      &lt;li&gt;\( (a+b)u = au + bu \)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;4-矩阵matrix&quot;&gt;4, 矩阵（Matrix）&lt;/h2&gt;

&lt;p&gt;matrix就是一个vector set。一般我们用大写加粗字母表示，比如&lt;strong&gt;M&lt;/strong&gt;。每一个元素用相同字母带上下标表示，比如\( m_{ij}\)，其中i表示第i行，j表示第j列。同样处于方便，很多时候直接用大写的字母表示矩阵。我们会叫一个行列相同的矩阵是方阵（square matrix）。&lt;/p&gt;

\[matrix： \quad \begin{vmatrix}
{a_{11}}&amp;amp;{a_{12}}&amp;amp;{\cdots}&amp;amp;{a_{1n}}\\\\
{a_{21}}&amp;amp;{a_{22}}&amp;amp;{\cdots}&amp;amp;{a_{2n}}\\\\
{\vdots}&amp;amp;{\vdots}&amp;amp;{\ddots}&amp;amp;{\vdots}\\\\
{a_{m1}}&amp;amp;{a_{m2}}&amp;amp;{\cdots}&amp;amp;{a_{mn}}\\\\
\end{vmatrix}\]

\[square \quad matrix： \quad \begin{vmatrix}
{a_{11}}&amp;amp;{a_{12}}&amp;amp;{\cdots}&amp;amp;{a_{1n}}\\\\
{a_{21}}&amp;amp;{a_{22}}&amp;amp;{\cdots}&amp;amp;{a_{2n}}\\\\
{\vdots}&amp;amp;{\vdots}&amp;amp;{\ddots}&amp;amp;{\vdots}\\\\
{a_{n1}}&amp;amp;{a_{n2}}&amp;amp;{\cdots}&amp;amp;{a_{nn}}\\\\
\end{vmatrix}\]

&lt;h2 id=&quot;5-特殊矩阵&quot;&gt;5, 特殊矩阵&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;零矩阵（Zero Matrix）&lt;/p&gt;

    &lt;p&gt;零矩阵即所有元素皆为0的矩阵&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

\[O_{mn}： \quad \begin{vmatrix}
{0}&amp;amp;{0}&amp;amp;{\cdots}&amp;amp;{0}\\\\
{0}&amp;amp;{0}&amp;amp;{\cdots}&amp;amp;{0}\\\\
{\vdots}&amp;amp;{\vdots}&amp;amp;{\ddots}&amp;amp;{\vdots}\\\\
{0}&amp;amp;{0}&amp;amp;{\cdots}&amp;amp;{0}\\\\
\end{vmatrix}\]

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;单位矩阵（Identity matrix）: must be square&lt;/p&gt;

    &lt;p&gt;行列必须相等，对角线全部为1，其余entities都是0&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

\[I_{nn}： \quad \begin{vmatrix}
{1}&amp;amp;{0}&amp;amp;{\cdots}&amp;amp;{0}\\\\
{0}&amp;amp;{1}&amp;amp;{\cdots}&amp;amp;{0}\\\\
{\vdots}&amp;amp;{\vdots}&amp;amp;{\ddots}&amp;amp;{\vdots}\\\\
{0}&amp;amp;{0}&amp;amp;{\cdots}&amp;amp;{1}\\\\
\end{vmatrix}\]

&lt;h2 id=&quot;6-矩阵的性质properties-of-matrix&quot;&gt;6, 矩阵的性质（Properties of Matrix）&lt;/h2&gt;

&lt;p&gt;对于&lt;strong&gt;A&lt;/strong&gt;, &lt;strong&gt;B&lt;/strong&gt;, &lt;strong&gt;C&lt;/strong&gt; 是 mxn 的矩阵, 并且 s 和 t 是任意标量&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;交换性 (commutativity)：
    &lt;ul&gt;
      &lt;li&gt;\( A + B = B + A \)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;结合性 (associativity)：
    &lt;ul&gt;
      &lt;li&gt;\( (A + B) + C = A + (B + C) \)&lt;/li&gt;
      &lt;li&gt;\( (st)A = s(tA) \)&lt;/li&gt;
      &lt;li&gt;\( s(A + B) = sA + sB \)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;分配性 (distributivity)：
    &lt;ul&gt;
      &lt;li&gt;\( (s+t)A = sA + tA \)
t
        &lt;h2 id=&quot;7矩阵的转置transpose&quot;&gt;7，矩阵的转置（Transpose）&lt;/h2&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;将矩阵A的行换成同序号的列所得到的新矩阵称为矩阵A的转置矩阵，记作\( A^T \)或\( A’ \)&lt;/p&gt;

&lt;p&gt;例
\(A \quad = \quad \begin{vmatrix}
{1}&amp;amp;{0}&amp;amp;{3}&amp;amp;{-1}\\\\
{2}&amp;amp;{1}&amp;amp;{0}&amp;amp;{2}\\\\
\end{vmatrix}\)&lt;/p&gt;

&lt;p&gt;的专职矩阵为&lt;/p&gt;

\[A^T \quad = \quad A' \quad = \quad \begin{vmatrix}
{1}&amp;amp;{2}\\\\
{0}&amp;amp;{1}\\\\
{3}&amp;amp;{0}\\\\
{-1}&amp;amp;{2}\\\\
\end{vmatrix}\]

&lt;p&gt;运算性质（假设所有运算都是可行的）&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;\( (A’)’ = A \)&lt;/li&gt;
  &lt;li&gt;\( (A+B)’ = A’ + B’ \)&lt;/li&gt;
  &lt;li&gt;\( (AB)’ = A’B’ \)&lt;/li&gt;
  &lt;li&gt;\( (\lambda A)’ = \lambda A’ \quad \lambda 是常数\)&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 27 May 2020 00:00:00 +0000</pubDate>
        <link>https://kyleng.github.io/linear%20algebra/LinearAlgebra01</link>
        <guid isPermaLink="true">https://kyleng.github.io/linear%20algebra/LinearAlgebra01</guid>
        
        <category>Linear</category>
        
        <category>Algebra</category>
        
        
        <category>Linear Algebra</category>
        
      </item>
    
      <item>
        <title>Zookeeper（一）</title>
        <description>\[x_1\]

&lt;h2 id=&quot;一zookeeper概念简介&quot;&gt;一.Zookeeper概念简介&lt;/h2&gt;
&lt;p&gt;Zookeeper是一个分布式协调服务；就是为用户的分布式应用程序提供协调服务&lt;br /&gt;
主要包括主从协调、服务器节点动态上下线、统一配置管理、分布式共享锁、统一名称服务……&lt;br /&gt;
通俗的说Zookeeper主要包含两个功能：&lt;br /&gt;
1）管理(存储，读取)用户程序提交的数据；&lt;br /&gt;
2）为用户程序提供数据节点监听服务；&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：半数机制：集群中半数以上机器存活，集群可用。
zookeeper适合装在奇数台机器上！！！&lt;/p&gt;

&lt;h2 id=&quot;二安装&quot;&gt;二.安装&lt;/h2&gt;

&lt;p&gt;本文中以三台机器为例&lt;br /&gt;
安装前请检查机器都可以相互ssh免密登陆，确保JDK已经安装正确，安装包已经上传至服务器。&lt;br /&gt;
&lt;a href=&quot;http://zookeeper.apache.org/&quot; title=&quot;Zookeeper官网&quot;&gt;Zookeeper官网&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;1解压安装包&quot;&gt;1，解压安装包&lt;/h3&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tar -zxvf zookeeper-3.4.9.tar.gz -C /opt/
# 把解压后文件夹复制到其他两台机器
scp -r /opt/zookeeper-3.4.9/ kyle002:/opt/
scp -r /opt/zookeeper-3.4.9/ kyle003:/opt/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2修改环境变量&quot;&gt;2，修改环境变量&lt;/h3&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo vim /etc/profile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在文件结尾加上下面两句环境变量配置&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export ZOOKEEPER_HOME=/opt/zookeeper-3.4.9
export PATH=$PATH:\$ZOOKEEPER_HOME/bin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;http://img.blog.csdn.net/20170611230526583&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;重新加载profile文件&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;source /etc/profile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;3修改配置文件&quot;&gt;3，修改配置文件&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cp /opt/zookeeper-3.4.9/conf/zoo_sample.cfg /opt/zookeeper-3.4.9/conf/zoo.cfg
vim /opt/zookeeper-3.4.9/conf/zoo.cfg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;http://img.blog.csdn.net/20170611230548240&quot; alt=&quot;&quot; /&gt;
配置文件修改如下&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=/home/hadoop/zookeeper/data
dataLogDir=/home/hadoop/zookeeper/log
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to &quot;0&quot; to disable auto purge feature
#autopurge.purgeInterval=1
server.1=kyle001:2888:3888
server.2=kyle002:2888:3888
server.3=kyle003:2888:3888
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;创建配置文件中配置的文件夹&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mkdir 755 -p /home/hadoop/zookeeper/data /home/hadoop/zookeeper/log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;data文件夹下新建myid，每台机器的文件内容要跟配置文件一致&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# 集群中每台机器都要配置
echo 1 &amp;gt; /home/hadoop/zookeeper/data/maid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;4测试安装结果&quot;&gt;4，测试安装结果&lt;/h3&gt;
&lt;p&gt;启动（每台机器）&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[hadoop@kyle001 data]$ /opt/zookeeper-3.4.9/bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.4.9/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

# 想要在一台机器上远程启动需要注意：需要先source下资源&amp;lt;br&amp;gt;
ssh kyle002 &quot;source /etc/profile;/opt/zookeeper-3.4.9/bin/zkServer.sh start&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;全部启动之后查看状态&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[hadoop@kyle003 data]$ /opt/zookeeper-3.4.9/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.4.9/bin/../conf/zoo.cfg
Mode: follower 注意：Mode还有可能是leader&amp;lt;br&amp;gt; 用jps查看

[hadoop@kyle002 data]$ jps
1588 QuorumPeerMain
1647 Jps QuorumPeerMain就是zookeeper任务
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;三zookeeper结构和命令&quot;&gt;三.zookeeper结构和命令&lt;/h2&gt;
&lt;h3 id=&quot;1zookeeper特性&quot;&gt;1，zookeeper特性&lt;/h3&gt;
&lt;p&gt;Zookeeper：一个leader，多个follower组成的集群&lt;br /&gt;
全局数据一致：每个server保存一份相同的数据副本，client无论连接到哪个server，数据都是一致的&lt;br /&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;分布式读写，更新请求转发，由leader实施。&lt;br /&gt;&lt;/li&gt;
  &lt;li&gt;来自同一个client的更新请求按其发送顺序依次执行。&lt;br /&gt;&lt;/li&gt;
  &lt;li&gt;数据更新原子性，一次数据更新要么成功，要么失败。&lt;br /&gt;&lt;/li&gt;
  &lt;li&gt;实时性，在一定时间范围内，client能读到最新数据。
    &lt;h3 id=&quot;2zookeeper数据结构&quot;&gt;2，zookeeper数据结构&lt;/h3&gt;
    &lt;p&gt;层次化的目录结构，命名符合常规文件系统规范(见下图)&lt;br /&gt;
每个节点在zookeeper中叫做znode,并且其有一个唯一的路径标识&lt;br /&gt;
节点Znode可以包含数据和子节点（但是EPHEMERAL类型的节点不能有子节点）&lt;br /&gt;
客户端应用可以在节点上设置监视器（后续详细讲解）&lt;br /&gt;&lt;br /&gt;
&lt;img src=&quot;http://img.blog.csdn.net/20170611204938948&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
    &lt;h3 id=&quot;3节点类型&quot;&gt;3，节点类型&lt;/h3&gt;
    &lt;p&gt;Znode有两种类型：&lt;br /&gt;
短暂（ephemeral）（断开连接自己删除）&lt;br /&gt;
持久（persistent）（断开连接不删除）&lt;br /&gt;
Znode有四种形式的目录节点（默认是persistent ）:&lt;br /&gt;
PERSISTENT&lt;br /&gt;
PERSISTENT_SEQUENTIAL（持久序列/test0000000019 ）&lt;br /&gt;
EPHEMERAL&lt;br /&gt;
EPHEMERAL_SEQUENTIAL&lt;br /&gt;
创建znode时设置顺序标识，znode名称后会附加一个值，顺序号是一个单调递增的计数器，由父节点维护&lt;br /&gt;
在分布式系统中，顺序号可以被用于为所有的事件进行全局排序，这样客户端可以通过顺序号推断事件的顺序&lt;br /&gt;&lt;/p&gt;
    &lt;h3 id=&quot;4zookeeper命令行操作&quot;&gt;4，zookeeper命令行操作&lt;/h3&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;启动命令行客户端：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[hadoop@kyle001 ~]$ /opt/zookeeper-3.4.9/bin/zkCli.sh 
Connecting to localhost:2181
2017-06-12 06:06:11,483 [myid:] - INFO  [main:Environment@100] - Client environment:zookeeper.version=3.4.9-1757313, built on 08/23/2016 06:50 GMT
2017-06-12 06:06:11,488 [myid:] - INFO  [main:Environment@100] - Client environment:host.name=kyle001
2017-06-12 06:06:11,489 [myid:] - INFO  [main:Environment@100] - Client environment:java.version=1.8.0_131
2017-06-12 06:06:11,493 [myid:] - INFO  [main:Environment@100] - Client environment:java.vendor=Oracle Corporation
2017-06-12 06:06:11,494 [myid:] - INFO  [main:Environment@100] - Client environment:java.home=/soft/jdk1.8.0_131/jre
2017-06-12 06:06:11,494 [myid:] - INFO  [main:Environment@100] - Client environment:java.class.path=/opt/zookeeper-3.4.9/bin/../build/classes:/opt/zookeeper-3.4.9/bin/../build/lib/*.jar:/opt/zookeeper-3.4.9/bin/../lib/slf4j-log4j12-1.6.1.jar:/opt/zookeeper-3.4.9/bin/../lib/slf4j-api-1.6.1.jar:/opt/zookeeper-3.4.9/bin/../lib/netty-3.10.5.Final.jar:/opt/zookeeper-3.4.9/bin/../lib/log4j-1.2.16.jar:/opt/zookeeper-3.4.9/bin/../lib/jline-0.9.94.jar:/opt/zookeeper-3.4.9/bin/../zookeeper-3.4.9.jar:/opt/zookeeper-3.4.9/bin/../src/java/lib/*.jar:/opt/zookeeper-3.4.9/bin/../conf:
2017-06-12 06:06:11,494 [myid:] - INFO  [main:Environment@100] - Client environment:java.library.path=/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
2017-06-12 06:06:11,494 [myid:] - INFO  [main:Environment@100] - Client environment:java.io.tmpdir=/tmp
2017-06-12 06:06:11,494 [myid:] - INFO  [main:Environment@100] - Client environment:java.compiler=&amp;lt;NA&amp;gt;
2017-06-12 06:06:11,494 [myid:] - INFO  [main:Environment@100] - Client environment:os.name=Linux
2017-06-12 06:06:11,495 [myid:] - INFO  [main:Environment@100] - Client environment:os.arch=amd64
2017-06-12 06:06:11,495 [myid:] - INFO  [main:Environment@100] - Client environment:os.version=2.6.32-696.el6.x86_64
2017-06-12 06:06:11,495 [myid:] - INFO  [main:Environment@100] - Client environment:user.name=hadoop
2017-06-12 06:06:11,495 [myid:] - INFO  [main:Environment@100] - Client environment:user.home=/home/hadoop
2017-06-12 06:06:11,495 [myid:] - INFO  [main:Environment@100] - Client environment:user.dir=/home/hadoop
2017-06-12 06:06:11,500 [myid:] - INFO  [main:ZooKeeper@438] - Initiating client connection, connectString=localhost:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@446cdf90
Welcome to ZooKeeper!
2017-06-12 06:06:11,597 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1032] - Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
JLine support is enabled
2017-06-12 06:06:11,815 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@876] - Socket connection established to localhost/127.0.0.1:2181, initiating session
2017-06-12 06:06:11,957 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1299] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x15c992d06310000, negotiated timeout = 30000

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
[zk: localhost:2181(CONNECTED) 0] 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;1、使用 ls 命令来查看当前 ZooKeeper 中所包含的内容：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 0] ls /
[zookeeper]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;2、创建一个新的 znode ，使用 create /zk myData 。这个命令创建了一个新的 znode 节点“ zk ”以及与它关联的字符串：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 1] create /zk &quot;mydata&quot;
Created /zk
[zk: localhost:2181(CONNECTED) 2] 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：create -e /zk “mydata”就会创建一个短暂的节点（默认创建的是持久节点），在客户端quite的时候一起消失。&lt;/p&gt;

&lt;p&gt;3、运行 get 命令来确认 znode 的字符串：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 2] get /zk
mydata
cZxid = 0x400000002
ctime = Mon Jun 12 06:15:09 CST 2017
mZxid = 0x400000002
mtime = Mon Jun 12 06:15:09 CST 2017
pZxid = 0x400000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
[zk: localhost:2181(CONNECTED) 3] 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;4、监听某个节点的变化：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：监听这个节点的客户端会出现提示信息，这种监听只能监听一次变化&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 3] get /zk watch
mydata
cZxid = 0x400000002
ctime = Mon Jun 12 06:15:09 CST 2017
mZxid = 0x400000002
mtime = Mon Jun 12 06:15:09 CST 2017
pZxid = 0x400000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;5、通过 set 命令来对 zk 所关联的字符串进行设置：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 1] set /zk &quot;UpdateData&quot;
cZxid = 0x400000002
ctime = Mon Jun 12 06:15:09 CST 2017
mZxid = 0x400000004
mtime = Mon Jun 12 06:25:48 CST 2017
pZxid = 0x400000002
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 10
numChildren = 0
[zk: localhost:2181(CONNECTED) 2] 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果在4步设置监听之后再设置节点信息监听事件就会起作用，如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 4] 
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/zk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;6、删除节点&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 6] delete /zk
[zk: localhost:2181(CONNECTED) 7] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 8]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;7、递归删除节点：rmr&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 11] ls /
[zookeeper, test]
[zk: localhost:2181(CONNECTED) 12] ls /test
[haha]
[zk: localhost:2181(CONNECTED) 13] rmr /test
[zk: localhost:2181(CONNECTED) 14] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 15]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 01 Sep 2019 00:00:00 +0000</pubDate>
        <link>https://kyleng.github.io/zookeeper/Linear_Regression</link>
        <guid isPermaLink="true">https://kyleng.github.io/zookeeper/Linear_Regression</guid>
        
        <category>Zookeeper</category>
        
        
        <category>Zookeeper</category>
        
      </item>
    
      <item>
        <title>MySQL的Replication.主从同步(Master-slave)</title>
        <description>&lt;h2 id=&quot;mysql同步的基本概念&quot;&gt;&lt;strong&gt;Mysql同步的基本概念&lt;/strong&gt;&lt;/h2&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;前言&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;MySQL的Replication是一种多个MySQL的数据库做主从同步的方案，这对我们实现数据库的冗灾、备份、恢复、负载均衡等都是有极大帮助的。一来可以实现简单的读写分离场景，二来也可以纯粹的给数据库备份。&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MySQL官方提供的MySQL Replication教程：&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://dev.mysql.com/doc/refman/5.6/en/replication.html&quot;&gt;Mysql官网Replication教程地址&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;下图是MySQL官方给出了使用Replication的场景：&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://dl.iteye.com/upload/attachment/0076/1660/4a9328c6-a24d-34d4-9fd3-fd39e39fcec5.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mysql Replication原理：&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mysql 的 Replication 是一个异步的复制过程，从一个MySQL节点（称之为Master）复制到另一个MySQL节点（称之Slave）。在 Master 与 Slave 之间的实现整个复制过程主要由三个线程来完成，其中两个线程（SQL 线程和 I/O 线程）在 Slave 端，另外一个线程（I/O 线程）在 Master 端。&lt;/p&gt;

&lt;p&gt;要实现 MySQL 的 Replication ，首先必须打开 Master 端的 Binary Log，因为整个复制过程实际上就是 Slave 从 Master 端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;原理总结与注意点：&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;每个从仅可以设置一个主。&lt;/li&gt;
  &lt;li&gt;主在执行sql之后，记录二进制log文件（bin-log）。&lt;/li&gt;
  &lt;li&gt;从连接主，并从主获取binlog，存于本地relay-log，并从上次记住的位置起执行sql，一旦遇到错误则停止同步。&lt;/li&gt;
  &lt;li&gt;主从间的数据库不是实时同步，就算网络连接正常，也存在瞬间，主从数据不一致。&lt;/li&gt;
  &lt;li&gt;如果主从的网络断开，从会在网络正常后，批量同步。&lt;/li&gt;
  &lt;li&gt;如果对从进行修改数据，那么很可能从在执行主的bin-log时出现错误而停止同步，这个是很危险的操作。所以一般情况下，非常小心的修改从上的数据。&lt;/li&gt;
  &lt;li&gt;一个衍生的配置是双主，互为主从配置，只要双方的修改不冲突，可以工作良好。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;mysql同步主从配置&quot;&gt;&lt;strong&gt;Mysql同步主从配置&lt;/strong&gt;&lt;/h2&gt;
&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;1.实验环境:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;主服务器（Master）：192.168.1.10&lt;/li&gt;
  &lt;li&gt;从服务器（Slave）：192.168.1.11&lt;/li&gt;
  &lt;li&gt;两台机器都装有mysql。（注意：最好两个机器MySQL版本一致，或者从服务器的的版本比主服务器版本高，否则可能出现高版本的log文件拿到低版本的Mysql服务器上没办法执行。）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2.主服务器配置（Master配置）&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;创建mysql 的slave用户&lt;/strong&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  grant replication slave on *.* to slave@192.168.1.11 identified by 'slave';
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;这里的IP地址是从服务器的IP地址。&lt;br /&gt;
  replication slave 为mysql同步的必须权限，此处不要授权all权限.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;修改master的mysql配置文件 my.ini(Windows) 或 my.cnf(Linux)&lt;/strong&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  #设置 server id(server-id=1中的1可以任定义，只要是唯一的就行。)
  server-id=1 

  # 打开二进制日志 ，最好放在不同的硬盘上，减小 IO 消耗
  log-bin= mysql-binlog

  # 设置二进制日志保存日期
  expire_logs_day=10

  # 设置 每个 binlog 文件的大小
  max_binlog_size=500M

  # 设置需要备份的数据库
  binlog-do-db=back

  # 设置忽略备份的数据库
  binlog_ignore_db=mysql
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;重启Mysql&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;Windows：&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  net stop mysql;
  net start mysql;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Linux：&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  service mysql restart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;获取相关的db信息, 供slave链接db时使用&lt;/strong&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  mysql&amp;gt; show master status;
  +------------------+----------+--------------+------------------+-------------------+
  | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
  +------------------+----------+--------------+------------------+-------------------+
  | mysql_bin.000008 |      452 | back         |                  |                   |
  +------------------+----------+--------------+------------------+-------------------+
  1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3.从服务器配置（Slave配置）&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;修改Slave的mysql配置文件 my.ini(Windows) 或 my.cnf(Linux)&lt;/strong&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  # 设置 server id(server-id=2中的2可以任定义，只要是唯一的就行。)
  server-id=2 
	
  # 指定slave要复制哪个库
  replicate-do-db=back
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;启动从服务器上的复制线程&lt;/strong&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  start slave;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;检查主从同步&lt;/strong&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  mysql&amp;gt; show slave status\G;
  *************************** 1. row ***************************
                 Slave_IO_State: Waiting for master to send event
                    Master_Host: 192.168.1.10
                    Master_User: slave
                    Master_Port: 3306
                  Connect_Retry: 60
                Master_Log_File: mysql_bin.000008
            Read_Master_Log_Pos: 452
                 Relay_Log_File: WangPC-relay-bin.000004
                  Relay_Log_Pos: 320
          Relay_Master_Log_File: mysql_bin.000008
               Slave_IO_Running: Yes
              Slave_SQL_Running: Yes
                Replicate_Do_DB: back
            Replicate_Ignore_DB:
             Replicate_Do_Table:
         Replicate_Ignore_Table:
        Replicate_Wild_Do_Table:
    Replicate_Wild_Ignore_Table:
                     Last_Errno: 0
                     Last_Error:
                   Skip_Counter: 0
            Exec_Master_Log_Pos: 452
                Relay_Log_Space: 528
                Until_Condition: None
                 Until_Log_File:
                  Until_Log_Pos: 0
             Master_SSL_Allowed: No
             Master_SSL_CA_File:
             Master_SSL_CA_Path:
                Master_SSL_Cert:
              Master_SSL_Cipher:
                 Master_SSL_Key:
          Seconds_Behind_Master: 0
  Master_SSL_Verify_Server_Cert: No
                  Last_IO_Errno: 0
                  Last_IO_Error:
                 Last_SQL_Errno: 0
                 Last_SQL_Error:
    Replicate_Ignore_Server_Ids:
               Master_Server_Id: 1
                    Master_UUID: 3613c664-b7f7-11e7-9c73-005056c00001
               Master_Info_File: C:\ProgramData\MySQL\MySQL Server 5.7\Data\master.info
                      SQL_Delay: 0
            SQL_Remaining_Delay: NULL
        Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
             Master_Retry_Count: 86400
                    Master_Bind:
        Last_IO_Error_Timestamp:
       Last_SQL_Error_Timestamp:
                 Master_SSL_Crl:
             Master_SSL_Crlpath:
             Retrieved_Gtid_Set:
              Executed_Gtid_Set:
                  Auto_Position: 0
           Replicate_Rewrite_DB:
                   Channel_Name:
             Master_TLS_Version:
  1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;如果您看到Slave_IO_Running和Slave_SQL_Running均为Yes，则主从复制连接正常。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

</description>
        <pubDate>Wed, 25 Apr 2018 00:00:00 +0000</pubDate>
        <link>https://kyleng.github.io/mysql/mysql_replaction</link>
        <guid isPermaLink="true">https://kyleng.github.io/mysql/mysql_replaction</guid>
        
        <category>Mysql</category>
        
        
        <category>Mysql</category>
        
      </item>
    
      <item>
        <title>Solr-安装与配置</title>
        <description>&lt;h2 id=&quot;solr是什么&quot;&gt;&lt;strong&gt;Solr是什么&lt;/strong&gt;&lt;/h2&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
  &lt;p&gt;Solr是一个独立的企业级搜索应用服务器，它对外提供类似于Web-service的API接口。用户可以通过http请求，向搜索引擎服务器提交一定格式的XML文件，生成索引；也可以通过Http Get操作提出查找请求，并得到XML格式的返回结果。&lt;/p&gt;

  &lt;p&gt;Solr是一个高性能，采用Java5开发，基于Lucene的全文搜索服务器。同时对其进行了扩展，提供了比Lucene更为丰富的查询语言，同时实现了可配置、可扩展并对查询性能进行了优化，并且提供了一个完善的功能管理界面，是一款非常优秀的全文搜索引擎。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;以上摘自百度百科&lt;/p&gt;

&lt;h2 id=&quot;安装环境与版本&quot;&gt;&lt;strong&gt;安装环境与版本&lt;/strong&gt;&lt;/h2&gt;

&lt;h3 id=&quot;windows下安装&quot;&gt;Windows下安装&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;solr版本：Apache Solr 7.2.1&lt;/li&gt;
  &lt;li&gt;操作系统：windows10&lt;/li&gt;
  &lt;li&gt;Tomcat版本：apache-tomcat-9.0.6&lt;/li&gt;
  &lt;li&gt;JDK版本：1.8.0_121&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;一下载解压solr安装包&quot;&gt;一.下载解压solr安装包&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://www.apache.org/dyn/closer.lua/lucene/solr/7.2.1&quot;&gt;下载地址&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;点击下图第一个链接&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blog-1255865654.cos.ap-beijing.myqcloud.com/solr/01.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;点击下图最后一个链接&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blog-1255865654.cos.ap-beijing.myqcloud.com/solr/02.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;下载解压之后目录如下下图
&lt;img src=&quot;https://blog-1255865654.cos.ap-beijing.myqcloud.com/solr/03.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;bin ： Windows及Linux下的可执行文件&lt;/li&gt;
  &lt;li&gt;contrib：solr扩展库（solr的一些贡献软件/插件，用于增强solr的功能）&lt;/li&gt;
  &lt;li&gt;dist ：solr编译（build）过程的jar包文件，以及相关的jar包引用&lt;/li&gt;
  &lt;li&gt;docs：API文档&lt;/li&gt;
  &lt;li&gt;example：solr的工程例子&lt;/li&gt;
  &lt;li&gt;licenses：和solr相关的一些许可信息&lt;/li&gt;
  &lt;li&gt;server：solr web应用（webapps）相关配置（lib、conf、web.xml…）&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;二将solr配置到容器&quot;&gt;二.将solr配置到容器&lt;/h3&gt;

&lt;p&gt;solr默认容器是Jetty，这里不做介绍，下面介绍一下讲solr配置到Tomcat容器中。&lt;/p&gt;

&lt;h4 id=&quot;tomcat中solr项目配置&quot;&gt;Tomcat中solr项目配置&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. 将解压后的solr-7.2.1\server\solr-webapp\webapp文件夹拷贝到tomcat安装目录下的webapps文件夹中，并重命名为solr&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.将解压后的solr-7.2.1\server\lib\ext目录下的所有jar包、solr-7.2.1\dist下的solr-dataimporthandler-7.2.1.jar、solr-dataimporthandler-extras-7.2.1.jar和solr\server\lib下metrics开头的5个jar和gmetric4j-1.0.7.jar 粘贴复制到tomcat下的solr项目的WEB-INF\lib目录下&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.在tomcat安装目录下的webapps\solr\WEB-INF中，新建一个classes文件夹，将解压后的solr-7.2.1\server\resources内的log4j.properties文件拷贝到里面&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.修改tomcat安装目录下bin文件夹中的catalina.bat，添加solr.log.dir系统变量, 指定solr日志记录存放地址（面创建的logs文件夹路径在solr的安装目录下，后面会提到）。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://blog-1255865654.cos.ap-beijing.myqcloud.com/solr/04.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;set &quot;JAVA_OPTS=%JAVA_OPTS% -Dsolr.log.dir=D:\solr_home\logs&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;5.修改tomcat安装目录下webapps\solr\WEB-INF内的web.xml文件&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;修改前：
&lt;img src=&quot;https://blog-1255865654.cos.ap-beijing.myqcloud.com/solr/05.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;修改后：
&lt;img src=&quot;https://blog-1255865654.cos.ap-beijing.myqcloud.com/solr/06.PNG&quot; alt=&quot;&quot; /&gt;
&lt;strong&gt;env-entry-value的值是上面创建solr_home的地址。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;去掉权限，将web.xml中的以下内容注释了，否则待会访问solr的index.html的时候，会出现403错误。&lt;/strong&gt;
&lt;img src=&quot;https://blog-1255865654.cos.ap-beijing.myqcloud.com/solr/07.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;solr的安装目录配置&quot;&gt;solr的安装目录配置&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1.创建一个solr_home的文件夹作为solr的安装目录，如：D:\solr_home，并且拷贝solr-7.2.1\server\solr内的所有文件到solr_home的文件夹中（即solr的安装目录）&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.solr安装目录下创建logs（上面第四步配置的）文件夹和newcore文件夹，并且复制solr_home\configsets_default下的conf文件夹到newcore文件夹下&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.拷贝solr-7.2.1\contrib和solr-7.2.1\dist内的所有文件到solr_home的文件夹中，并且修改\solr_home\newcore\conf文件夹里solrconfig.xml文件如下图&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;修改前
&lt;img src=&quot;https://blog-1255865654.cos.ap-beijing.myqcloud.com/solr/08.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;修改后
&lt;img src=&quot;https://blog-1255865654.cos.ap-beijing.myqcloud.com/solr/09.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;三启动solr&quot;&gt;三.启动solr&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;启动Tomcat&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;查看solr, http://localhost:8080/solr/index.html#/&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://blog-1255865654.cos.ap-beijing.myqcloud.com/solr/10.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;切换到Core Admin选项卡，基于我们solr_home文件夹下的newcore文件夹，手动创建一个core最后按Add Core按钮生成core&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://blog-1255865654.cos.ap-beijing.myqcloud.com/solr/11.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;instanceDir:  solr安装目录下的new_core文件夹的路径&lt;/li&gt;
  &lt;li&gt;dataDir: solr安装目录下的new_core\data文件夹的路径&lt;/li&gt;
  &lt;li&gt;config: solr安装目录下的new_core\conf\solrconfig.xml文件的路径&lt;/li&gt;
  &lt;li&gt;schema: solr安装目录下的new_core\conf\managed-schema文件的路径（此版本之前还是schema.xml来配置）&lt;/li&gt;
&lt;/ol&gt;

</description>
        <pubDate>Sun, 18 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://kyleng.github.io/solr/solr1</link>
        <guid isPermaLink="true">https://kyleng.github.io/solr/solr1</guid>
        
        <category>Solr</category>
        
        
        <category>Solr</category>
        
      </item>
    
      <item>
        <title>设计模式----代理模式</title>
        <description>&lt;h2 id=&quot;一&quot;&gt;一.&lt;/h2&gt;

&lt;h2 id=&quot;二&quot;&gt;二.&lt;/h2&gt;

&lt;h2 id=&quot;三&quot;&gt;三.&lt;/h2&gt;
</description>
        <pubDate>Fri, 01 Sep 2017 00:00:00 +0000</pubDate>
        <link>https://kyleng.github.io/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F(designpattern)/DesignPatterns_Proxy</link>
        <guid isPermaLink="true">https://kyleng.github.io/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F(designpattern)/DesignPatterns_Proxy</guid>
        
        <category>DesignPattern</category>
        
        
        <category>设计模式(DesignPattern)</category>
        
      </item>
    
      <item>
        <title>Zookeeper（二）</title>
        <description>&lt;h2 id=&quot;四zookeeper的javaapi&quot;&gt;四.Zookeeper的javaAPI&lt;/h2&gt;
&lt;p&gt;org.apache.zookeeper.Zookeeper是客户端入口主类，负责建立与server的会话
它提供了如下所示几类主要方法&lt;/p&gt;

&lt;h3 id=&quot;1主要方法概要&quot;&gt;1.主要方法概要&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;create ———— 在本地目录树中创建一个节点&lt;/li&gt;
  &lt;li&gt;delete ———— 删除一个节点&lt;/li&gt;
  &lt;li&gt;exists ———— 测试本地是否存在目标节点&lt;/li&gt;
  &lt;li&gt;get/set data —— 从目标节点上读取 / 写数据&lt;/li&gt;
  &lt;li&gt;get/set ACL ——- 获取 / 设置目标节点访问控制列表信息&lt;/li&gt;
  &lt;li&gt;get children —— 检索一个子节点上的列表&lt;/li&gt;
  &lt;li&gt;sync ————– 等待要被传送的数据&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;2增删改查基本操作&quot;&gt;2.增删改查基本操作&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;创建客户端并连接&lt;/strong&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; private static final String connectString = &quot;kyle001:2181,kyle002:2181,kyle003:2181&quot;;
 // timeout时间
 private static final int sessionTimeout = 2000;

 ZooKeeper zkClient = null;

 public void init() throws Exception {
     // 创建客户端对象
     zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
         @Override
         public void process(WatchedEvent event) {
             // 收到事件通知后的回调函数（应该是我们自己的事件处理逻辑）
             System.out.println(event.getType() + &quot;---&quot; + event.getPath());
             try {
                 // 对根目录进行监听，由于监听事件触发一次即完成，所以要不断重新监听
                 zkClient.getChildren(&quot;/&quot;, true);
             } catch (Exception e) {
             }
         }
     });
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;创建节点&lt;/strong&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; /**
  * 创建节点
  * @throws KeeperException
  * @throws InterruptedException
  */
 public void createZnode() throws KeeperException, InterruptedException {
     // 参数1：要创建的节点的路径 
     // 参数2：节点数据  数据类型是byte类型，也就是说一个配置文件转换成byte也可以保存
     // 参数3：节点的权限  Ids类的
     // 参数4：节点的类型 枚举类型，对应四种类别的节点
     // 上传的数据可以是任何类型，但都要转成byte[]
     String nodeCreated = zkClient.create(&quot;/JAVAClient&quot;, &quot;helloZK&quot;.getBytes(), Ids.OPEN_ACL_UNSAFE,
             CreateMode.PERSISTENT);
     System.out.println(&quot;创建节点成功&quot; + nodeCreated);
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;判断节点是否存在&lt;/strong&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; /**
  * 判断节点是否存在
  * @throws KeeperException
  * @throws InterruptedException
  */
 public void checkZnode() throws KeeperException, InterruptedException {
     // 参数1：节点的路径 
     // 参数2：是否对节点进行监听
     Stat stat = zkClient.exists(&quot;/JAVAClient&quot;, false);
     System.out.println(stat == null ? &quot;not exist&quot; : &quot;exist&quot;);
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;获取子节点&lt;/strong&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; /**
  * 获取子节点
  * @throws Exception
  */
 public void getChildren() throws Exception {
     // 参数1：节点的路径 
     // 参数2：是否对节点进行监听
     List&amp;lt;String&amp;gt; children = zkClient.getChildren(&quot;/&quot;, true);
     for (String child : children) {
         System.out.println(child);
     }
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;获取节点数据&lt;/strong&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; /**
  * 获取节点数据
  * @throws Exception
  */
 public void getData() throws Exception {
     // 参数1：节点路径
     // 参数2：是否 对节点监听
     // 参数3：节点状态（方便定位获取版本）
     byte[] data = zkClient.getData(&quot;/JAVAClient&quot;, false, null);
     System.out.println(new String(data));

 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;修改节点内容&lt;/strong&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; /**
  * 修改节点内容
  * @throws Exception
  */
 public void setData() throws Exception {

     // 参数1：阶段路径
     // 参数2：修改的内容
     // 参数3：指定要修改的版本，-1表示删除所有版本
     Stat setData = zkClient.setData(&quot;/JAVAClient&quot;, &quot;helloZookeeper&quot;.getBytes(), -1);
     System.out.println(setData.toString());
     byte[] data = zkClient.getData(&quot;/JAVAClient&quot;, false, null);
     System.out.println(new String(data));

 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;删除节点&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; /**
  * 删除节点
  * @throws Exception
  */
 public void deleteZnode() throws Exception {

     // 参数1：阶段路径
     // 参数2：指定要删除的版本，-1表示删除所有版本
     // Delete the node with the given path. 
     // The call will succeed if such a node exists, 
     // and the given version matches the node's version
     // (if the given version is -1, it matches any node's versions). 
     zkClient.delete(&quot;/JAVAClient&quot;, -1);

 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;
</description>
        <pubDate>Wed, 08 Jun 2016 00:00:00 +0000</pubDate>
        <link>https://kyleng.github.io/zookeeper/zookeeper2</link>
        <guid isPermaLink="true">https://kyleng.github.io/zookeeper/zookeeper2</guid>
        
        <category>Zookeeper</category>
        
        
        <category>Zookeeper</category>
        
      </item>
    
      <item>
        <title>Zookeeper（一）</title>
        <description>&lt;h2 id=&quot;一zookeeper概念简介&quot;&gt;一.Zookeeper概念简介&lt;/h2&gt;
&lt;p&gt;Zookeeper是一个分布式协调服务；就是为用户的分布式应用程序提供协调服务&lt;br /&gt;
主要包括主从协调、服务器节点动态上下线、统一配置管理、分布式共享锁、统一名称服务……&lt;br /&gt;
通俗的说Zookeeper主要包含两个功能：&lt;br /&gt;
1）管理(存储，读取)用户程序提交的数据；&lt;br /&gt;
2）为用户程序提供数据节点监听服务；&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：半数机制：集群中半数以上机器存活，集群可用。
zookeeper适合装在奇数台机器上！！！&lt;/p&gt;

&lt;h2 id=&quot;二安装&quot;&gt;二.安装&lt;/h2&gt;

&lt;p&gt;本文中以三台机器为例&lt;br /&gt;
安装前请检查机器都可以相互ssh免密登陆，确保JDK已经安装正确，安装包已经上传至服务器。&lt;br /&gt;
&lt;a href=&quot;http://zookeeper.apache.org/&quot; title=&quot;Zookeeper官网&quot;&gt;Zookeeper官网&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;1解压安装包&quot;&gt;1，解压安装包&lt;/h3&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tar -zxvf zookeeper-3.4.9.tar.gz -C /opt/
# 把解压后文件夹复制到其他两台机器
scp -r /opt/zookeeper-3.4.9/ kyle002:/opt/
scp -r /opt/zookeeper-3.4.9/ kyle003:/opt/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2修改环境变量&quot;&gt;2，修改环境变量&lt;/h3&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo vim /etc/profile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在文件结尾加上下面两句环境变量配置&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;export ZOOKEEPER_HOME=/opt/zookeeper-3.4.9
export PATH=$PATH:\$ZOOKEEPER_HOME/bin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;http://img.blog.csdn.net/20170611230526583&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;重新加载profile文件&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;source /etc/profile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;3修改配置文件&quot;&gt;3，修改配置文件&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cp /opt/zookeeper-3.4.9/conf/zoo_sample.cfg /opt/zookeeper-3.4.9/conf/zoo.cfg
vim /opt/zookeeper-3.4.9/conf/zoo.cfg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;http://img.blog.csdn.net/20170611230548240&quot; alt=&quot;&quot; /&gt;
配置文件修改如下&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=/home/hadoop/zookeeper/data
dataLogDir=/home/hadoop/zookeeper/log
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to &quot;0&quot; to disable auto purge feature
#autopurge.purgeInterval=1
server.1=kyle001:2888:3888
server.2=kyle002:2888:3888
server.3=kyle003:2888:3888
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;创建配置文件中配置的文件夹&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mkdir 755 -p /home/hadoop/zookeeper/data /home/hadoop/zookeeper/log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;data文件夹下新建myid，每台机器的文件内容要跟配置文件一致&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# 集群中每台机器都要配置
echo 1 &amp;gt; /home/hadoop/zookeeper/data/maid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;4测试安装结果&quot;&gt;4，测试安装结果&lt;/h3&gt;
&lt;p&gt;启动（每台机器）&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[hadoop@kyle001 data]$ /opt/zookeeper-3.4.9/bin/zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.4.9/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

# 想要在一台机器上远程启动需要注意：需要先source下资源&amp;lt;br&amp;gt;
ssh kyle002 &quot;source /etc/profile;/opt/zookeeper-3.4.9/bin/zkServer.sh start&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;全部启动之后查看状态&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[hadoop@kyle003 data]$ /opt/zookeeper-3.4.9/bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.4.9/bin/../conf/zoo.cfg
Mode: follower 注意：Mode还有可能是leader&amp;lt;br&amp;gt; 用jps查看

[hadoop@kyle002 data]$ jps
1588 QuorumPeerMain
1647 Jps QuorumPeerMain就是zookeeper任务
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;三zookeeper结构和命令&quot;&gt;三.zookeeper结构和命令&lt;/h2&gt;
&lt;h3 id=&quot;1zookeeper特性&quot;&gt;1，zookeeper特性&lt;/h3&gt;
&lt;p&gt;Zookeeper：一个leader，多个follower组成的集群&lt;br /&gt;
全局数据一致：每个server保存一份相同的数据副本，client无论连接到哪个server，数据都是一致的&lt;br /&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;分布式读写，更新请求转发，由leader实施。&lt;br /&gt;&lt;/li&gt;
  &lt;li&gt;来自同一个client的更新请求按其发送顺序依次执行。&lt;br /&gt;&lt;/li&gt;
  &lt;li&gt;数据更新原子性，一次数据更新要么成功，要么失败。&lt;br /&gt;&lt;/li&gt;
  &lt;li&gt;实时性，在一定时间范围内，client能读到最新数据。
    &lt;h3 id=&quot;2zookeeper数据结构&quot;&gt;2，zookeeper数据结构&lt;/h3&gt;
    &lt;p&gt;层次化的目录结构，命名符合常规文件系统规范(见下图)&lt;br /&gt;
每个节点在zookeeper中叫做znode,并且其有一个唯一的路径标识&lt;br /&gt;
节点Znode可以包含数据和子节点（但是EPHEMERAL类型的节点不能有子节点）&lt;br /&gt;
客户端应用可以在节点上设置监视器（后续详细讲解）&lt;br /&gt;&lt;br /&gt;
&lt;img src=&quot;http://img.blog.csdn.net/20170611204938948&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
    &lt;h3 id=&quot;3节点类型&quot;&gt;3，节点类型&lt;/h3&gt;
    &lt;p&gt;Znode有两种类型：&lt;br /&gt;
短暂（ephemeral）（断开连接自己删除）&lt;br /&gt;
持久（persistent）（断开连接不删除）&lt;br /&gt;
Znode有四种形式的目录节点（默认是persistent ）:&lt;br /&gt;
PERSISTENT&lt;br /&gt;
PERSISTENT_SEQUENTIAL（持久序列/test0000000019 ）&lt;br /&gt;
EPHEMERAL&lt;br /&gt;
EPHEMERAL_SEQUENTIAL&lt;br /&gt;
创建znode时设置顺序标识，znode名称后会附加一个值，顺序号是一个单调递增的计数器，由父节点维护&lt;br /&gt;
在分布式系统中，顺序号可以被用于为所有的事件进行全局排序，这样客户端可以通过顺序号推断事件的顺序&lt;br /&gt;&lt;/p&gt;
    &lt;h3 id=&quot;4zookeeper命令行操作&quot;&gt;4，zookeeper命令行操作&lt;/h3&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;启动命令行客户端：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[hadoop@kyle001 ~]$ /opt/zookeeper-3.4.9/bin/zkCli.sh 
Connecting to localhost:2181
2017-06-12 06:06:11,483 [myid:] - INFO  [main:Environment@100] - Client environment:zookeeper.version=3.4.9-1757313, built on 08/23/2016 06:50 GMT
2017-06-12 06:06:11,488 [myid:] - INFO  [main:Environment@100] - Client environment:host.name=kyle001
2017-06-12 06:06:11,489 [myid:] - INFO  [main:Environment@100] - Client environment:java.version=1.8.0_131
2017-06-12 06:06:11,493 [myid:] - INFO  [main:Environment@100] - Client environment:java.vendor=Oracle Corporation
2017-06-12 06:06:11,494 [myid:] - INFO  [main:Environment@100] - Client environment:java.home=/soft/jdk1.8.0_131/jre
2017-06-12 06:06:11,494 [myid:] - INFO  [main:Environment@100] - Client environment:java.class.path=/opt/zookeeper-3.4.9/bin/../build/classes:/opt/zookeeper-3.4.9/bin/../build/lib/*.jar:/opt/zookeeper-3.4.9/bin/../lib/slf4j-log4j12-1.6.1.jar:/opt/zookeeper-3.4.9/bin/../lib/slf4j-api-1.6.1.jar:/opt/zookeeper-3.4.9/bin/../lib/netty-3.10.5.Final.jar:/opt/zookeeper-3.4.9/bin/../lib/log4j-1.2.16.jar:/opt/zookeeper-3.4.9/bin/../lib/jline-0.9.94.jar:/opt/zookeeper-3.4.9/bin/../zookeeper-3.4.9.jar:/opt/zookeeper-3.4.9/bin/../src/java/lib/*.jar:/opt/zookeeper-3.4.9/bin/../conf:
2017-06-12 06:06:11,494 [myid:] - INFO  [main:Environment@100] - Client environment:java.library.path=/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
2017-06-12 06:06:11,494 [myid:] - INFO  [main:Environment@100] - Client environment:java.io.tmpdir=/tmp
2017-06-12 06:06:11,494 [myid:] - INFO  [main:Environment@100] - Client environment:java.compiler=&amp;lt;NA&amp;gt;
2017-06-12 06:06:11,494 [myid:] - INFO  [main:Environment@100] - Client environment:os.name=Linux
2017-06-12 06:06:11,495 [myid:] - INFO  [main:Environment@100] - Client environment:os.arch=amd64
2017-06-12 06:06:11,495 [myid:] - INFO  [main:Environment@100] - Client environment:os.version=2.6.32-696.el6.x86_64
2017-06-12 06:06:11,495 [myid:] - INFO  [main:Environment@100] - Client environment:user.name=hadoop
2017-06-12 06:06:11,495 [myid:] - INFO  [main:Environment@100] - Client environment:user.home=/home/hadoop
2017-06-12 06:06:11,495 [myid:] - INFO  [main:Environment@100] - Client environment:user.dir=/home/hadoop
2017-06-12 06:06:11,500 [myid:] - INFO  [main:ZooKeeper@438] - Initiating client connection, connectString=localhost:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@446cdf90
Welcome to ZooKeeper!
2017-06-12 06:06:11,597 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1032] - Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
JLine support is enabled
2017-06-12 06:06:11,815 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@876] - Socket connection established to localhost/127.0.0.1:2181, initiating session
2017-06-12 06:06:11,957 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1299] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x15c992d06310000, negotiated timeout = 30000

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
[zk: localhost:2181(CONNECTED) 0] 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;1、使用 ls 命令来查看当前 ZooKeeper 中所包含的内容：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 0] ls /
[zookeeper]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;2、创建一个新的 znode ，使用 create /zk myData 。这个命令创建了一个新的 znode 节点“ zk ”以及与它关联的字符串：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 1] create /zk &quot;mydata&quot;
Created /zk
[zk: localhost:2181(CONNECTED) 2] 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：create -e /zk “mydata”就会创建一个短暂的节点（默认创建的是持久节点），在客户端quite的时候一起消失。&lt;/p&gt;

&lt;p&gt;3、运行 get 命令来确认 znode 的字符串：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 2] get /zk
mydata
cZxid = 0x400000002
ctime = Mon Jun 12 06:15:09 CST 2017
mZxid = 0x400000002
mtime = Mon Jun 12 06:15:09 CST 2017
pZxid = 0x400000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
[zk: localhost:2181(CONNECTED) 3] 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;4、监听某个节点的变化：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：监听这个节点的客户端会出现提示信息，这种监听只能监听一次变化&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 3] get /zk watch
mydata
cZxid = 0x400000002
ctime = Mon Jun 12 06:15:09 CST 2017
mZxid = 0x400000002
mtime = Mon Jun 12 06:15:09 CST 2017
pZxid = 0x400000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;5、通过 set 命令来对 zk 所关联的字符串进行设置：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 1] set /zk &quot;UpdateData&quot;
cZxid = 0x400000002
ctime = Mon Jun 12 06:15:09 CST 2017
mZxid = 0x400000004
mtime = Mon Jun 12 06:25:48 CST 2017
pZxid = 0x400000002
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 10
numChildren = 0
[zk: localhost:2181(CONNECTED) 2] 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果在4步设置监听之后再设置节点信息监听事件就会起作用，如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 4] 
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/zk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;6、删除节点&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 6] delete /zk
[zk: localhost:2181(CONNECTED) 7] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 8]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;7、递归删除节点：rmr&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[zk: localhost:2181(CONNECTED) 11] ls /
[zookeeper, test]
[zk: localhost:2181(CONNECTED) 12] ls /test
[haha]
[zk: localhost:2181(CONNECTED) 13] rmr /test
[zk: localhost:2181(CONNECTED) 14] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 15]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Wed, 08 Jun 2016 00:00:00 +0000</pubDate>
        <link>https://kyleng.github.io/zookeeper/zookeeper1</link>
        <guid isPermaLink="true">https://kyleng.github.io/zookeeper/zookeeper1</guid>
        
        <category>Zookeeper</category>
        
        
        <category>Zookeeper</category>
        
      </item>
    
      <item>
        <title>JavaWeb--Servlet</title>
        <description>&lt;h3 id=&quot;servlet是什么&quot;&gt;&lt;strong&gt;Servlet是什么&lt;/strong&gt;&lt;/h3&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
  &lt;p&gt;Servlet（Server Applet）是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据，生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口，广义的Servlet是指任何实现了这个Servlet接口的类，一般情况下，人们将Servlet理解为后者。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;以上摘自维基百科，通俗的说，Servlet是一个java接口，适用于B/S架构中的请求处理。&lt;/p&gt;

&lt;h3 id=&quot;初识servlet&quot;&gt;初识Servlet&lt;/h3&gt;
&lt;hr /&gt;
&lt;p&gt;既然Servlet是一个接口，那按照常规做法就先创建一个类去实现这个接口，是不是就可以处理浏览器发过来的请求呢？答案肯定不是，那么怎样才能处理呢？这时就可以用一个Web应用服务器Tomcat,WebLogic,WebSphere,Jetty等负责处理客户请求,把请求传送给Servlet,并将Servlet的响应传送回给客户。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;创建一个web工程&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;&lt;a href=&quot;http://blog.csdn.net/u014079773/article/details/51397850&quot;&gt;创建方式请参考网友博客&lt;/a&gt;&lt;br /&gt;
 完成之后目录结构大概是这个样子&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;https://blog-1255865654.cos.ap-beijing.myqcloud.com/sevlet/servlet01.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;创建一个Servlet接口的实现类&lt;/strong&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; package com.kyle.study01;

 import java.io.IOException;
 import javax.servlet.Servlet;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
	
 public class HelloServlet implements Servlet {
	
     @Override
     public void destroy() {
         System.out.println(&quot;destroy&quot;);
	
     }
	
     @Override
     public ServletConfig getServletConfig() {
         System.out.println(&quot;getServletConfig&quot;);
         return null;
     }
	
     @Override
     public String getServletInfo() {
         System.out.println(&quot;getServletInfo&quot;);
         return null;
     }
	
     @Override
     public void init(ServletConfig arg0) throws ServletException {
         System.out.println(&quot;init&quot;);
     }
	
     @Override
     public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
         System.out.println(&quot;service&quot;);
     }
	
     public HelloServlet() {
         System.out.println(&quot;HelloServlet constructor&quot;);
     }
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;为测试方便在每个重写方法中加入一句打印方法名，并且加入构造函数。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;在web.xml中配置这个Servlet&lt;/strong&gt;&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &amp;lt;!-- 配置和映射 Servlet --&amp;gt;
 &amp;lt;servlet&amp;gt;
     &amp;lt;servlet-name&amp;gt;helloservlet&amp;lt;/servlet-name&amp;gt;
     &amp;lt;!-- 类的全路径名 --&amp;gt;
     &amp;lt;servlet-class&amp;gt;com.kyle.study01.HelloServlet&amp;lt;/servlet-class&amp;gt;
 &amp;lt;/servlet&amp;gt;
 &amp;lt;servlet-mapping&amp;gt;
     &amp;lt;servlet-name&amp;gt;helloservlet&amp;lt;/servlet-name&amp;gt;
     &amp;lt;!-- / 代表项目根目录 --&amp;gt;
     &amp;lt;url-pattern&amp;gt;/hello&amp;lt;/url-pattern&amp;gt;
 &amp;lt;/servlet-mapping&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;在Tomcat中发布此项目&lt;/strong&gt;&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;在浏览器中输入http://localhost:8080/ServletStudy/hello&lt;/p&gt;

        &lt;p&gt;控制台输出：&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; HelloServlet constructor
 init
 service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;多次刷新浏览器&lt;/p&gt;

        &lt;p&gt;控制态输出：&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; service
 service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;右键Tomcat停止服务器&lt;/p&gt;

        &lt;p&gt;控制态输出：&lt;/p&gt;

        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; destroy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ol&gt;

    &lt;p&gt;如下图：&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;https://blog-1255865654.cos.ap-beijing.myqcloud.com/sevlet/Servlet03.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;servlet的生命周期&quot;&gt;Servlet的生命周期&lt;/h3&gt;
&lt;hr /&gt;

&lt;p&gt;结合上面的例子已经对Servlet有了一个初步的了解，下面来详细说一下Servlet的各个生命周期方法。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Servlet 通过调用 init () 方法进行初始化。&lt;/li&gt;
  &lt;li&gt;Servlet 调用 service() 方法来处理客户端的请求。&lt;/li&gt;
  &lt;li&gt;Servlet 通过调用 destroy() 方法终止（结束）。&lt;/li&gt;
  &lt;li&gt;最后，Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://blog-1255865654.cos.ap-beijing.myqcloud.com/sevlet/Servlet-LifeCycle.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;init(ServletConfig arg0) 方法&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用，在后续每次用户请求时不再调用。因此，它是用于一次性初始化，就像 Applet 的 init 方法一样。&lt;br /&gt;
 Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时，但是您也可以指定 Servlet 在服务器第一次启动时被加载。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;service(ServletRequest arg0, ServletResponse arg1) 方法&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;service() 方法是执行实际任务的主要方法。Servlet 容器（即 Web 服务器）调用 service() 方法来处理来自客户端（浏览器）的请求，并把格式化的响应写回给客户端。&lt;br /&gt;
 每次服务器接收到一个 Servlet 请求时，服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型（GET、POST、PUT、DELETE 等），并在适当的时候调用 doGet、doPost、doPut，doDelete 等方法。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;destroy() 方法&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;destroy() 方法只会被调用一次，在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘，并执行其他类似的清理活动。&lt;br /&gt;
 在调用 destroy() 方法之后，servlet 对象被标记为垃圾回收。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;构造器方法&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;从上面例子可以看出多次刷浏览器网址构造方法只被调用了一次，由此可见在之后的两次调用service方法时候都是同一个Servlet对象,因此可以推断Servlet是单例的。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;servlet的单实例多线程&quot;&gt;Servlet的单实例多线程&lt;/h3&gt;
&lt;hr /&gt;
&lt;p&gt;从上面可以得知一个servlet是在第一次被访问时加载到内存并实例化的。同样的业务请求共享一个servlet实例。不同的业务请求一般对应不同的servlet。&lt;br /&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 15 Apr 2016 00:00:00 +0000</pubDate>
        <link>https://kyleng.github.io/java/javaweb_Servlet</link>
        <guid isPermaLink="true">https://kyleng.github.io/java/javaweb_Servlet</guid>
        
        <category>servlet</category>
        
        
        <category>java</category>
        
      </item>
    
      <item>
        <title>Java--动态代理</title>
        <description>&lt;h2 id=&quot;动态代理概述&quot;&gt;动态代理概述&lt;/h2&gt;

&lt;p&gt;动态代理是指在运行时动态生成代理类。不需要像静态代理那个去手动写一个个的代理类。生成动态代理类有很多方式：Java动态代理，CGLIB，Javassist，ASM库等。这里主要说一下Java动态代理和CGLIB的实现。&lt;/p&gt;

&lt;h3 id=&quot;一-jdk动态代理-通过接口&quot;&gt;一 JDK动态代理—-通过接口&lt;/h3&gt;

&lt;p&gt;在java的动态代理机制中，有两个重要的类或接口，一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class)，这一个类和接口是实现动态代理所必须用到的。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;InvocationHandler:&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;每一个动态代理类都必须要实现InvocationHandler这个接口，并且每个代理类的实例都关联到了一个handler，当通过代理对象调用一个方法的时候，这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  /**
   * 
   * proxy:  指代所代理的那个真实对象
   * method: 指代的是所要调用真实对象的某个方法的Method对象
   * args:　　指代的是调用真实对象某个方法时接受的参数
   *
   */
  Object invoke(Object proxy, Method method, Object[] args) throws Throwable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Proxy:&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;这个代类有很多方法常用的方法就是newProxyInstance&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  /**
   * 
   * loader:  一个ClassLoader对象，定义了由哪个ClassLoader对象来对生成的代理对象进行加载
   * interfaces:  一个Interface对象的数组，表示的是我将要给我需要代理的对象提供一组什么接口，
   * 	如果提供了一组接口给它，那么这个代理对象就宣称实现了该接口(多态)，这样我就能调用这组接口中的方法了
   * h:  一个InvocationHandler对象，表示的是当我这个动态代理对象在调用方法的时候，会关联到哪一个InvocationHandler对象上
   *
   */
  public static Object newProxyInstance(ClassLoader loader, Class&amp;lt;?&amp;gt;[] interfaces,  InvocationHandler h)  throws IllegalArgumentException
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;一个例子：&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;定义一个Subject类型的接口:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; package com.kyle.DynamicProxy;
	
 public interface Subject {
		
     void hello(String str);
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;定义了一个类来实现这个接口，这个类就是真实对象，RealSubject类:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; package com.kyle.DynamicProxy;
	
 public class RealSubject implements Subject {
	
     @Override
     public void hello(String str) {
         System.out.println(&quot;hello: &quot; + str);
     }
	
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;定义一个动态代理类了，每一个动态代理类都必须要实现 InvocationHandler 这个接口，因此这个动态代理类也不例外:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; package com.kyle.DynamicProxy;
	
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
	
 public class DynamicProxy implements InvocationHandler {
	
     // 要代理的真实对象
     private Object subject;
	
     // 构造方法，要代理的真实对象赋初值
     public DynamicProxy(Object subject) {
         this.subject = subject;
     }
	
     @Override
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         // 在代理真实对象前我们可以添加一些自己的操作
         System.out.println(&quot;before Hello&quot;);
	
         System.out.println(&quot;Method:&quot; + method);
	
         // 当代理对象调用真实对象的方法时，其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
         method.invoke(subject, args);
	
         // 在代理真实对象后我们也可以添加一些自己的操作
         System.out.println(&quot;after Hello&quot;);
	
         return null;
     }
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;最后，定义Client类：&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Proxy;
	
 public class Client {
	
 public static void main(String[] args) {
		
     // 要代理的真实对象
     Subject realSubject = new RealSubject();
		
     // 要代理哪个真实对象，就将该对象传进去，最后是通过该真实对象来调用其方法的
     InvocationHandler handler = new DynamicProxy(realSubject);
	
     /*
      * 通过Proxy的newProxyInstance方法来创建我们的代理对象，三个参数 第一个参数
      * handler.getClass().getClassLoader()
      * ，这里使用handler这个类的ClassLoader对象来加载代理对象
      * 第二个参数realSubject.getClass().getInterfaces()，这里为代理对象提供的接口是真实对象所实行的接口
      * ，表示我要代理的是该真实对象，这样我就能调用这组接口中的方法了 第三个参数handler， 我们这里将这个代理对象关联到了上方的
      * InvocationHandler 这个对象上
      */
     Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(),
             realSubject.getClass().getInterfaces(), handler);
	
     System.out.println(subject.getClass().getName());
     subject.hello(&quot;world&quot;);
     }
	
 }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;控制台的输出：&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;com.sun.proxy.$Proxy0
before Hello
Method:public abstract void com.kyle.DynamicProxy.Subject.hello(java.lang.String)
hello: world  realSubject
after Hello
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;注：&lt;/strong&gt;通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象，它并不是我们的InvocationHandler类型，也不是我们定义的那组接口的类型，而是在运行是动态生成的一个对象，并且命名方式都是这样的形式，以$开头，proxy为中，最后一个数字表示对象的标号。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;对于JDK动态代理的疑问&lt;/strong&gt;
为什么java动态代理为什么一定要代理接口而不能代理类？
在动态代理经过编译之后的实现类似于以下结构：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public class $Proxy1 extends Proxy implements 传入的接口{
    
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;到这里应该很容易理解为什么这里需要代理接口而不是一个类，因为这个动态代理已经继承了Proxy这个类.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;延迟加载代理举例：&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;接口类：&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  package com.kyle.LazyLoad;
	
  public interface IDBExcute {
		
      String query();
	
      int update();
  }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;实现类：&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  package com.kyle.LazyLoad;
	
  public class DBExcute implements IDBExcute {
	
      String queryContent = &quot;Something from DB.&quot;;
	
      @Override
      public String query() {
          System.out.println(&quot;query is running...&quot;);
          // 模拟查询操作的返回结果
          return queryContent;
      }
	
      public DBExcute() {
          // 真实对象被创建时候打印信息
          System.out.println(&quot;Real object is created...&quot;);
      }
	
      @Override
      public int update() {
          System.out.println(&quot;update is running...&quot;);
          // 模拟更新操作影响的件数
          return 1;
      }
  }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;代理类：&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  package com.kyle.LazyLoad;
	
  import java.lang.reflect.InvocationHandler;
  import java.lang.reflect.Method;
	
  public class DBExcuteHandler implements InvocationHandler {
	
      // 定义主题接口
      IDBExcute dbQuery = null;
	
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          // 如果第一次调用，生成真实主题,创建真正要代理的类
          if (dbQuery == null) {
              dbQuery = new DBExcute();
          }
	
          // 返回真实主题完成实际的操作
          return method.invoke(dbQuery, args);
      }
  }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;测试类：&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  package com.kyle.LazyLoad;
	
  import java.lang.reflect.Proxy;
	
  public class Main {
	
      public static void main(String[] args) {
          System.out.println(&quot;开始获取代理对象&quot;);
          // 获取代理对象的时候真正的对象并没有被创建
          IDBExcute excute = (IDBExcute) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
                  new Class[] { IDBExcute.class }, new DBExcuteHandler());
          System.out.println(&quot;开始调用实际方法&quot;);
          // 当第一次调用实际对象方法的时候真正的对象才被创建
          String result = excute.query();
          System.out.println(&quot;查询方法结果： &quot; + result);
          int count = excute.update();
          System.out.println(&quot;更新结果： &quot; + count);
	
      }
  }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;控制台的输出：&lt;br /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;开始获取代理对象
开始调用实际方法
Real object is created...
query is running...
查询方法结果： Something from DB.
update is running...
更新结果： 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;二-cglib动态代理-通过类继承&quot;&gt;二 CGLIB动态代理—-通过类继承&lt;/h3&gt;
&lt;p&gt;未完待续。。。&lt;/p&gt;
</description>
        <pubDate>Mon, 04 Apr 2016 00:00:00 +0000</pubDate>
        <link>https://kyleng.github.io/java/java_DynamicProxy</link>
        <guid isPermaLink="true">https://kyleng.github.io/java/java_DynamicProxy</guid>
        
        <category>java，动态代理</category>
        
        
        <category>java</category>
        
      </item>
    
      <item>
        <title>Java多线程&amp;并发--Queue</title>
        <description>&lt;h2 id=&quot;java中并发queue种类&quot;&gt;Java中并发Queue种类&lt;/h2&gt;

&lt;p&gt;在并发编程中我们有时候需要使用线程安全的队列。如果我们要实现一个线程安全的队列有两种实现方式一种是使用&lt;strong&gt;阻塞算法&lt;/strong&gt;，另一种是使用&lt;strong&gt;非阻塞算法&lt;/strong&gt;。&lt;br /&gt;
&lt;strong&gt;阻塞算法:&lt;/strong&gt; BlockingQueue接口实现类，
&lt;strong&gt;非阻塞算法:&lt;/strong&gt; ConcurrentLinkedQueue类&lt;/p&gt;

&lt;h2 id=&quot;concurrentlinkedqueue&quot;&gt;ConcurrentLinkedQueue&lt;/h2&gt;

&lt;p&gt;ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列，它采用先进先出的规则对节点进行排序，当我们添加一个元素的时候，它会添加到队列的尾部，当我们获取一个元素时，它会返回队列头部的元素。因为是无锁方式实现，所以适合在高并发场景，性能要优于BlockingQueue接口实现的子类对象&lt;/p&gt;

&lt;h3 id=&quot;1使用cas算法来入队&quot;&gt;1,使用CAS算法来入队&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;public boolean offer(E e) {
        if (e == null) throw new NullPointerException();
        //入队前，创建一个入队节点
        Node&amp;lt;/e&amp;gt;&amp;lt;e&amp;gt; n = new Node&amp;lt;/e&amp;gt;&amp;lt;e&amp;gt;(e);
        retry:
        //死循环，入队不成功反复入队。
        for (;;) {
            //创建一个指向tail节点的引用
            Node&amp;lt;/e&amp;gt;&amp;lt;e&amp;gt; t = tail;
            //p用来表示队列的尾节点，默认情况下等于tail节点。
            Node&amp;lt;/e&amp;gt;&amp;lt;e&amp;gt; p = t;
            for (int hops = 0; ; hops++) {
            //获得p节点的下一个节点。
                Node&amp;lt;/e&amp;gt;&amp;lt;e&amp;gt; next = succ(p);
     			//next节点不为空，说明p不是尾节点，需要更新p后在将它指向next节点
                if (next != null) {
                   //循环了两次及其以上，并且当前节点还是不等于尾节点
                    if (hops &amp;gt; HOPS &amp;amp;&amp;amp; t != tail)
                        continue retry;
                    p = next;
                }
                //如果p是尾节点，则设置p节点的next节点为入队节点。
                else if (p.casNext(null, n)) {
                  //如果tail节点有大于等于1个next节点，则将入队节点设置成tair节点，更新失败了也没关系，因为失败了表示有其他线程成功更新了tair节点。
					if (hops &amp;gt;= HOPS)
                        casTail(t, n); // 更新tail节点，允许失败
                    return true;
                }
               // p有next节点,表示p的next节点是尾节点，则重新设置p节点
                else {
                    p = succ(p);
                }
            }
        }
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;blockingqueue接口&quot;&gt;BlockingQueue接口&lt;/h2&gt;

&lt;p&gt;BlockingQueue 是个接口，需要使用它的实现之一来使用 BlockingQueue。java.util.concurrent 具有以下 BlockingQueue 接口的实现(Java 6)：&lt;br /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ArrayBlockingQueue&lt;/li&gt;
  &lt;li&gt;DelayQueue&lt;/li&gt;
  &lt;li&gt;LinkedBlockingQueue&lt;/li&gt;
  &lt;li&gt;PriorityBlockingQueue&lt;/li&gt;
  &lt;li&gt;SynchronousQueue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;BlockingQueue 通常用于一个线程生产对象，而另外一个线程消费这些对象的场景。&lt;br /&gt;
&lt;img src=&quot;https://timgsa.baidu.com/timg?image&amp;amp;quality=80&amp;amp;size=b9999_10000&amp;amp;sec=1503846043589&amp;amp;di=49c2987da1f56b640003a38eec71028c&amp;amp;imgtype=0&amp;amp;src=http%3A%2F%2Fstatic.oschina.net%2Fuploads%2Fspace%2F2014%2F0106%2F211417_F2gn_1421353.png&quot; alt=&quot;&quot; title=&quot;图片来自网络&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BlockingQueue 接口中的方法&lt;/strong&gt;&lt;br /&gt;
BlockingQueue 具有 4 组不同的方法用于插入、移除以及对队列中的元素进行检查。如果请求的操作不能得到立即执行的话，每个方法的表现也不同。&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.blog.csdn.net/20170827202620381&quot; alt=&quot;&quot; title=&quot;图片来自网络&quot; /&gt;&lt;/p&gt;

&lt;p&gt;四组不同的行为方式解释：&lt;br /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;抛异常：&lt;/strong&gt;如果试图的操作无法立即执行，抛一个异常。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;特定值：&lt;/strong&gt;如果试图的操作无法立即执行，返回一个特定的值(常常是 true / false)。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;阻塞：&lt;/strong&gt;如果试图的操作无法立即执行，该方法调用将会发生阻塞，直到能够执行。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;超时：&lt;/strong&gt;如果试图的操作无法立即执行，该方法调用将会发生阻塞，直到能够执行，但等待时间不会超过给定值。返回一个特定值以告知该操作是否成功(典型的是 true / false)。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;注意：&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;无法向一个 BlockingQueue 中插入 null。如果你试图插入 null，BlockingQueue 将会抛出一个 NullPointerException。&lt;/li&gt;
  &lt;li&gt;可以访问到 BlockingQueue 中的所有元素，而不仅仅是开始和结束的元素。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;1数组阻塞队列-arrayblockingqueue&quot;&gt;1,数组阻塞队列 ArrayBlockingQueue&lt;/h3&gt;

&lt;p&gt;ArrayBlockingQueue 是一个&lt;strong&gt;有界&lt;/strong&gt;的&lt;strong&gt;阻塞&lt;/strong&gt;队列，其内部实现是将对象放到一个数组里。有界也就意味着，它不能够存储无限多数量的元素。它有一个同一时间能够存储元素数量的上限。你可以在对其初始化的时候设定这个上限，但之后就无法对这个上限进行修改了(注：因为它是基于数组实现的，也就具有数组的特性：一旦初始化，大小就无法修改)。&lt;br /&gt;
ArrayBlockingQueue 内部以 FIFO(先进先出)的顺序对元素进行存储。队列中的头元素在所有元素之中是放入时间最久的那个，而尾元素则是最短的那个。&lt;br /&gt;
ArrayBlockingQueue在生产者放入数据和消费者获取数据，都是共用同一个锁对象，由此也意味着两者无法真正并行运行。&lt;/p&gt;

&lt;h3 id=&quot;2链阻塞队列-linkedblockingqueue&quot;&gt;2,链阻塞队列 LinkedBlockingQueue&lt;/h3&gt;
&lt;p&gt;LinkedBlockingQueue 内部以一个链式结构(链接节点)对其元素进行存储。如果需要的话，这一链式结构可以选择一个上限。如果没有定义上限，将使用 Integer.MAX_VALUE 作为上限。&lt;br /&gt;
LinkedBlockingQueue 内部以 FIFO(先进先出)的顺序对元素进行存储。队列中的头元素在所有元素之中是放入时间最久的那个，而尾元素则是最短的那个。&lt;br /&gt;
通过putLock和takeLock两个锁进行同步，两个锁分别实例化notFull和notEmpty两个Condtion，用来协调多线程的存取动作。其中某些方法(如remove,toArray,toString,clear等)的同步需要同时获得这两个锁，并且总是先putLock.lock紧接着takeLock.lock(在同一方法fullyLock中)，这样的顺序是为了避免可能出现的死锁情况。&lt;/p&gt;

&lt;h3 id=&quot;3延迟队列-delayqueue&quot;&gt;3,延迟队列 DelayQueue&lt;/h3&gt;
&lt;p&gt;Delayed 元素的一个&lt;strong&gt;无界阻塞&lt;/strong&gt;队列，只有在延迟期满时才能从中提取元素。该队列的头部 是延迟期满后保存时间最长的 Delayed 元素。如果延迟都还没有期满，则队列没有头部，并且 poll 将返回 null。当一个元素的getDelay(TimeUnit.NANOSECONDS) 方法返回一个小于或等于零的值时，则出现期满。java.util.concurrent.Delayed 接口定义：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	public interface Delayed extends Comparable&amp;lt;Delayed&amp;lt; {  
	  
	 public long getDelay(TimeUnit timeUnit);  
	  
	} 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;DelayQueue 将会在每个元素的 getDelay() 方法返回的值的时间段之后才释放掉该元素。如果返回的是 0 或者负值，延迟将被认为过期，该元素将会在 DelayQueue 的下一次 take  被调用的时候被释放掉。
传递给 getDelay 方法的 getDelay 实例是一个枚举类型，它表明了将要延迟的时间段。TimeUnit 枚举将会取以下值：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;DAYS  
HOURS  
MINUTES  
SECONDS  
MILLISECONDS  
MICROSECONDS  
NANOSECONDS 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Delayed 接口也继承了 java.lang.Comparable 接口，这也就意味着 Delayed 对象之间可以进行对比。这个可能在对 DelayQueue 队列中的元素进行排序时有用，因此它们可以根据过期时间进行有序释放。&lt;/p&gt;

&lt;h3 id=&quot;4具有优先级的阻塞队列-priorityblockingqueue&quot;&gt;4,具有优先级的阻塞队列 PriorityBlockingQueue&lt;/h3&gt;

&lt;p&gt;PriorityBlockingQueue 是一个无界的并发队列。它使用了和类 java.util.PriorityQueue 一样的排序规则。你无法向这个队列中插入 null 值。&lt;br /&gt;
所有插入到 PriorityBlockingQueue 的元素必须实现 java.lang.Comparable 接口。因此该队列中元素的排序就取决于你自己的 Comparable 实现。
注意 PriorityBlockingQueue 对于具有相等优先级(compare() == 0)的元素并不强制任何特定行为。&lt;br /&gt;
如果你从一个 PriorityBlockingQueue 获得一个 Iterator 的话，该 Iterator 并不能保证它对元素的遍历是以优先级为序的。&lt;/p&gt;

&lt;h3 id=&quot;5同步队列-synchronousqueue&quot;&gt;5,同步队列 SynchronousQueue&lt;/h3&gt;
&lt;p&gt;SynchronousQueue 是一个特殊的队列，它的内部同时只能够容纳单个元素。如果该队列已有一元素的话，试图向队列中插入一个新元素的线程将会阻塞，直到另一个线程将该元素从队列中抽走。同样，如果该队列为空，试图向队列中抽取一个元素的线程将会阻塞，直到另一个线程向队列中插入了一条新的元素。&lt;br /&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 03 Apr 2016 00:00:00 +0000</pubDate>
        <link>https://kyleng.github.io/java/java_Queue</link>
        <guid isPermaLink="true">https://kyleng.github.io/java/java_Queue</guid>
        
        <category>java，Thread</category>
        
        
        <category>java</category>
        
      </item>
    
  </channel>
</rss>
