21.构建memcached服务、LNMP+memcached、PHP的本地Session信息、PHP实现session共享
*******************************
完整部署:一台前端调度服务器:proxy,两台后端LNMP WebServer
项目要求:01.Proxy部署Nginx调度器负载后端两台Web服务器,调度算法为轮询。
02.Proxy部署Mencache缓存服务器,后端WebServer配置php连接Proxy的Memcached服务,将本地Session缓存在Memcached服务器,实现后端两台WebServer Session共享。
03.Proxy部署Varnish加速WebServer。
Client请求 –> (Proxy)Varnish(未缓存) –> (Proxy)Nginx(轮询) –> WebServer –> (Proxy)Varnish(缓存) –> Client
*******************************
1> 构建memcached服务
安装包:memcached
配置文件:/etc/sysconfig/memcached
默认端口:11211
服务:memcached
访问:]# telnet 192.168.4.5 11211
常用命令:
set name 0 180 3
plj
get name
add replace append delete stats flush_all quit
总结:本质上,它是一个简洁的key-value存储系统。
特点: 01.全内存运转
02.哈希方式存储
03.简单文本协议进行数据通信
04.只操作字符型数据
05.其它类型数据由应用解释,序列化以及反序列化
06.集群也由应用进行控制,采用一致性散列(哈希)算法
缺点: 01.数据是保存在内存当中的,一旦服务进程重启,数据会全部丢失
对策:可以采取更改Memcached的源代码,增加定期写入硬盘的功能
02.Memcached以root权限运行,而且Memcached本身没有任何权限管理和认证功能,安全性不足。
对策:可以将Memcached服务绑定在内网IP上,通过防火墙进行防护
整理:特性、优点和限制
Memory :内存存储,速度快,对于内存的要求高,所缓存的内容非持久化。对于 CPU 要求很低,所以常常采用将Memcached 服务端和一些 CPU 高消耗 Memory 低消耗应用部属在一起 。(否则会互相挤占资源)
集中式 Cache :避开了分布式 Cache 的传播问题,但是需要非单点保证其可靠性,这需要 cluster 的工作,可以将多个Memcached 作为一个虚拟的 cluster ,同时对于 cluster 的读写和普通的 memcached 的读写性能没有差别。
分布式扩展: Memcached 很突出的一个优点,就是采用了可分布式扩展的模式。可以将部属在一台机器上的多个 Memcached 服务端或者部署在多个机器上的 Memcached 服务端组成一个虚拟的服务端,对于调用者来说完全屏蔽和透明。提高的单机器的内存利用率 。
Socket 通信:传输内容的大小以及序列化的问题需要注意,虽然 Memcached 通常会被放置到内网作为 Cache, Socket 传输速率应该比较高(当前支持 Tcp 和 udp 两种模式,同时根据客户端的不同可以选择使用 nio 的同步或者异步调用方式),但是序列化成本和带宽成本还是需要注意。这里也提一下序列化,对于对象序列化的性能往往让大家头痛,但是如果对于同一类的 Class 对象序列化传输,第一次序列化时间比较长,后续就会优化,其实也就是说序列化最大的消耗不是对象序列化,而是类的序列化。如果穿过去的只是字符串,那么是最好的,省去了序列化的操作,因此在 Memcached 中保存的往往是较小的内容 。
特殊的内存分配机制:首先要说明的是 Memcached 支持最大的存储对象为 1M (page)。它的内存分配比较特殊,但是这样的分配方式其实也是对于性能考虑的,简单的分配机制可以更容易回收再分配,节省对于 CPU 的使用(前面的文章中有描述) 。
Cache 机制简单: 首先它没有什么同步,消息分发,两阶段提交等等,它就是一个很简单的 Cache ,把东西放进去,然后可以取出来,如果发现所提供的 Key 没有命中,那么就很直白的告诉你,你这个 key 没有任何对应的东西在缓存里,去数据库或者其他地方取,当你在外部数据源取到的时候,可以直接将内容置入到 Cache 中,这样下次就可以命中了 。这里会提到怎么去同步这些数据,两种方式,一种就是在你修改了以后立刻更新 Cache内容,这样就会即时生效。另一种是说容许有失效时间,到了失效时间,自然就会将内容删除,此时再去去的时候就会命中不了,然后再次将内容置入 Cache ,用来更新内容。后者用在一些时时性要求不高,写入不频繁的情况。
客户端的重要性: 客户端设计的合理十分重要,同时也给使用者提供了很大的空间去扩展和设计客户端来满足各种场景的需要,包括容错,权重,效率,特殊的功能性需求,嵌入框架等等。
2> LNMP+memcached+session共享
部署:两台WebServer部署LNMP,配置PHP连接Memcached数据库。
Proxy调度:查看《思维导图(1-20)》
实现方式:
web1 web2
]# vim /etc/php-fpm.d/www.conf //文件的最后2行
php_value[session.save_handler] = memcache
php_value[session.save_path] = “tcp://192.168.2.5:11211”
]# systemctl restart php-fpm
总结:还可以部署高可用,待续…
*************************************
22.安装部署Tomcat服务器、使用Tomcat部署虚拟主机、使用Varnish加速Web
1> Tomcat
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,它早期的名称为catalina,后来由Apache、Sun 和其他一些公司及个人共同开发而成,并更名为Tomcat。Tomcat 是一个小型的轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选,因为Tomcat 技术先进、性能稳定,成为目前比较流行的Web 应用服务器。Tomcat是应用(java)服务器,它只是一个servlet容器,是Apache的扩展,但它是独立运行的。目前最新的版本为Tomcat 8.0.24 Released。
Tomcat不是一个完整意义上的Jave EE服务器,它甚至都没有提供对哪怕是一个主要Java EE API的实现;但由于遵守apache开源协议,tomcat却又为众多的java应用程序服务器嵌入自己的产品中构建商业的java应用程序服务器,如JBoss和JOnAS。尽管Tomcat对Jave EE API的实现并不完整,然而很企业也在渐渐抛弃使用传统的Java EE技术(如EJB)转而采用一些开源组件来构建复杂的应用。这些开源组件如Structs、Spring和Hibernate,而Tomcat能够对这些组件实现完美的支持。
总结:
缺点:01. 是轻量级的Web 容器,无法满足复杂业务场景的要求。J2EE规范中的标准容器是web container和EJB containor。另外还要提供诸如JNDI,JMS, JDBC,JMAIL等等的服务,TOMCAT把这些都省略了,要想满足这些功能必须带另外的开源框架产品。
02. 配置简单,但是图形化做的不好,不直观,给非技术用户感觉比较不好
03. 缺少更多的监控功能和接口。运行状态(runtime)的统计数据不多,展示界面不好。
04. 性能稍差
05. 不支持session复制这样的高级功能
06. 缺少多个实例协同工作的设置,集群,多服务器
07. 自动化管理等功能缺失
2> 安装部署Tomcat服务器
环境:java-1.8.0-openjdk ava-1.8.0-openjdk-headless
版本:apache-tomcat-8.0.30
工作目录:/usr/local/tomcat
启动:/usr/local/tomcat/bin/startup.sh
关闭:/usr/local/tomcat/bin/shutdown.sh
端口:tcp6 0 0 :::8080 :::* LISTEN 12448/java
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 12448/java
tcp6 0 0 :::8009 :::* LISTEN 12448/java
配置文件:/usr/local/tomcat/conf/server.xml
3> Tomcat部署虚拟主机 (Proxy调度两台Tomcat WebServer)
配置文件:/usr/local/tomcat/conf/server.xml
支持:页面跳转、SSL加密、日志配置
配置Tomcat集群:
http…
upstream toms {
server web1:8080;
server web2:8080;
…
}
…
location / ;
int[] length = new int[] { 256, 512 };
PartitionUtil pu = new PartitionUtil(count, length);
如果需要平均分配设置:平均分为 4 分片,partitionCount*partitionLength=1024。
<function name=”func1″ class=”org.opencloudb.route.function.PartitionByLong”>
<property name=”partitionCount”>4</property>
<property name=”partitionLength”>256</property>
</function>
###############
03:范围约定
此分片适用于,提前规划好分片字段某个范围属于哪个分片。
<tableRule name=”auto-sharding-long”>
<rule>
<columns>user_id</columns>
<algorithm>rang-long</algorithm>
</rule>
</tableRule>
<function name=”rang-long” class=”org.opencloudb.route.function.AutoPartitionByLong”>
<property name=”mapFile”>autopartition-long.txt</property>
<property name=”defaultNode”>0</property>
</function>
配置说明:
columns:标识将要分片的表字段;
algorithm:分片函数;
rang-long 函数中:
mapFile 代表配置文件路径;
defaultNode:超过范围后的默认节点。
所有的节点配置都是从 0 开始,及 0 代表节点 1,此配置非常简单,即预先制定可能的 id 范围到某个分片:
# range start-end ,data node index
# K=1000,M=10000.
0-500M=0
500M-1000M=1
1000M-1500M=2
或
0-10000000=0
10000001-20000000=1
###############
04:取模
此规则为对分片字段求摸运算。
<tableRule name=”mod-long”>
<rule>
<columns>user_id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<function name=”mod-long” class=”org.opencloudb.route.function.PartitionByMod”>
<!– how many data nodes –>
<property name=”count”>3</property>
</function>
配置说明:
columns:标识将要分片的表字段;
algorithm:分片函数;
此种配置非常明确,即根据 id 进行十进制求模预算,相比固定分片 hash,此种在批量插入时可能存在批量插入单事务插入多数据分片,增大事务一致性难度。
###############
05:按日期(天)分片
此规则为按天分片。
<tableRule name=”sharding-by-date”>
<rule>
<columns>create_time</columns>
<algorithm>sharding-by-date</algorithm>
</rule>
</tableRule>
<function name=”sharding-by-date” class=”org.opencloudb.route.function.PartitionByDate”>
<property name=”dateFormat”>yyyy-MM-dd</property>
<property name=”sBeginDate”>2014-01-01</property>
<property name=”sEndDate”>2014-01-02</property>
<property name=”sPartionDay”>10</property>
</function>
配置说明:
columns :标识将要分片的表字段;
algorithm :分片函数;
dateFormat :日期格式;
sBeginDate :开始日期;
sEndDate:结束日期;
sPartionDay :分区天数,即默认从开始日期算起,分隔 10 天一个分区。
如果配置了 sEndDate 则代表数据达到了这个日期的分片后后循环从开始分片插入。
Assert.assertEquals(true, 0 == partition.calculate(“2014-01-01”));
Assert.assertEquals(true, 0 == partition.calculate(“2014-01-10”));
Assert.assertEquals(true, 1 == partition.calculate(“2014-01-11”));
Assert.assertEquals(true, 12 == partition.calculate(“2014-05-01”));
###############
06:取模范围约束
此种规则是取模运算与范围约束的结合,主要为了后续数据迁移做准备,即可以自主决定取模后数据的节点分布。
<tableRule name=”sharding-by-pattern”>
<rule>
<columns>user_id</columns>
<algorithm>sharding-by-pattern</algorithm>
</rule>
</tableRule>
<function name=”sharding-by-pattern” class=”org.opencloudb.route.function.PartitionByPattern”>
<property name=”patternValue”>256</property>
<property name=”defaultNode”>2</property>
<property name=”mapFile”>partition-pattern.txt</property>
</function>
partition-pattern.txt
# id partition range start-end ,data node index
###### first host configuration
1-32=0
33-64=1
65-96=2
97-128=3
######## second host configuration
129-160=4
161-192=5
193-224=6
225-256=7
0-0=7
配置说明:
columns :标识将要分片的表字段;
algorithm :分片函数;
patternValue:即求模基数;
defaoultNode:默认节点,如果配置了默认,则不会按照求模运算;
mapFile:配置文件路径。
配置文件中,1-32 即代表 id%256 后分布的范围,如果在 1-32 则在分区 1,其他类推,如果 id 非数据,则会分配在 defaoultNode 默认节点。
String idVal = “0”;
Assert.assertEquals(true, 7 == autoPartition.calculate(idVal));
idVal = “45a”;
Assert.assertEquals(true, 2 == autoPartition.calculate(idVal));
###############
07:截取数字做 hash 求模范围约束
此种规则类似于取模范围约束,此规则支持数据符号字母取模。
<tableRule name=”sharding-by-prefixpattern”>
<rule>
<columns>user_id</columns>
<algorithm>sharding-by-prefixpattern</algorithm>
</rule>
</tableRule>
<function name=”sharding-by-pattern” class=”org.opencloudb.route.function.PartitionByPrefixPattern”>
<property name=”patternValue”>256</property>
<property name=”prefixLength”>5</property>
<property name=”mapFile”>partition-pattern.txt</property>
</function>
partition-pattern.txt
# range start-end ,data node index
# ASCII
# 8-57=0-9 阿拉伯数字
# 64、65-90=@、A-Z
# 97-122=a-z
###### first host configuration
1-4=0
5-8=1
9-12=2
13-16=3
###### second host configuration
17-20=4
21-24=5
25-28=6
29-32=7
0-0=7
配置说明:
columns :标识将要分片的表字段;
algorithm :分片函数;
patternValue:求模基数;
prefixLength:ASCII 截取的位数;
mapFile:配置文件路径。
配置文件中,1-32 即代表 id%256 后分布的范围,如果在 1-32 则在分区 1,其他类推。
此种方式类似方式 6,只不过采取的是将列种获取前 prefixLength 位列所有 ASCII 码的和进行求模。
sum%patternValue ,获取的值,在范围内的分片数,
String idVal=“gf89f9a”;
Assert.assertEquals(true, 0==autoPartition.calculate(idVal));
idVal=“8df99a”;
Assert.assertEquals(true, 4==autoPartition.calculate(idVal));
idVal=“8dhdf99a”;
Assert.assertEquals(true, 3==autoPartition.calculate(idVal));
###############
08:截取数字 hash 解析
此规则是截取字符串中的 int 数值 hash 分片。
<tableRule name=”sharding-by-stringhash”>
<rule>
<columns>user_id</columns>
<algorithm>sharding-by-stringhash</algorithm>
</rule>
</tableRule>
<function name=”sharding-by-stringhash” class=”org.opencloudb.route.function.PartitionByString”>
<property name=”partitionLength”>512</property><!– zero-based –>
<property name=”partitionCount”>2</property>
<property name=”hashSlice”>0:2</property>
</function>
配置说明:
columns :标识将要分片的表字段;
algorithm :分片函数;
函数中:
partitionLength:代表字符串;
hash:求模基数;
partitionCount:分区数;
hashSlice :hash 预算位,即根据子字符串中 int 值 hash 运算。0 means str.length(), -1 means str.length()-1。
/**
* “2” -> (0,2)
* “1:2” -> (1,2)
* “1:” -> (1,0)
* “-1:” -> (-1,0)
* “:-1” -> (0,-1)
* “:” -> (0,0)
*/
例子:
String idVal=null;
rule.setPartitionLength(“512”);
rule.setPartitionCount(“2”);
rule.init();
rule.setHashSlice(“0:2”);
// idVal = “0”;
// Assert.assertEquals(true, 0 == rule.calculate(idVal));
// idVal = “45a”;
// Assert.assertEquals(true, 1 == rule.calculate(idVal));
// last 4
rule = new PartitionByString();
rule.setPartitionLength(“512”);
rule.setPartitionCount(“2”);
rule.init();
//last 4 characters
rule.setHashSlice(“-4:0”);
idVal = “aaaabbb0000”;
Assert.assertEquals(true, 0 == rule.calculate(idVal));
idVal = “aaaabbb2359”;
Assert.assertEquals(true, 0 == rule.calculate(idVal));
*************************************
39.NoSQL概述 部署Redis服务 、部署LNMP+Redis
1> NoSQL:(Not Only SQL),泛指非关系型的数据库。
Redis:Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
2> 部署Redis服务
版本: redis-4.0.8
查看状态:
utils]# /etc/init.d/redis_6379 status
配置文件:/etc/redis/6379.conf
连接redis:
]# redis-cli
127.0.0.1:6379> ping
PONG //PONG说明服务正常
常用指令操作:
set keyname keyvalue 存储
get keyname 获取
del keyname 删除变量
keys * 打印所有变量
EXISTS keyname 测试是否存在
type keyname 查看类型
move keyname dbname
select 数据库编号0-15 切换库
expire keyname 10 设置有效时间
ttl keyname 查看生存时间
flushall 删除所有变量
save 保存所有变量
shutdown 关闭redis服务
在命令行输入密码连接
]# redis-cli -h 192.168.4.50 -p 6350 -a 123456
192.168.4.50:6350> ping
PONG
由于修改Redis服务运行参数,所以在停止服务的时候也不能用默认的方法停止
]# /etc/init.d/redis_6379 stop //停止失败
]# redis-cli -h 192.168.4.50 -p 6350 -a 123456 shutdown
3> 部署LNMP+Redis
Nginx-1.12.2
Php-fpm-5.4.16
Php-redis-2.2.4
脚本连接:
<?php
$redis = new redis();
$redis->connect(‘192.168.4.50’,6350);
$redis->auth(“123456”);
$redis->set(‘tel,’13152098678);
echo $redis->get(‘tel’);
?>
*************************************
40.创建Redis集群 管理集群
1> Redis集群:
主库宕机后,对应的从库会自动升级为主库,原主库起来后,成为新主库的从库。
2> 创建集群
]# redis-trib.rb create –replicas 1
> 192.168.4.51:6351 192.168.4.52:6352
> 192.168.4.53:6353 192.168.4.54:6354
> 192.168.4.55:6355 192.168.4.56:6356
主库对应的从库,会自动把数据同步到本机。
查看集群信息:
]# redis-trib.rb check 192.168.4.51:6351
查看数据存储情况:
]# redis-trib.rb info 192.168.4.51:6351
添加master角色主机 (添加 192.168.4.57,在51操作):
]# redis-trib.rb add-node 192.168.4.57:6357 192.168.4.51:6351
重新分片:
]# redis-trib.rb reshard 192.168.4.51:6351
添加slave角色主机 (添加slave 192.168.4.58 51上操作):
]# redis-trib.rb add-node –slave 192.168.4.58:6358 192.168.4.51:6351
自动分配给57
移除slave角色主机 (移除192.168.4.58,51操作)
redis-trib.rb del-node 任意主机 被移除主机ID(slave主机没有haxi槽,可直接移除)
]# redis-trib.rb del-node 192.168.4.51:6351 a28a8ad17defa60a4169262a909a17e46d5ce699
移除master角色主机 (移除 192.168.4.57 51操作)
释放占用的hash槽
]# redis-trib.rb reshard 192.168.4.51:6351
移除master主机
]# redis-trib.rb del-node 192.168.4.51:6351 7ac349e23d72f46967eeb0ef6b022c27396a4388










