0%

CDH集群部署

安装步骤

  1. 安装JDK

  2. host修改

    /etc/hosts配置文件

  3. NTP时间同步

  4. SSH免秘钥登录

  5. 安装mariadb

    yum install install mariadb -y

  6. mariadb 建表

    1
    2
    3
    4
    5
    6
    7
    8
    9
    SET PASSWORD=PASSWORD('xcloud2017');
    grant all privileges on *.* to 'root'@'%' identified by 'xcloud2017' with grant option; flush privileges;
    create database scmdbn DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
    create database hive DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
    create database amon DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
    create database hue DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
    create database monitor DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
    create database report DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
    create database oozie DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
Read more »

原文地址

起因

前段时间,看到redis作者发布的一篇文章《Is Redlock safe?》,Redlock是redis作者基于redis设计的分布式锁的算法。文章起因是有一位分布式的专家写了一篇文章《How to do distributed locking》,质疑Redlock的正确性。redis作者则在《Is Redlock safe?》文章中给予回应,一来一回甚是精彩。文本就为读者一一解析两位专家的争论。

在了解两位专家的争论前,让我先从我了解的分布式锁一一道来。文章中提到的分布式锁均为排他锁。

Read more »

nginx互斥锁的实现

发表于 2017-06-22 |

nginx 基于原子操作、信号量以及文件锁实现了一个简单高效的互斥锁,当多个 worker 进程之间需要互斥操作时都会用到。下面来看下 nginx 是如何实现它的。

原子操作

在实现互斥锁时用到了原子操作,先来了解一下 nginx 下提供的两个原子操作相关的函数:

1
2
3
4
5
static ngx_inline ngx_atomic_uint_t
ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, ngx_atomic_uint_t set)

static ngx_inline ngx_atomic_int_t
ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add)

第一个函数是一个 CAS 操作,首先它比较 lock 地址处的变量是否等于 old, 如果相等,就把 lock 地址处的变量设为 set 变返回成功,否则返回失败。注意上述过程是作为一个原子一起进行的,不会被打断。 用代码可以描述如下:

1
2
3
4
5
6
7
8
9
10
static ngx_inline ngx_atomic_uint_t
ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, ngx_atomic_uint_t set)
{
if (*lock == old) {
*lock = set;
return 1;
}

return 0;
}

第二个函数是读取 value 地址处的变量,并将其与 add 相加的结果再写入 *lock,然后返回原来 *lock 的值,这些操作也是作为一个整体完成的,不会被打断。用代码可描述如下:

1
2
3
4
5
6
7
8
9
10
static ngx_inline ngx_atomic_int_t
ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add)
{
ngx_atomic_int_t old;

old = *value;
*value += add;

return old;
}
Read more »

