使用Nagios中监控进程最大线程数

最近在刚好一些业务经常把线程跑满,导致服务器资源用完,所以就写了一个脚本用于Nagios下相关进程的最大线程数的监控,Unix的服务器上最大的线程数默认的是1024,当然在业务繁忙的服务器中这样肯定是不够用的,当然在实际生产环境中做初始化调优时一般都会有做过修改,如开启打开文件的最大句柄数等等,一般情况下我们都是修改/etc/security/limits.conf文件,但是要修改最大线程数就要修改/etc/security/limits.d/90-nproc.conf文件了,修改就和修改limits.conf文件文件的方式一样,在此就不做过多的解释,我一般把所有用户的最大的线程数都调大

*          soft    nproc     65535

在调整好后线程数的预警值可以根据实际情况调整,脚本实现也很简单,如下:

#!/bin/bash
#check_pstree.sh
#Used for pstree process monitoring
#writer jim
#history 2017.07.01

# Nagios 返回值
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3
#对传递进来的参数判断
if [ $# -lt 1 ];then
    echo "Please enter the process string"
    echo "ex> $0 java"
    exit $STATE_UNKNOWN
fi

if [ $# -gt 1 ]; then
        echo "The input parameters are too much"
    echo "ex> $0 java"
    exit $STATE_UNKNOWN
fi

reg_name=$1
process_pid=$(ps -ef | grep "$reg_name " | grep -v grep | awk '{print $2}')
declare -i max_process_num=$(ulimit -an | grep "max user processes" | awk '{print $5}')
declare -i warning_num=$max_process_num/2
#在此预警值取最大线程数的50%,具体可以根据实际生产环境修改
pstree_num=$(pstree -p $process_pid | wc -l)

if [ $pstree_num -le $warning_num ];then
        echo "$reg_name pstree number is:$pstree_num;warning_num is:$warning_num;max user processes is:$max_process_num,OK"
        exit $STATE_OK
else 
        echo "error!!!The number of pstree is too much.the number is:$pstree_num"
        exit $STATE_CRITICAL
fi

当然在这个脚本也可以修改后用cron任务中做定时检查,不过在Nagios中不知为何线程数的值在Nagios的监控页面下显示总有异常,不过直接执行是没有问题的。

Ganglia监控Hadoop集群 使用Nagios发送告警邮件

基本介绍

Ganglia:是UC Berkeley发起的一个开源集群监视项目,设计用于测量数以千计的节点。Ganglia的核心包含gmond、gmetad以及一个Web前端。主要是用来监控系统性能,如:cpu 、mem、硬盘利用率, I/O负载、网络流量情况、系统负载等,通过曲线很容易见到每个节点的工作状态,对合理调整、分配系统资源,提高系统整体性能起到重要作用。
更重要的是,HDFS、YARN、HBase等已经支持其守护进程的资源情况发送给Ganglia进行监控。

Nagios:是一款开源的电脑系统和网络监视工具,能有效监控Windows、Linux和Unix的主机状态,交换机路由器等网络设置,打印机等。尤其有用的是,在系统或服务状态异常时发出邮件或短信报警第一时间通知网站运维人员,在状态恢复后发出正常的邮件或短信通知。

我们这次的架构设计:

  1. Ganglia的优势在于监控数据的实时性和丰富的图形化界面,同时对Mobile端支持的很好,但是在出现问题的时候报警提示功能,相对较弱。

  2. Nagios的优势在于出现问题和问题恢复时可以提供强大的报警提示功能,但是在实时监控和图形化展示上功能较弱,对大规模集群支持较差。

  3. 要对数据平台中支持的Hadoop集群(HDFS、YARN)对资源的使用情况进行监控。

所以我们将3者结合起来,架构如下:

监控

相关版本:Ubuntu 16.04 LTS、Ganglia 3.6.1、Nagios 4.1.1、Hadoop 2.7.3

部署Ganglia:

在需要进行Web展示的节点上安装:

sudo apt-get update
sudo apt install apache2 php libapache2-mod-php 
sudo apt-get install rrdtool
sudo apt-get install gmetad ganglia-webfrontend
#过程中出现apache2重启的对话框,选择yes即可

在需要被监控的节点上安装:

sudo apt-get update
sudo apt install php libapache2-mod-php 
sudo apt-get install ganglia-monitor
#过程中出现apache2重启的对话框,选择yes即可

下述操作过程,在主节点上进行:

#复制 Ganglia webfrontend Apache 配置:
sudo cp /etc/ganglia-webfrontend/apache.conf /etc/apache2/sites-enabled/ganglia.conf

#编辑gmetad配置文件 
sudo vi /etc/ganglia/gmetad.conf
#更改数据源 data_source “my cluster” localhost 修改为:
data_source "bigdata cluster" 10  wl1:8649 wl2:8649 wl3:8649
setuid_username "nobody"
gridname "bigdata cluster"
case_sensitive_hostnames 1
all_trusted on

#主节点上执行:
sudo ln -s /usr/share/ganglia-webfrontend/ /var/www/ganglia

下述操作过程,在所有被监控节点上进行:

#编辑gmond配置文件 
sudo vi /etc/ganglia/gmond.conf
globals {
  daemonize = yes
  setuid = yes
  user = ganglia
  debug_level = 0
  max_udp_msg_len = 1472
  mute = no
  deaf = no
  host_dmax = 0 /*secs */
  cleanup_threshold = 300 /*secs */
  gexec = no
  send_metadata_interval = 10
}
/* If a cluster attribute is specified, then all gmond hosts are wrapped inside
 * of a <CLUSTER> tag.  If you do not specify a cluster tag, then all <HOSTS> will
 * NOT be wrapped inside of a <CLUSTER> tag. */
cluster {
  name = "bigdata cluster"
  owner = "ganglia"
  latlong = "unspecified"
  url = "unspecified"
}

/* The host section describes attributes of the host, like the location */
host {
  location = “wl1"  #每个节点写自己的主机名
}

/* Feel free to specify as many udp_send_channels as you like.  Gmond
   used to only support having a single channel */
udp_send_channel {
  #mcast_join = 239.2.11.71
  host = wl1  #每个节点都指向gmetad主机
  port = 8649
  ttl = 1
}

/* You can specify as many udp_recv_channels as you like as well. */
udp_recv_channel {
  #mcast_join = 239.2.11.71
  port = 8649
  #bind = 239.2.11.71
}


/* You can specify as many tcp_accept_channels as you like to share
   an xml description of the state of the cluster */
tcp_accept_channel {
  port = 8649
}

收集Hadoop集群的HDFS、YARN metric源:

下述操作过程,在所有Hadoop集群节点上进行:

#编辑hadoop-metrics2.properties
vi hadoop-2.7.3/etc/hadoop/hadoop-metrics2.properties
#注释掉所有原来的内容,增加如下内容:
*.sink.ganglia.class=org.apache.hadoop.metrics2.sink.ganglia.GangliaSink31
*.sink.ganglia.period=10

*.sink.ganglia.slope=jvm.metrics.gcCount=zero,jvm.metrics.memHeapUsedM=both
*.sink.ganglia.dmax=jvm.metrics.threadsBlocked=70,jvm.metrics.memHeapUsedM=40

namenode.sink.ganglia.servers=wl1:8649
resourcemanager.sink.ganglia.servers=wl1:8649

datanode.sink.ganglia.servers=wl1:8649
nodemanager.sink.ganglia.servers=wl1:8649

jobhistoryserver.sink.ganglia.servers=wl1:8649

maptask.sink.ganglia.servers=wl1:8649
reducetask.sink.ganglia.servers=wl1:8649

重启Hadoop集群、重启gmond、gmetad、gweb:

hadoop-2.7.3/sbin/stop-all.sh
hadoop-2.7.3/sbin/start-all.sh
sudo /etc/init.d/ganglia-monitor restart (所有节点) gmond服务 
sudo /etc/init.d/gmetad restart    (gmetad节点)   gmetad服务
sudo /etc/init.d/apache2 restart  (gweb节点)    web服务(包含gweb服务)

然后在安装了gweb的节点上使用主机ip/ganglia即可登录Web:

监控

选择某个Node具体观察,可以看到已经收集到了HDFS和YARN的度量数据:

监控

监控

选择Mobile标签页,可以看到对移动终端的展示支持的很好:

监控

部署Nagios:

  • 为了Nagios能正常发送告警邮件,先要安装sendmail工具:
sudo apt-get install sendmail  
sudo apt-get install sendmail-cf
sudo apt-get install mailutils  
sudo apt-get install sharutils
#终端输入命令:
ps aux |grep sendmail
#输出如下:说明sendmail 已经安装成功并启动了
root     20978  0.0  0.3   8300  1940 ?        Ss   06:34   0:00 sendmail: MTA: accepting connections          
root     21711  0.0  0.1   3008   776 pts/0    S+   06:51   0:00 grep sendmail
  • 配置sendmail:
#打开sendmail的配置文件 /etc/mail/sendmail.mc
vi  /etc/mail/sendmail.mc
#找到如下行:
DAEMON_OPTIONS(`Family=inet,  Name=MTA-v4, Port=smtp, Addr=127.0.0.1')dnl
#将Addr=127.0.0.1修改为Addr=0.0.0.0,表明可以连接到任何服务器。
DAEMON_OPTIONS(`Family=inet,  Name=MTA-v4, Port=smtp, Addr=0.0.0.0')dnl

#生成新的配置文件:
cd /etc/mail  
mv sendmail.cf sendmail.cf~      #做一个备份  
m4 sendmail.mc &gt; sendmail.cf  #&gt;的左右有空格
#修改sendmail.cf
vi /etc/mail/sendmail.cf
#新增
Dj$w. #注意最后面有一个点

#修改hosts,否则发送邮件的过程会非常慢,因为sendmail
#以wl1作为域名加到主机名wl1后组成完整的长名wl1.wl1来访问,
#会提示找不到域名
vi /etc/hosts
x.x.x.x       wl1 wl1.localdomain wl1.wl1
#重启sendmail服务:
service sendmail restart
#测试发送邮件,看看能否收得到:
echo "test" | mail -s test [email protected]
  • 安装Nagios:

参考Ubuntu 16.04 安装 Nagios Core:

Ubuntu 16.04 安装 Nagios Core

其中下载Nagios插件那一步时,nagios-plugins-2.1.1官网下载太慢,先从下面的链接下载好,然后编译安装

nagios-plugins-2.1.1下载:
http://download.csdn.net/download/u014722463/9288011

使用http://主机IP/nagios/ 登录,需要输入安装时设置的用户名nagiosadmin及其密码,然后就可以看到主页了:

监控

  • 主要说一下如何用Nagios监控Ganglia数据,并根据阀值发出告警:
#新生成一个监控ganglia的插件check_ganglia.py
cd /usr/local/nagios/libexec
vi check_ganglia.py #内容如下:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import sys
import getopt
import socket
import xml.parsers.expat

class GParser:
  def __init__(self, host, metric):
    self.inhost =0
    self.inmetric = 0
    self.value = None
    self.host = host
    self.metric = metric

  def parse(self, file):
    p = xml.parsers.expat.ParserCreate()
    p.StartElementHandler = parser.start_element
    p.EndElementHandler = parser.end_element
    p.ParseFile(file)
    if self.value == None:
      raise Exception('Host/value not found')
    return float(self.value)

  def start_element(self, name, attrs):
    if name == "HOST":
      if attrs["NAME"]==self.host:
        self.inhost=1
    elif self.inhost==1 and name == "METRIC" and attrs["NAME"]==self.metric:
      self.value=attrs["VAL"]

  def end_element(self, name):
    if name == "HOST" and self.inhost==1:
      self.inhost=0

def usage():
 print """Usage: check_ganglia 
-h|--host= -m|--metric= -w|--warning= 
-c|--critical= [-o|--opposite=] [-s|--server=] [-p|--port=] """
 sys.exit(3)

if __name__ == "__main__":
##############################################################
 ganglia_host = 'x.x.x.x'  #修改为你的gmetad主机的ip
 ganglia_port = 8651
 host = None
 metric = None
 warning = None
 critical = None
 opposite = 0  ##增加一个参数,表示设定值取反,也就是当实际值小于等于设定值报警

 try:
   options, args = getopt.getopt(sys.argv[1:],
     "h:m:w:c:o:s:p:",
     ["host=", "metric=", "warning=","critical=","opposite=", "server=","port="],
     )
 except getopt.GetoptError, err:
   print "check_gmond:", str(err)
   usage()
   sys.exit(3)

 for o, a in options:
   if o in ("-h", "--host"):
      host = a
   elif o in ("-m", "--metric"):
      metric = a
   elif o in ("-w", "--warning"):
      warning = float(a)
   elif o in ("-c", "--critical"):
      critical = float(a)
   elif o in ("-o", "--opposite"):
      opposite = int(a)
   elif o in ("-p", "--port"):
      ganglia_port = int(a)
   elif o in ("-s", "--server"):
      ganglia_host = a


 if critical == None or warning == None or metric == None or host ==None:
   usage()
   sys.exit(3)

 try:
   s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   s.connect((ganglia_host,ganglia_port))
   parser = GParser(host, metric)
   value = parser.parse(s.makefile("r"))
   s.close()
 except Exception, err:
   #import pdb
   #pdb.set_trace()
   print "CHECKGANGLIA UNKNOWN: Error while getting value"%s"" % (err)
   sys.exit(3)

 if opposite == 1: ###根据传入参数做判断,等于1时,表示取反,等于0,不取反
      if value &lt;= critical:
        print &quot;CHECKGANGLIA CRITICAL: %s is %.2f&quot; % (metric, value)
        sys.exit(2)
      elif value = critical:
        print "CHECKGANGLIA CRITICAL: %s is %.2f" % (metric, value)
        sys.exit(2)
      elif value &gt;= warning:
          print "CHECKGANGLIA WARNING: %sis %.2f" % (metric, value)
          sys.exit(1)
      else:
        print "CHECKGANGLIA OK: %s is %.2f" % (metric, value)
        sys.exit(0)

修改该脚本为可读写、操作权限:

 chmod 755 check_ganglia.py

在如下目录,新建文件:(注意啊,里面最好不要有注释,可能会引起功能不可用,原因我没时间去分析)

#在/usr/local/nagios/etc/objects/下新建一个services.cfg
cd /usr/local/nagios/etc/objects/
vi services.cfg #内容如下:
define host {
    use linux-server
    host_name wl1
    address   x.x.x.1
}

define host {
    use linux-server
    host_name wl2
    address   x.x.x.2
}

define host {
    use linux-server
    host_name wl3
    address   x.x.x.3
}

define hostgroup {
    hostgroup_name ganglia-servers
    alias   nagios server
    members *
}

define servicegroup {
  servicegroup_name ganglia-metrics
  alias Ganglia Metrics
}

define command {
  command_name check_ganglia
  command_line $USER1$/check_ganglia.py -h $HOSTNAME$ -m $ARG1$ -w $ARG2$ -c $ARG3$ -o $ARG4$
}

define service {
    use generic-service
    name ganglia-service
    hostgroup_name ganglia-servers
    service_groups ganglia-metrics
    notifications_enabled 1
    notification_interval 10
    register  0
}

define service{
        use                             ganglia-service
        service_description             内存空闲
        check_command                   check_ganglia!mem_free!200!50!1
        contact_groups admins
}

define service{
        use                             ganglia-service
        service_description             load_one
        check_command                   check_ganglia!load_one!4!5!0
        contact_groups admins
}
define service{
        use                             ganglia-service
        service_description             disc_free
        check_command                   check_ganglia!disk_free!40!50!0
        contact_groups admins
}
define service{
        use                             ganglia-service
        service_description             yarn.NodeManagerMetrics.AvailableGB
        check_command                   check_ganglia!yarn.NodeManagerMetrics.AvailableGB!8!4!1
        contact_groups admins
}

需要注意的是,这个services.cfg文件就是用来你的Nagios自动去Ganglia里面取数据的,里面定义的需要关注的Ganglia的项目越多,Nagios里面显示的越多,我这里仅仅是一个范本,只举例了几个简单的数据,如果有需要,请自行增加。

修改该配置文件为可读写、操作权限:

chown nagios:nagios services.cfg
chmod 664 services.cfg

修改Nagios主配置文件:

vi /usr/local/nagios/etc/nagios.cfg
#cfg_file=/usr/local/nagios/etc/objects/localhost.cfg

#add by wangliang for ganglia
cfg_file=/usr/local/nagios/etc/objects/services.cfg

修改和发送告警邮件相关的配置:

vi /usr/local/nagios/etc/objects/commands.cfg
#将其中的/bin/mail替换为mail
# 'notify-host-by-email' command definition
define command{
        command_name    notify-host-by-email
        command_line    /usr/bin/printf "%b" "***** Nagios *****nnNotification Type: $NOTIFICATIONTYPE$nHost: $HOSTNAME$nState: $HOSTSTATE$nAddress: $HOSTADDRESS$nInfo: $HOSTOUTPUT$nnDate/Time: $LONGDATETIME$n" | mail -s "** $NOTIFICATIONTYPE$ Host Alert: $HOSTNAME$ is $HOSTSTATE$ **" $CONTACTEMAIL$
        }

# 'notify-service-by-email' command definition
define command{
        command_name    notify-service-by-email
        command_line    /usr/bin/printf "%b" "***** Nagios *****nnNotification Type: $NOTIFICATIONTYPE$nnService: $SERVICEDESC$nHost: $HOSTALIAS$nAddress: $HOSTADDRESS$nState: $SERVICESTATE$nnDate/Time: $LONGDATETIME$nnAdditional Info:nn$SERVICEOUTPUT$n" | mail -s "** $NOTIFICATIONTYPE$ Service Alert: $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$ **" $CONTACTEMAIL$
        }

#修改发送的邮件地址和收件人:
vi /usr/local/nagios/etc/objects/contacts.cfg
###############################################################################
# CONTACTS.CFG - SAMPLE CONTACT/CONTACTGROUP DEFINITIONS
#
#
# NOTES: This config file provides you with some example contact and contact
#        group definitions that you can reference in host and service
#        definitions.
#
#        You don't need to keep these definitions in a separate file from your
#        other object definitions.  This has been done just to make things
#        easier to understand.
#
###############################################################################



###############################################################################
###############################################################################
#
# CONTACTS
#
###############################################################################
###############################################################################

# Just one contact defined by default - the Nagios admin (that's you)
# This contact definition inherits a lot of default values from the 'generic-contact'
# template which is defined elsewhere.

define contact{
        contact_name                    nagiosadmin        ; Short name of user
    use                generic-contact        ; Inherit default values from generic-contact template (defined above)
        alias                           Nagios Admin        ; Full name of user

        email                           [email protected]    ; &lt;&lt;***** CHANGE THIS TO YOUR EMAIL ADDRESS ******
        }

define contact{
        contact_name                    nagiosadmin2           ; Short name of user
        use                             generic-contact         ; Inherit default values from generic-contact template (defined above)
        alias                           Nagios Admin2            ; Full name of user

        email                           [email protected]     ; &lt;&lt;***** CHANGE THIS TO YOUR EMAIL ADDRESS ******
        }

define contact{
        contact_name                    nagiosadmin3             ; Short name of user
        use                             generic-contact         ; Inherit default values from generic-contact template (defined above)
        alias                           Nagios Admin3            ; Full name of user

        email                          [email protected]     ; &lt;&lt;***** CHANGE THIS TO YOUR EMAIL ADDRESS ******
        }
###############################################################################
###############################################################################
#
# CONTACT GROUPS
#
###############################################################################
###############################################################################

# We only have one contact in this simple configuration file, so there is
# no need to create more than one contact group.

define contactgroup{
        contactgroup_name       admins
        alias                   Nagios Administrators
        members            *
        }

利用如下命令,判断修改是否成功:

/usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios.cfg
Total Warnings: 0
Total Errors:   0

按顺序重启相关服务:

sudo /etc/init.d/ganglia-monitor restart  (所有节点)
sudo /etc/init.d/gmetad restart       (gmetad节点)
sudo /etc/init.d/apache2 restart      (gweb节点)
service nagios restart    (nagios节点)
service sendmail restart  (nagios节点)

最后的效果图如下:
(nagios采集数据的过程略慢,有的时候会短暂的显示service status是unknown或者pending,过一会就会好的,不用着急)

监控

收到的邮件告警的图示:

监控

下一步工作是把这几个组件做成docker镜像,用k8s调度,具体过程不在详述,参考我前面的文章就可以完成。

需要注意的地方:

  1. 如果你想在Ganglia Web上显示各节点的主机名,则需要提前在
    gmetad节点的/etc/hosts里面配置好ip和hostname的映射关系,ganglia会在收到各节点数据时,先按照ip查找hosts里面的hostname,如果没有,则rrd中就按照ip存储;如果有,则rrd中按照查到的名字存储,Web显示数据时,是根据rrd中的记录的名字或者Ip来显示的。

  2. 如果你以前是按照ip显示,后来想改成hostname,则先要把rrd的内容清空,反之亦然。

  3. 记得rrd的权限是:
    drwxr-xr-x nobody nogroup rrds/
    否则网页会提示拒绝连接

  4. 由于sendmail使用的是smtp协议,而有的公司用的是esmtp协议的服务器,所以用本文描述的sendmail发送告警邮件可能邮箱会收不到。后来我使用了sendEmail的工具,它可以使用esmtp协议,如下格式:sendEmail -f [email protected] -t [email protected] -s smtp.exmail.qq.com -xu [email protected] -xp xxx -m “test”
    进行测试,就可以发送成功啦,
    安装很简单,参考此处:http://www.linuxidc.com/Linux/2011-12/49699.htm
    需要同步修改nagios的/usr/local/nagios/etc/objects/commands.cfg

define command{
        command_name    notify-host-by-email
        command_line    /usr/bin/printf &quot;%b&quot; &quot;***** Nagios *****nnNotification Type: $NOTIFICATIONTYPE$nHost: $HOSTNAME$nState: $HOSTSTATE$nAddress: $HOSTADDRESS$nInfo: $HOSTOUTPUT$nnDate/Time: $LONGDATETIME$n&quot; | /usr/local/bin/sendEmail -f [email protected] -t $CONTACTEMAIL$ -s smtp.exmail.qq.com -u &quot;** $NOTIFICATIONTYPE$ Host Alert: $HOSTNAME$ is $HOSTSTATE$ **&quot; -xu [email protected] -xp xxxx
        }

# 'notify-service-by-email' command definition
define command{
        command_name    notify-service-by-email
        command_line    /usr/bin/printf &quot;%b&quot; &quot;***** Nagios *****nnNotification Type: $NOTIFICATIONTYPE$nnService: $SERVICEDESC$nHost: $HOSTALIAS$nAddress: $HOSTADDRESS$nState: $SERVICESTATE$nnDate/Time: $LONGDATETIME$nnAdditional Info:nn$SERVICEOUTPUT$n&quot; | /usr/local/bin/sendEmail -f [email protected] -t $CONTACTEMAIL$ -s smtp.exmail.qq.com -u &quot;** $NOTIFICATIONTYPE$ Service Alert: $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$ **&quot; -xu [email protected] -xp xxx
        }

Linux CentOS 7.2 MySQL的root密码忘记时重置方法

验证环境:

[root@~~/]# rpm -qa | grep mysql
mysql-5.6.28-1.el6.x86_64
[root@~~/]# lsb_release -a
LSB Version:    :core-4.1-amd64:core-4.1-noarch
Distributor ID: CentOS
Description:    CentOS Linux release 7.2.1511 (Core)
Release:        7.2.1511
Codename:       Core
[root@~~/]# uname -r
3.10.0-327.22.2.el7.x86_64

首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库。
因为在重新设置mysql的root密码的期间,MySQL数据库完全出于没有密码保护的状态下,其他的用户也可以任意地登录和修改MySQL的信息。可以采用将MySQL对外的端口封闭,并且停止Apache以及所有的用户进程的方法实现服务器的准安全状态。最安全的状态是到服务器的Console上面操作,并且拔掉网线。

修改MySQL的登录设置:

在[mysqld]的段中加上一句:skip-grant-tables
[root@~~/]# vi /etc/my.cnf
例如: 
[mysqld] 
datadir=/var/lib/mysql 
socket=/var/lib/mysql/mysql.sock 
skip-grant-tables 
保存并且退出vi。

重新启动mysqld

[root@~~/]# /etc/init.d/mysqld restart 
Stopping MySQL: [ OK ] 
Starting MySQL: [ OK ]

登录并修改MySQL的root密码

[root@~~/]# mysql
Welcome to the MySQL monitor.  Commands end with ; or g.
Your MySQL connection id is 1
Server version: 5.6.28-log Source distribution
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
mysql> use mysql;
mysql> update user set password=password("test") where user='root';
mysql> flush privileges;
mysql> exit; 
Bye

将MySQL的登录设置修改回来

将刚才在[mysqld]的段中加上的skip-grant-tables删除,保存并且退出vi;

[root@~~/]# vi /etc/my.cnf
保存并且退出vi。

再次重新启动mysqld

[root@~~/]# /etc/init.d/mysqld restart 
Stopping MySQL: [ OK ] 
Starting MySQL: [ OK ]

使用新的密码登录,正常登录

如果外网不能访问数据库,可以进行如下操作:

[root@~~/]# firewall-cmd --permanent --zone=public --add-port=3306/tcp  
success
[root@~~/]# firewall-cmd --reload
success

linux常用命令介绍

  1. 查看当前终端名:tty 或who am i

    查看当前所有登录的终端信息:who

    查看当前所有登录的终端的详细信息 w

  2. 编辑器

Gedit 只能在图形化界面编辑,不能远程编辑。

Nano 可以远程登陆后编辑

(开机后自动登录图形化界面:/etc/gdm/custom.conf

           [damon]

            AutomaticLoginEnable=True

       AutomaticLogin=root)

系统管理

修改登录前的信息 /etc/issue 完成后ctrl+x退出

系统管理

修改登陆后的信息 /etc/motd (佛祖保佑,永不死机:先在图形化界面安装光盘,然后把motd放在一个目录下,在终端敲rz(把物理机里的文件拷到虚拟机目录下

sz与此相反),找到motd文件,然后敲ls查看文件,如果有motd文件名说明拷贝成功,然后cp motd /etc/motd/(把etc下的motd 文件覆盖一下),敲y,然后cat /etc/motd就完成了。就会出现如图所示的效果:

系统管理

  • 内部命令与外部命令
    判断命令的类型: tupe +命令
    

系统管理

    显示所有启动的内部命令: enable

系统管理

统计启动的内部命令的个数:enable |wc -l

系统管理

  • Enable -n 显示被禁用的内部命令

  • Enable -n 命令名 禁用这个命令

  • Enable -n |wc -l 统计禁用的内部命令的个数

  • Enable -n command 仅用一个内部命令

  • alias 内部命令 > hsah >
    PATH > command not find

       Alias  显示当前已定义的别名
    

系统管理

Alias aliasname=’command[-x]
[….]’ 定义别名

Unlias aliname 取消定义别名

Unalias -a 取消所有的别名

(cp + -i 覆盖文件时才会提示,rm删除文件时也一样。)

  • Hwcolock 查看硬时间

  • Hwclock -s 将硬时间写入软时间(系统时间)

  • Hwclock -w 将软时间写入硬时间

  • Clock= hwclock

  • 修改时区

     Centos6    ln  -f /usr/share/zoneinfo /America/New _York/etc/localtime
    
                Ln -f /usr/share/zoneinfo
    

    /Asia/Shanghai/etc/localtime

     Centos7
    
                Timedatectl 查看当前时区
    

系统管理

                Timedatectl

list-timezone 查看所有的时区

    修改时区    Timedatectl

set-timezone America/New_York

                Timedatectl set-timezone

Asia/Shanghai

系统管理

  • Screen
      Screen 进入screen 名字以当前终端名.主机名前缀
    
      Screen
    

    -S screenname 创建会话

      Screen
    

    -ls 或–list 查看当前所有的screen

系统管理

      Screen

-r screenname 进入一个screen

       Ctrl +c 或exit退出screen

       Screen 恢复screen页面

       Screen +x screenname  加入会话

       Ctrl

+a同时按松手后按d 剥离会话

  • $的用法
        $变量名 引用变量的值
    
        $()或‘’引用命令执行的结果
    
        $[]运算
    
        ${变量名}或“$变量名”当变量名的起止不分明时,用来划定变量名的范围,同时引用变量。
    
  • {}的用法

    {a..z}表示引用指定范围的字母

    {1..9990}表示引用指定范围的数字

    {1,3,5}表示分别引用每一个字符

  • Tab

    补齐

    2tab 把根下所有的文件列出

    ~2tab 家目录下的所有文件列出

系统管理

 .2tab 当前目录下的所有文件列出,包含隐藏文件

 *2tab当前目录下的所有文件列出,不包含隐藏文件

 $2tab 显示当前所有的环境变量

系统管理

 =2tab=ls -A 显示上一级命令

设置MySQL数据库表名不区分大小写的方法

问题说明

MySQL 如何设置不区分表名大小写。

处理办法

一般情况下 Linux 服务器默认安装 MySQL 的数据库表名是区分大小写的,如果 ECS 上安装的 MySQL 不支持表名区分大小下,则按照如下方法操作即可:

  1. 用 root 登录,修改 /etc/my.cnf (注意:以实际 my.cnf 配置文件路径为准)

  2. 在 [mysqld] 节点下,加入一行: lower_case_table_names=1

  3. 重启 MySQL 即可;

MongoDB shell常用操作

shell命令操作语法和JavaScript很类似,其实控制台底层的查询语句都是用javascript脚本完成操作的。使用shell 命令,需要启动mongo.exe。

常用shell命令如下:

1、查询本地所有数据库名称

> show dbs;

2、切换至指定数据库环境(若无指定的数据库,则创建新的库)

> use mydb;

3、查询当前库下的所有聚集集合collection(相当于table)

> show collections;

4、创建聚集集合

> db.createCollection('mycollection');

5、查询聚集集合中数据条数

> db.mycollection.count();

6、插入数据

> db.mycollection.insert({'username':'xyz_lmn','age':26,'salary':120});

往’mycollection’聚集集合中插上一条数库,name为’xyz_lmn’,age为’26’,salary为’120′

7、查询age等于26的数据

> db.mycollection.find({"age":26});

8、查询salary大于100的数据

> db.mycollection.find({salary:{$gt:100}});

9、查询age小于30,salary大于100的数据

> db.mycollection.find({age:{$lt:30}},{salary:{$gt:100}});

10、查询salary小于40或salary大于200的数据

> db.mycollection.find({$or: [{salary: {$lt:40}}, {salary: {$gt:200}}]});

11、查询指定列的数据

> db.mycollection.find({},{age:1,salary:1});

1表示显示此列的意思,也可以用true表示

12、查询username中包含’e’的数据

> db.mycollection.find({username:/e/});

13、查询以a打头的数据

> db.mycollection.find({username:/^a/});

14、查询age列数据,并去掉重复数据

> db.mycollection.distinct('age');

15、查询前10条数据

> db.mycollection.find().limit(10);

16、查询1条以后的所有数据

> db.mycollection.find().skip(1);

17、查询第一条数据

> db.mycollection.findOne();

18、查询结果集的记录数(查询salary小于40或大于100的记录数)

db.mycollection.find({$or: [{salary: {$lt:40}}, {salary: {$gt:100}}]}).count();

19、按salary升序排序

> db.mycollection.find().sort({salary:1});

按照salary字段升序排序

20、降序

> db.mycollection.find().sort({salary:-1});

按照salary字段降序排序

21、根据username修改age

> db.employee.update({username:'jim'},{$set:{age:22}},false,true);
db.collection.update( criteria, objNew, upsert, multi )
  • criteria : update的查询条件,类似sql update查询内where后面的

  • objNew : update的对象和一些更新的操作符(如$,$inc…)等,也可以理解为sql update查询内set后面的

  • upsert : 如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。

  • multi : MongoDB默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。

22、将指定username的age字段增加5

> db.mycollection.update({username:'jim'},{$inc:{age:5}},false,true);

将username为‘jim’的age字段加5

23、删除username为’rose’的数据

> db.mycollection.remove({uname:'rose'});

24、集合collection重命名

> db.mycollection.renameCollection('c_temp');

将mycollection集合重命名为’c_temp’

25、删除集合

> db.c_temp.drop();

删除名为’c_temp’的集合

26、删除当前数据库

> db.dropDatabase();

未分类

MongoDB如何添加用户

  1. 不需要验证启动mongodb
  2. 添加用户

创建用户

db.createUser({
    user: 'testname',  // 用户名
    pwd: 'testpwd', // 密码
    roles: [
        {
            role: 'readWrite', // 读写权限
            db: 'test'  // 所属数据库
        }
    ]
})

需要验证启动MongoDB

mongod --dbpath mongoData --auth
show dbs // 报错,因为没有验证
use test // 切换到test数据库
db.auth('testname', 'testpwd') // 1
show collections // 可以查看表
use local // 切换到local数据
show collections // 报错
db.auth('testname', 'testpwd') // 报错,因为testname是test数据的用户

需要了解的概念:

  1. mongodb可以同时存在多个数据库。

  2. mongodb的用户是属于某个数据库的。即,你创建的某个用户只能在一数据库中使用。

  3. mongodb启动有两种模式,需要验证和不需要验证。默认不需要验证,当你使用验证模式启动后,对数据的所有操作必须通过验证并且具有相应权限才可以操作。

修改密码

use test // 切换到test数据库
db.auth('testname', 'testpwd') // 验证
db.changeUserPassword('testname', 'newtestpwd') // 修改密码

配置及测试mongodb副本集

mongodb副本集即客户端连接到整个副本集,不关心具体哪一台机器是否挂掉。主服务器负责整个副本集的读写,副本集定期同步数据备份,一旦主节点挂掉,副本节点就会选举一个新的主服务器,这一切对于应用服务器不需要关心。副本集中的副本节点在主节点挂掉后通过心跳机制检测到后,就会在集群内发起主节点的选举机制,自动选举一位新的主服务器。选举还有个前提条件,参与选举的节点数量必须大于副本集总节点数量的一半,如果已经小于一半了所有节点保持只读状态。因此,官方推荐我们的副本集机器数量至少为3个:一个主节点,两个副本节点。当然,mongodb副本集中可以有很多类型的节点,其中有一个仲裁节点,即当参与选举的节点无法选出主节点时仲裁节点充当仲裁的作用。仲裁节点不存储数据,只是仲裁。所以,我们的副本集可以设置为:1主+1从+1仲裁。

那么我们准备3台服务器:192.168.198.224(主),192.168.198.225(从),192.168.198.226(仲裁)。

1、分别在每台机器上下载解压mongodb安装包

curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-amazon-3.4.6.tgz
tar -zxvf mongodb-linux-x86_64-amazon-3.4.6.tgz
mv mongodb-linux-x86_64-amazon-3.4.6/ /usr/local/mongodb

2、分别在每台机器上创建mongodb的data、log以及配置目录

cd /usr/local/mongodb
mkdir -p data/db
mkdir log
touch log/mongod.log
mkdir etc
touch etc/mongod.conf

3、分别在每台机器上配置config文件

vim etc/mongod.conf

为了启动方便,我们可以将mongodb的启动配置项直接在配置文件中:

dbpath = /usr/local/mongodb/data/db        # 指定数据库路径
logpath = /usr/local/mongodb/log/mongod.log          # 指定mongodb日志文件
logappend = true        # 使用追加的方式写日志
port = 27017               #设置端口号为27017
fork = true                   #设置以守护进程的方式启动mongod
replSet = myrs            #设置副本集的名字为myrs,同一副本集群的replSet名称必需相同

4、分别在每台机器上启动副本集

cd /usr/local/mongodb
./bin/mongod -f ./etc/mongod.conf    #指定以mongod.conf配置启动mongod

5、初始化副本集

登录任意一台机器的mongodb后台管理shell:

cd /usr/local/mongodb
./bin/mongo
use admin
config = {
"_id":"rs0",
"members":[
  {"_id":0,"host":"192.168.198.223:27017"},
  {"_id":1,"host":"192.168.198.225:27017"},
  {"_id":2,"host":"192.168.198.226:27017",arbiterOnly:true}
]
}
rs.initiate(config);   #初始化配置

注意:如果执行rs.initiate(config)报错,那么我们需要检查三台服务器的防火墙27017端口是否开放。 如果没有问题,我们可以查看集群节点:

rs.status();

至此,整个副本集已经搭建成功了。
那么,我们可以测试一下副本集的基本功能:

1、测试副本集的数据复制功能

此时在我的机器上192.168.198.224是主节点,我们用mongo来登录shell。

cd /usr/local/mongodb
./bin/mongo
use test  #创建test数据库
db.testdb.insert({"name":"yaya"});       #插入数据

我们用副本节点登录shell,我这里是192.168.198.225:

cd /usr/local/mongodb
./bin/mongo
use test
show tables

此时会报错:

[thread1] Error: listCollections failed: {
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk"
} 

因为mongodb默认是从主节点读写数据的,副本节点上不允许读,需要设置副本节点可以读。

myrs:SECONDARY> db.getMongo().setSlaveOk();

此时就可以读取数据了:

repset:SECONDARY> db.testdb.find();

控制台输出:{ “_id” : ObjectId(“59676d711881041abab44477”), “name” : “yaya” }
所以,数据复制的功能是可用的。

2、测试副本集的故障转移功能

将主节点192.168.198.224的mongod进程杀死:

myrs:PRIMARY> use admin
myrs:PRIMARY> db.shutdownServer()

此时可以看到,192.168.198.225原本是副节点,此时自动转换为主节点。可以通过rs.status()来查看。

MongoDB数据库文档操作示例

前面的话

本文将详细介绍MongoDB数据库关于文档的增删改查

插入文档

  要将数据插入到 MongoDB 集合中,需要使用 MongoDB 的 insert()或save()方法,还有insertOne()或insertMany()方法

【insert()】

insert()命令的基本语法如下

db.COLLECTION_NAME.insert(document)

在插入的文档中,如果不指定_id参数,那么 MongoDB 会为此文档分配一个唯一的ObjectId。_id为集合中的每个文档唯一的12个字节的十六进制数

如果数据库中不存在集合,则MongoDB将创建此集合,然后将文档插入到该集合中

未分类

要在单个查询中插入多个文档,可以在insert()命令中传递文档数组

未分类

可以使用js语法,插入多个文档

未分类

【save()】

插入文档也可以使用db.post.save(document)。 如果不在文档中指定_id,那么save()方法将与insert()方法一样自动分配ID的值。如果指定_id,则将以save()方法的形式替换包含_id的文档的全部数据。

也就是说save()方法和insert()方法的区别是,save()方法可以复写或修改,而insert()方法不可以

db.post.save(document)

未分类

未分类

【insertOne()】

使用db.collection.insertOne()方法可以将单个文档插入到集合中

未分类

【insertMany()】

  使用db.collection.insertMany()方法可以将多个文档插入到集合中

未分类

查询文档

【find()】

  要从MongoDB集合查询数据,需要使用MongoDB的find()方法,默认返回结果中的前20条文档,输入”it”显示接下来的20条文档。

  find()命令的基本语法如下:

db.COLLECTION_NAME.find(document)

  find()方法将以非结构化的方式显示所有文档

未分类

  可以限定查询条件

未分类

  可以通过find 的第二个参数来指定返回的键,值为1或true表示显示该键,值为0或false表示不显示该键

未分类

  find()方法下的count()方法可以显示符合条件的文档数量

未分类

【findOne()】

  findOne()方法只返回一个文档,该文档是最早被添加的文档

未分类

【比较操作符】

小于        {<key>:{$lt:<value>}}    
小于或等于    {<key>:{$lte:<value>}}    
大于        {<key>:{$gt:<value>}}    
大于或等于    {<key>:{$gte:<value>}}    
不等于      {<key>:{$ne:<value>}}
等于        {<key>:{$eq:<value>}}

  取得x小于2的值

未分类

  取得x大于等于2的值

未分类

  取得x不等于2的值

未分类

【逻辑操作符】

  可以使用逻辑操作符and、and、or来表示与、或

 { $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] }
{ $nor: [ { <expression1> }, { <expression2> }, ... { <expressionN> } ] }

未分类

【正则表达式】

  文档查询可以使用正则表达式,但只支持字符串类型的数据

未分类

【$where】

  $where操作符功能强大而且灵活,它可以使用任意的JavaScript作为查询的一部分,包含JavaScript表达式的字符串或者JavaScript函数

未分类

  使用字符串

未分类

  使用函数

未分类

限制与跳过
【limit()】

  如果需要在MongoDB中读取指定数量的数据记录,可以使用MongoDB的Limit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数

  默认返回结果中的前20条文档,输入”it”显示接下来的20条文档

  如果没有指定limit()方法中的参数则显示集合中的所有数据

db.COLLECTION_NAME.find().limit(NUMBER)

未分类

【skip()】

  可以使用skip()方法来跳过指定数量的数据,skip方法同样接受一个数字参数作为跳过的记录条数

db.COLLECTION_NAME.find().skip(NUMBER)

未分类

排序
【sort()】

  在MongoDB中使用sort()方法对数据进行排序,sort()方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而-1是用于降序排列

db.COLLECTION_NAME.find().sort({KEY:1})

未分类

更新文档
  MongoDB 使用update()或save()方法来更新集合中的文档

【update()】

  update() 方法用于更新已存在的文档。语法格式如下:

db.collection.update(<query>,<update>,{upsert:<boolean>, multi: <boolean>,writeConcern:<document>})
query : update的查询条件,类似sql update查询内where后面的
update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入
multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新
writeConcern :可选,抛出异常的级别

 
 [注意]经过测试,upsert参数无法设置为true或者false,都可以插入新的字段

未分类

  mongodb默认只更新找到的第一条记录,将x:1,更新为x:10

未分类

  要特别注意的是,如果不使用$set,则将文档的内容替换为x:10

未分类

  更新全部记录,将x:10,更新为x:1

未分类

  mongodb默认只添加到更新找到的第一条记录,将x:1的记录,添加z:1

未分类

  将找到的x:2的全部记录,添加z:2

未分类

【save()】

  save()方法可以插入或更新文档,如果参数中的文档的_id与集合中所存在的_id都不同,则插入;如果相同,则更新

未分类

删除文档

  MongoDB remove()函数是用来移除集合中的数据

【remove()】

  默认地,mongodb删除符合条件的所有文档

db.collection.remove(<query>,{justOne: <boolean>, writeConcern: <document>})
query :删除的文档的条件。
justOne : (可选)如果设为 true 或 1,则只删除一个文档。
writeConcern :(可选)抛出异常的级别。

  只删除符合条件的第一个文档 

未分类

  删除符合条件的所有文档 

未分类

php-memcached扩展安装及使用方法

客户端下载

客户端下载:
https://docs-aliyun.cn-hangzhou.oss.aliyun-inc.com/cn/ocs/0.1.9/assets/libmemcached-1.0.16.gz?spm=5176.doc48432.2.1.eQ5tPY&file=libmemcached-1.0.16.gz

客户端介绍:
http://pecl.php.net/support.php?spm=5176.doc48432.2.2.eQ5tPY

客户端版本介绍:
http://pecl.php.net/package/memcached?spm=5176.doc48432.2.3.GstFhV

系统要求及环境配置

注意:您已经有 php memcache 等环境,请注意教程中的一些提示,以免生产环境被覆盖,导致业务不可用,在升级及再编译环境前请做好环境备份。

windows 系列版本

如果采用标准的 php memcached 扩展不能成功搭建,可以考虑换成手工拼包的形式来访问云数据库 Memcache,连接方式请参考如下链接,示例代码非常简单,与 php memcached 的区别就是仅支持主流接口,需自己补充某些特定接口,安装及使用方法请参见这里。

Centos 及 Aliyun Linux 6系列版本

注意:Memcached 2.2.0 扩展必须使用 libmemcached 1.0.x 的库,低于1.0的库不再能够成功编译。编译 libmemcached 时 GCC 要求在4.2及以上。

  • 确认是否安装了gcc-c++ 等组件(使用 gcc –v 查看版本是否为4.2及以上)。如没有请执行 yum install gcc+ gcc-c++。

  • 执行 rpm –qa | grep php 查看系统中是否有 PHP 环境,如果没有则执行 yum install php-devel,php-common,php-cli 安装包含源码编译的 PHP。
    建议使用 php 5.3及以上版本。php 5.2部分版本系列源代码会有 zend_parse_parameters_none 函数会出错,如需使用请参照 php 官方相关文档。如是源代码编译,请按照官方 php 编译升级的办法进行。

  • 检测是否有已安装了 SASL 相关环境包,如没有,则执行 yum install cyrus-sasl-plain cyrus-sasl cyrus-sasl-devel cyrus-sasl-lib 安装 SASL 相关环境。

  • 检测下是否有已安装了 libmemcached 源码包,若没有,则执行以下命令安装 libmemcached 源码包(推荐版本 libmemcached-1.0.18)。

 wget https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gz 
 tar zxvf libmemcached-1.0.18.tar.gz
 cd libmemcached-1.0.18
 ./configure --prefix=/usr/local/libmemcached --enable-sasl
 make
 make install
 cd ..
  • 执行 yum install zlib-devel 安装 memcached 源码包(推荐版本为 memcached-2.2.0)。

注意:

  • 安装 memcached 前需要确认是否有 zlib-devel 包需要执行。

  • 请先检测下是否已安装了 memcached 客户端包(包含源码包)。如有则不需要安装,但需要重新编译增加 -enable-memcached-sasl 这个扩展。

wget http://pecl.php.net/get/memcached-2.2.0.tgz
tar zxvf memcached-2.2.0.tgz
cd memcached-2.2.0
phpize(如果系统中有两套PHP环境,需绝对路径调用该命令/usr/bin/phpize,该路径为使用云数据库Memcache的PHP环境路径)
./configure --with-libmemcached-dir=/usr/local/libmemcached --enable-memcached-sasl(注意这个参数)
make
make install
  • 修改 php.ini 文件(locate 找该文件,如果系统中有两套 PHP 环境,需找到使用云数据库 Memcache 的 PHP 环境路径,对应修改之),增加
extension=memcached.so memcached.use_sasl = 1。
  • 使用该页面最后的测试代码测试下是否环境部署成功,请修改代码中相应的地址、端口、用户名及密码。

Centos及 Aliyun Linux 5系列版本 【64位版本】

  • 确认是否安装了 gcc-c++ 等组件。如没有请执行 yum install gcc+ gcc-c++ 。

  • 执行rpm –qa | grep php 查看系统中是否有 php 环境,如果没有则执行 yum install php53 php53-devel 安装包含源码编译的 php;如有 php 则不要安装。建议使用 php 5.3(含)以上版。

php 5.2部分版本系列源代码会有 zend_parse_parameters_none 函数会出错,如需使用请参照 php 官方相关文档。

  • 执行 yum install cyrus-sasl-plain cyrus-sasl cyrus-sasl-devel cyrus-sasl-lib 安装 SASL 相关环境。

  • 检测下是否已安装了 libmemcached(包含源码包),如有则不需要安装,如没有则执行以下命令安装(推荐版本 libmemcached 1.0.2)。

 wget http://launchpad.net/libmemcached/1.0/1.0.2/+download/libmemcached-1.0.2.tar.gz
 tar -zxvf libmemcached-1.0.2.tar.gz
 cd libmemcached-1.0.2
 ./configure --prefix=/usr/local/libmemcached --enable-sasl
 make
 make install
 cd ..
  • 执行 yum install zlib-devel 安装源码包 memcached(推荐版本 memcached 2.0)。

注意:

  • 安装 memcached 前需要确认是否有 zlib-devel 包需要执行。

  • 请先检测下是否有已安装了 memcached 客户端包(包含源码包)。如有则不需要安装,但需要重新编译增加 -enable-memcached-sasl 这个扩展。

wget http://pecl.php.net/get/memcached-2.0.0.tgz tar -zxvf memcached-2.0.0.tgz 
cd memcached-2.0.0 phpize(如果系统中有两套PHP环境,需绝对路径调用该命令/usr/bin/phpize,该路径为使用云数据库Memcache的PHP环境路径,请在memcached源码目录内执行phpize) 
./configure --with-libmemcached-dir=/usr/local/libmemcached --enable-memcached-sasl(注意这个参数) 
make 
make install
  • 修改 php.ini 文件(locate 找该文件,yum 安装的一般在 /etc/php.ini。 如果系统中有两套 PHP 环境,需找到使用云数据库 Memcache 的 PHP 环境路径,对应修改之),增加 extension=memcached.so memcached.use_sasl = 1 。

  • 执行 php –m |grep ,memcached ,若显结果有 memcache 表示环境已支持 memcache。

  • 使用该页面最后的测试代码测试下是否环境部署成功,请修改代码中相应的地址、端口、用户名及密码。

Ubuntu Debian 等系列版本

  • 变更 ubuntu 源。

方案一:执行 vim /etc/apt/source.list,在最前面添加以下内容。

 deb http://mirrors.aliyun.com/ubuntu/ precise main restricted universe multiverse
 deb http://mirrors.aliyun.com/ubuntu/ precise-security main restricted universe multiverse
 deb http://mirrors.aliyun.com/ubuntu/ precise-updates main restricted universe multiverse
 deb http://mirrors.aliyun.com/ubuntu/ precise-proposed main restricted universe multiverse
 deb http://mirrors.aliyun.com/ubuntu/ precise-backports main restricted universe multiverse
 deb-src http://mirrors.aliyun.com/ubuntu/ precise main restricted universe multiverse
 deb-src http://mirrors.aliyun.com/ubuntu/ precise-security main restricted universe multiverse
 deb-src http://mirrors.aliyun.com/ubuntu/ precise-updates main restricted universe multiverse
 deb-src http://mirrors.aliyun.com/ubuntu/ precise-proposed main restricted universe multiverse
 deb-src http://mirrors.aliyun.com/ubuntu/ precise-backports main restricted universe multiverse
 apt-get update //更新一下列表

方案二: 通过 wget http://oss.aliyuncs.com/aliyunecs/update_source.zip 下载 update_source 的压缩包,解压后予执行权限 chmod 777 文件名 ,然后执行该脚本进行自动变更源操作。

  • 通过 ape-get 配置 GCC,G++ 。

首先需要使用 dpkg –s 安装包名,例如 dpkg –s gcc,确认是否安装了 gcc-c++ 等组件。如没有请执行 apt-get build-dep gcc apt-get install build-essential。

  • 安装 php5, php5-dev。

首先需要使用 dpkg –s 安装包名,例如 dpkg –s php,确认是否安装了 php 等组件。如没有请执行 apt-get install php5 php5-dev (同时会自动安装php5-cli和php5-common)。

  • 安装配置 sasl 支持。

首先需要使用 dpkg –s 安装包名, 例如 dpkg –s libsasl2,确认是否安装了 libsasl2 cloog-ppl 等组件,如没有请执行以下命令。

 apt-get install libsasl2-dev cloog-ppl
 cd /usr/local/src
  • 执行以下命令安装指定版本的 libmemcache。

注意:请先检测下是否有已安装了这些包(包含源码包),如有则不需要安装。

 wget https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gz
 tar -zxvf libmemcached-1.0.18.tar.gz
 cd libmemcached-1.0.18
 ./configure --prefix=/usr/local/libmemcached
 make
 make install
 cd ..
  • 执行以下命令安装指定版本的 memcached。

注意:请先检测下是否有已安装了 memcached 客户端包(包含源码包),如有则不需要安装,但需要重新编译增加 -enable-memcached-sasl 这个扩展。

 wget 
 http://pecl.php.net/get/memcached-2.2.0.tgz tar zxvf memcached-2.2.0.tgz 
 cd memcached-2.2.0 phpize5 
 ./configure --with-libmemcached-dir=/usr/local/libmemcached --enable-memcached-sasl 
 make 
 make install
  • 配置 php 支持 memcached,然后测试。
 echo "extension=memcached.so" >>/etc/php5/conf.d/pdo.ini echo "memcached.use_sasl = 1" >>/etc/php5/conf.d/pdo.ini
 php -m |grep mem memcached

如果显示出该组件代表安装完成,配置完毕。

PHP 代码示例

示例1:基本的连接云数据库 Memcache 及 set/get 操作

<?php
$connect = new Memcached;  //声明一个新的memcached链接
$connect->setOption(Memcached::OPT_COMPRESSION, false); //关闭压缩功能
$connect->setOption(Memcached::OPT_BINARY_PROTOCOL, true); //使用binary二进制协议
$connect->setOption(Memcached::OPT_TCP_NODELAY, true); //重要,php memcached有个bug,当get的值不存在,有固定40ms延迟,开启这个参数,可以避免这个bug
$connect->addServer('aaaaaaaaaa.m.yyyyyyyyyyy.ocs.aliyuncs.com', 11211); //添加OCS实例地址及端口号
$connect->setSaslAuthData('aaaaaaaaaa', 'password'); //设置OCS帐号密码进行鉴权,如已开启免密码功能,则无需此步骤;新版OCS的username可以置空
$connect->set("hello", "world");
echo 'hello: ',$connect->get("hello");
$connect->quit();
?>

示例2:在云数据库 Memcache 中缓存一个数组

<?php
$connect= new Memcached; //声明一个新的memcached链接
$connect->setOption(Memcached::OPT_COMPRESSION, false); //关闭压缩功能
$connect->setOption(Memcached::OPT_BINARY_PROTOCOL, true);//使用binary二进制协议
$connect->setOption(Memcached::OPT_TCP_NODELAY, true); //重要,php memcached有个bug,当get的值不存在,有固定40ms延迟,开启这个参数,可以避免这个bug
$connect->addServer('xxxxxxxx.m.yyyyyyyy.ocs.aliyuncs.com', 11211);//添加OCS实例地址及端口号
$connect->setSaslAuthData('xxxxxxxx', 'bbbbbbbb');//设置OCS帐号密码进行鉴权,如已开启免密码功能,则无需此步骤
$user = array(
    "name" => "ocs",
    "age" => 1,
    "sex" => "male"
); //声明一组数组  
$expire = 60; //设置过期时间
test($connect->set('your_name',$user,$expire), true, 'Set cache failed');
if($connect->get('your_name')){
$result =$connect->get('your_name');
}else{  
echo "Return code:", $connect->getResultCode();
echo "Retucn Message:", $connect->getResultMessage (); //如出现错误,解析出返回码
$result=" ";
}  
print_r($result);
$connect->quit();
function test($val, $expect, $msg)
{  
    if($val!= $expect) throw new Exception($msg);
}  
?>

示例3:云数据库 Memcache 与 MySQL 数据库结合使用

<?php
$connect = new Memcached; //声明一个新的memcached链接
$connect->setOption(Memcached::OPT_COMPRESSION, false);//关闭压缩功能
$connect->setOption(Memcached::OPT_BINARY_PROTOCOL, true);//使用binary二进制协议
$connect->setOption(Memcached::OPT_TCP_NODELAY, true); //重要,php memcached有个bug,当get的值不存在,有固定40ms延迟,开启这个参数,可以避免这个bug
$connect->addServer('xxxxxx.m.yyyyyyyy.ocs.aliyuncs.com', 11211);//添加实例地址  端口号
$connect->setSaslAuthData('xxxxxx', 'my_passwd');//设置OCS帐号密码进行鉴权,如已开启免密码功能,则无需此步骤
$user = array(
   "name" => "ocs",
   "age"  => 1,
   "sex"  => "male"
); //定义一组数组
if($connect->get('your_name'))
{
  $result =$connect->get('your_name');
  print_r($result);
  echo "Found in OCS, get data from OCS"; //如果获取到数据,则打印此数据来源于OCS
  exit;  
}
else
{
  echo "Return code:", $connect->getResultCode();
  echo "Retucn Message:", $connect->getResultMessage ();//抛出code返回码
  $db_host='zzzzzz.mysql.rds.aliyuncs.com'; //数据库地址
  $db_name='my_db';         //database name
  $db_username='db_user';    //数据库用户名
  $db_password='db_passwd';//数据库用户密码
  $connection=mysql_connect($db_host,$db_username,$db_password);
  if (!mysql_select_db($db_name, $connection))
  {
    echo 'Could not select database'; //数据库连接不成功则抛出错误信息
    exit;
  }
  $sql = "SELECT name,age,sex FROM test1 WHERE name = 'ocs'";
  $result = mysql_query($sql, $connection);
  while ($row = mysql_fetch_assoc($result))
  {
    $user = array(
      "name" => $row["name"],
      "age"  => $row["age"],
      "sex"  => $row["sex"],
    );
    $expire = 5; //设置数据在缓存中的过期时间
    test($connect->set('your_name',$user,$expire), true, 'Set cache failed'); //写入OCS缓存
  }
  mysql_free_result($result);
  mysql_close($connection);
}
print_r($connect->get('your_name')); //打印出  获取到的数据
echo "Not Found in OCS,get data from MySQL"; //确认从数据库获取的数据
$connect->quit();
function test($val, $expect, $msg)
{
  if($val!= $expect) throw new Exception($msg);
}
?>