转载自:(http://legendtkl.com/2017/04/28/golang-gc/)

1.Golang GC 发展

Golang 从第一个版本以来,GC 一直是大家诟病最多的。但是每一个版本的发布基本都伴随着 GC 的改进。下面列出一些比较重要的改动。

  • v1.1 STW
  • v1.3 Mark STW, Sweep 并行
  • v1.5 三色标记法
  • v1.8 hybrid write barrier

2. GC 算法简介

这一小节介绍三种经典的 GC 算法:引用计数(reference counting)、标记-清扫(mark & sweep)、节点复制(Copying Garbage Collection),分代收集(Generational Garbage Collection)。

2.1 引用计数

引用计数的思想非常简单:每个单元维护一个域,保存其它单元指向它的引用数量(类似有向图的入度)。当引用数量为 0 时,将其回收。引用计数是渐进式的,能够将内存管理的开销分布到整个程序之中。C++ 的 share_ptr 使用的就是引用计算方法。

引用计数算法实现一般是把所有的单元放在一个单元池里,比如类似 free list。这样所有的单元就被串起来了,就可以进行引用计数了。新分配的单元计数值被设置为 1(注意不是 0,因为申请一般都说 ptr = new object 这种)。每次有一个指针被设为指向该单元时,该单元的计数值加 1;而每次删除某个指向它的指针时,它的计数值减 1。当其引用计数为 0 的时候,该单元会被进行回收。虽然这里说的比较简单,实现的时候还是有很多细节需要考虑,比如删除某个单元的时候,那么它指向的所有单元都需要对引用计数减 1。那么如果这个时候,发现其中某个指向的单元的引用计数又为 0,那么是递归的进行还是采用其他的策略呢?递归处理的话会导致系统颠簸。关于这些细节这里就不讨论了,可以参考文章后面的给的参考资料。

Read more »

​ 因为Nginx是利用信号来实现平滑升级、更换日志文件、配置文件实时生效、重启服务等功能的,所以在Nginx的启动过程中会向操作系统内核注册所使用到的信号,其代码实现如下

1
2
3
4
5
6
7
8
9
10
int ngx_cdecl
main(int argc, char *const *argv)
{
……
// 初始化信号
if (ngx_init_signals(cycle->log) != NGX_OK) {
return 1;
}
……
}
Read more »

Nginx 进程模型

Nginx 进程模型采用master/worker进程模型,一个master进程,多个worker进程。master进程主要工作就是重载配置文件、监听信号(重载配置文件/重新打开日志文件等)、监控worker,而worker进程核心就是处理网络事件以及定时相关操作,maser和worker之间通信机制采用socketpair + 共享内存 + 信号,worker和worker之间通信机制采用socketpair通信。


1. Nginx启动流程

  • 命令行参数解析,获取主配置文件路径等,ngx_process_options
  • 各种初始化工作,调用各个模块create_conf和init_conf方法、创建pid文件、创建共享内存、监听套接字、调用各个模块init_module方法…,初始化工作主要在ngx_init_cycle这个函数中完成
  • 注册各种信号处理函数,主要在ngx_init_signals函数中完成,在signals全局数组中保存了各种信号以及相应的信号处理函数
  • 创建后台daemon进程
  • 创建pid文件
  • 根据启动参数判断启动哪种模式,master/worker进程模式则进入ngx_master_process_cycle函数
Read more »

信号处理机制

在 Linux 中,每个进程都拥有两个位向量,这两个位向量共同决定了进程将如何处理信号:
- 在 Linux 中,每个进程都拥有两个位向量,这两个位向量共同决定了进程将如何处理信号:
- 在 Linux 中,每个进程都拥有两个位向量,这两个位向量共同决定了进程将如何处理信号:

当内核发送一个信号给进程时,它将会修改进程的pending位向量,譬如说,当内核发送一个SIGINT信号给进程,那么它会将进程的pending[SIGINT]的值设置成 1。同样地,当进程屏蔽掉一个信号时,那么它会修改blocked位向量。当进程屏蔽掉一个信号之后,内核仍然可以发送这个信号给进程(保存在进程的pending位向量中),但进程不会接收并处理这个信号。只有当进程解除了对这个信号的屏蔽之后,进程才会接收并处理这个信号。

下面的程序一开始就屏蔽了SIGINT信号,所以即使内核发送SIGINT信号给这个程序,这个信号也不会得到处理。而当程序解除了对SIGINT的屏蔽之后,这个SIGINT信号才会得到处理:

Read more »

MySQL 存储引擎-MyISAM与InnoDB差异

<高性能mysql>对两者差异的评价如下:

InnoDB:MySQL默认的事务型引擎,也是最重要和使用最广泛的存储引擎。它被设计成为大量的短期事务,短期事务大部分情况下是正常提交的,很少被回滚。InnoDB的性能与自动崩溃恢复的特性,使得它在非事务存储需求中也很流行。除非有非常特别的原因需要使用其他的存储引擎,否则应该优先考虑InnoDB引擎。

MyISAM:在MySQL 5.1 及之前的版本,MyISAM是默认引擎。MyISAM提供的大量的特性,包括全文索引、压缩、空间函数(GIS)等,但MyISAM并不支持事务以及行级锁,而且一个毫无疑问的缺陷是崩溃后无法安全恢复。正是由于MyISAM引擎的缘故,即使MySQL支持事务已经很长时间了,在很多人的概念中MySQL还是非事务型数据库。尽管这样,它并不是一无是处的。对于只读的数据,或者表比较小,可以忍受修复操作,则依然可以使用MyISAM

  1. InnoDB 支持事务,MyISAM 不支持事务。这是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一;

  2. InnoDB 支持外键,而 MyISAM 不支持。对一个包含外键的 InnoDB 表转为 MYISAM 会失败;

  3. InnoDB 是聚集索引,MyISAM 是非聚集索引。聚簇索引的文件存放在主键索引的叶子节点上,因此 InnoDB 必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而 MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的;

  4. InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;

  5. InnoDB 最小的锁粒度是行锁,MyISAM 最小的锁粒度是表锁。一个更新语句会锁住整张表,导致其他查询和更新都会被阻塞,因此并发访问受限。这也是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一;

  6. MyISAM支持fulltext类型的全文索引,InnoDB不支持,但是innodb可以使用sphinx插件支持全文索引,并且效果更好;

  7. MyISAM允许没有任何索引和主键的表存在,索引都是保存行的地址;InnoDB如果没有设定主键或者非空唯一索引,**就会自动生成一个6字节的主键(用户不可见)**,数据是主索引的一部分,附加索引保存的是主索引的值。

MySQL 索引失效

为了测试索引失效,首先创建一个用于测试的数据表

1
2
3
4
5
6
7
8
9
10
create table 
student(id int not null primary key, name varchar(10) not null,
age int,
address varchar(200),
hobby varchar(200),
key(name, age, address)
);

insert into student(id, name, age, address, hobby)
values(1, 'a', 20, 'a', 'a'),(2, 'b', 30, 'b', 'b'),(3, 'c', 30, 'c', 'c');

索引失效的几种常见场景

  1. select语句中有is null或者is not null查询判断。索引是一棵B+树,节点中不会存储NULL值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
MariaDB [test]> explain select * from student where age is null \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: student
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 3
Extra: Using where
1 row in set (0.00 sec)


MariaDB [test]> explain select * from student where age is not null \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: student
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 3
Extra: Using where
1 row in set (0.01 sec)
  1. 前导模糊查询不能利用索引,例如查询字段使用like '%XX'或者like '%XX%'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
MariaDB [test]> explain select * from student where name like '%a' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: student
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 3
Extra: Using where
1 row in set (0.00 sec)


MariaDB [test]> explain select * from student where name like '%a%' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: student
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 3
Extra: Using where
1 row in set (0.00 sec)


// like 'a%' 场景是可以使用到索引
MariaDB [test]> explain select * from student where name like 'a%' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: student
type: range
possible_keys: name
key: name
key_len: 12
ref: NULL
rows: 1
Extra: Using index condition
1 row in set (0.00 sec)
  1. 查询条件有or
1
2
3
4
5
6
7
8
9
10
11
12
13
MariaDB [test]> explain select * from student where name='a' or name='b' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: student
type: ALL
possible_keys: name
key: NULL
key_len: NULL
ref: NULL
rows: 3
Extra: Using where
1 row in set (0.00 sec)
  1. 不符合左前缀法则的查询,跳过多列索引的第一列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
MariaDB [test]> explain select * from student where age=10 \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: student
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 3
Extra: Using where
1 row in set (0.00 sec)

  1. 范围查询 > < between
1
2
3
4
5
6
7
8
9
10
11
12
13
MariaDB [test]> explain select * from student where name>='a' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: student
type: ALL
possible_keys: name
key: NULL
key_len: NULL
ref: NULL
rows: 3
Extra: Using where
1 row in set (0.00 sec)
  1. 查询条件使用函数在索引列上,或者对索引列进行运算
1
2
3
4
5
6
7
8
9
10
11
12
13
MariaDB [test]> explain select * from student where left(name, 1)='a' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: student
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 3
Extra: Using where
1 row in set (0.00 sec)
  1. not in/not exists
1
2
3
4
5
6
7
8
9
10
11
12
13
MariaDB [test]> explain select * from student where name not in ('c', 'b') \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: student
type: ALL
possible_keys: name
key: NULL
key_len: NULL
ref: NULL
rows: 3
Extra: Using where
1 row in set (0.00 sec)
  1. 隐式转换导致索引失效,name是一个字符串字段,select查询时传入数字,mysql会把数字转换为字符串,然后做全表扫描
1
2
3
4
5
6
7
8
9
10
11
12
13
MariaDB [test]> explain select * from student where name = 11 \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: student
type: ALL
possible_keys: name
key: NULL
key_len: NULL
ref: NULL
rows: 3
Extra: Using where
1 row in set (0.00 sec)

由于历史的原因,公司部门在多个组件中使用了lighttpd,具体为何当时技术选型的时候没选nginx而选择lighttpd就不得而知了。lighttpd的社区相对nginx差距还是很大的,明显nginx的社区更活跃。lighttpd网上的资料以及第三方模块相对比较少,学习的成本会相对高一点。不过lighttpd的源码相对nginx会少一点,毕竟lighttpd比较轻量级,功能上没nginx那么多。网上nginx/lighttpd/appache 三种web server的测试结果,lighttpd占用内存最小,请求响应时间中等,apache最差。

进程模型

lighttpd采用master-worker进程模型,master进程主要负责加载配置、fork worker进程、管理worker进程,worker进程主要负责接收请求、处理请求、返回请求结果,worker进程个数可以在配置文件中配置,master进程会根据配置的个数,fork worker进程

Read more »