CentOS7 安装 Redis 集群

环境

  • 操作系统: CentOS7.9,关闭 firewalld 和 selinux

  • Redis: 5.0.14

  • master 实例

    • 10.0.4.110:6371
    • 10.0.4.110:6372
    • 10.0.4.110:6373
  • slave 实例

    • 10.0.4.111:6371
    • 10.0.4.111:6372
    • 10.0.4.111:6373

编译 redis server

  • 在 CentOS7.9 测试服务器上下载、编译

    1
    2
    3
    4
    
    curl -LO http://download.redis.io/releases/redis-5.0.14.tar.gz
    tar zxf redis-5.0.14.tar.gz
    cd redis-5.0.14
    make
    
  • 抽取安装文件

    1
    2
    3
    4
    5
    6
    
    mkdir -p /opt/redis/{bin,conf}
    cp src/{redis-server,redis-cli,redis-benchmark} /opt/redis/bin/
    cd /opt/redis/bin
    ln -s redis-server redis-check-aof
    ln -s redis-server redis-check-rdb
    ln -s redis-server redis-sentinel
    
  • 创建 /opt/redis/conf/redis-6379.conf,常用配置如下

PXE 网络装机

部署 dhcp 和 tft 服务

  • 安装 dnsmasq

    1
    2
    3
    4
    
    # rhel
    yum install dnsmasq
    # archlinux
    pacman -S dnsmasq
    
  • 修改配置 /etc/dnsmasq.conf

    1
    2
    3
    4
    5
    6
    
    port=0 # 用不着 dns 功能,可以关闭
    dhcp-range=10.0.86.2,10.0.86.9,255.255.255.0,1h
    #dhcp-boot=pxelinux.0 # bios 引导(未测试)
    dhcp-boot=grubx64.efi # efi 引导
    enable-tftp
    tftp-root=/var/ftp
    
  • 在其中一个网卡上配置 ip: 10.0.86.1/24

Postgresql 主从

主库配置

  • 修改 postgresql.conf
    1
    2
    3
    4
    5
    
    listen_address = '*'
    wal_level = replica
    wax_wal_senders = 10
    wal_keep_segments = 64
    hot_standby = on
    
  • 启动主库 postgresql-10 服务
    1
    
    systemctl start postgresql-10
    
  • 创建同步账户
    1
    2
    
    create user replica superuser password '123456';
    -- 这里可以只赋予 replication 权限,后面从库复制初始数据库时使用其他有权限帐号
    
  • 修改 pg_hba.conf
    1
    
    host replication replica samenet md5
    

从库配置

  • 停止从库 postgresql-10 服务,清空数据库目录
    1
    2
    
    systemctl stop postgresql-10
    rm -rf /var/lib/pgsql/10/data/*
    
  • 从主库复制初始数据库
    1
    2
    3
    4
    5
    6
    7
    8
    
    pg_basebackup \
        -h <主库ip> \
        -U replica \
        -F p \
        -X stream \
        -P -R \
        -D /var/lib/pgsql/10/data/ \
        -l backup_20191104
    
    • -h 指定连接的数据库的主机名或IP地址
    • -U 指定连接的用户名
    • -F 指定了输出的格式,支持p(原样输出)或者t(tar格式输出)
    • -X 表示备份开始后,启动另一个流复制连接从主库接收WAL日志
    • -P 表示允许在备份过程中实时的打印备份的进度
    • -R 表示会在备份结束后自动生成recovery.conf文件
    • -D 指定备份写入的数据目录,需要与数据库配置的数据库目录一致,初次备份之前从库的数据目录需要手动清空
    • -l 表示指定一个备份的标识

检查状态

  • 检查从库进程
    1
    2
    
    ps -ef|grep postgres
    # 可以看到 wal sender 和 receiver process 两个进程
    
  • 从库为只读模式,无法进行 增/删/改 操作
  • 主库查看 replication 客户端
    1
    
    select client_addr,sync_state from pg_stat_replication;
    

Python 的 ConfigParser 模块

样例文件

  • 该类配置文件可以包含一个或多个节(section),每个节可以有多个参数(键=值)。
  • 样例配置文件(/proj/conf/example_conf)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    [book]
    title:ConfigParser模块教程
    author:大头爸爸
    email:[email protected]
    time:2012-09-20 22:04:55
    [size]
    size:1024
    [other]
    blog:csdn.net
    
  • 上面配置文件中用的是冒号,也可以用等号。

读取配置文件

  • 示例文件: example.py
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    
    # -*- coding: utf-8 -*-
    import ConfigParser
    import string
    config=ConfigParser.ConfigParser()
    config.read(u'/proj/conf/example_conf')
    print string.upper(config.get("book","title")),
    print "by",config.get("book","author"),
    print "("+config.get("book","email")+")"
    print
    print config.get("size","size")
    print
    print config.sections()
    for section in config.sections():
        print section
        for option in config.options(section):
            print " ",option,"=",config.get(section,option)
    
  • example.py文件执行结果
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    CONFIGPARSER模块教程 by 大头爸爸 ([email protected])
    1024
      ['book', 'size', 'other']
    book
      title = ConfigParser模块教程
      author = 大头爸爸
      email = [email protected]
      time = 2012-09-20 22:04:55  size
      size = 1024  other
      blog = csdn.n
    

写入配置文件

  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    import ConfigParser
    import sys
    config=ConfigParser.ConfigParser()
    config.add_section("book")
    config.set("book","title","这是标题")
    config.set("book","author","大头爸爸")
    config.add_section("size")
    config.set("size","size",1024)
    config.write(sys.stdout)
    
  • 执行结果
    1
    2
    3
    4
    5
    
    [book]
    title = 这是标题
    author = 大头爸爸
    [size]
    size = 1024
    

ConfigParser方法

  • 创建ConfigParser实例
    1
    
    config=ConfigParser.ConfigParser()
    
  • 返回配置文件中节序列
    1
    
    config.sections()
    
  • 返回某个项目中的所有键的序列
    1
    2
    
    config=ConfigParser.ConfigParser()
    config.options(section)
    
  • 返回section节中,option的键值
    1
    2
    
    config=ConfigParser.ConfigParser()
    config.get(section,option)
    
  • 添加一个配置文件节点(str)
    1
    2
    
    config=ConfigParser.ConfigParser()
    config.add_section(str)
    
  • 设置section节点中,键名为option的值(val)
    1
    2
    
    config=ConfigParser.ConfigParser()
    config.set(section,option,val)
    
  • 读取配置文件
    1
    2
    
    config=ConfigParser.ConfigParser()
    config.read(filename)
    
  • 写入配置文件
    1
    2
    
    config=ConfigParser.ConfigParser()
    config.write(obj_file)
    

综合实例

 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
45
##coding=utf-8

import ConfigParser

def writeConfig(filename):
    config = ConfigParser.ConfigParser()
    # set db
    section_name = 'db'
    config.add_section( section_name )
    config.set( section_name, 'dbname', 'MySQL')
    config.set( section_name, 'host', '127.0.0.1')
    config.set( section_name, 'port', '80')
    config.set( section_name, 'password', '123456')
    config.set( section_name, 'databasename', 'test')

    # set app
    section_name = 'app'
    config.add_section( section_name )
    config.set( section_name, 'loggerapp', '192.168.20.2')
    config.set( section_name, 'reportapp', '192.168.20.3')

    # write to file
    config.write( open(filename, 'a') )

def updateConfig(filename, section, **keyv):
    config = ConfigParser.ConfigParser()
    config.read(filename)
    print config.sections()
    for section in config.sections():
        print "[",section,"]"
        items = config.items(section)
        for item in items:
            print "\t",item[0]," = ",item[1]
    print config.has_option("dbname", "MySQL")
    print config.set("db", "dbname", "11")
    print "..............."
    for key in keyv:
        print "\t",key," = ", keyv[key]
    config.write( open(filename, 'r+') )

if __name__ == '__main__':
    file_name = 'test.ini'
    writeConfig(file_name)
    updateConfig(file_name, 'app', reportapp = '192.168.100.100')
    print "end__"

Python 的 logging 模块

单输出日志到屏幕

  • 示例
    1
    2
    3
    4
    5
    6
    
    import logging
    logging.debug('debug message')
    logging.info('info message')
    logging.warning('warning message')
    logging.error('error message')
    logging.critical('critical message')
    
  • 输出
    1
    2
    3
    
    WARNING:root:warning message
    ERROR:root:error message
    CRITICAL:root:critical message
    
  • 默认情况下python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志。
  • 默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET)。
  • 默认的日志格式为日志级别:Logger名称:用户输出消息。

配置日志

  • 示例
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    import logging
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                        datefmt='%a, %d %b %Y %H:%M:%S',
                        filename='/tmp/test.log',
                        filemode='w')
    logging.debug('debug message')
    logging.info('info message')
    logging.warning('warning message')
    logging.error('error message')
    logging.critical('critical message')
    
  • 输出
    1
    2
    3
    4
    5
    6
    
    cat /tmp/test.log
     Mon, 05 May 2014 16:29:53 test_logging.py[line:9] DEBUG debug message
     Mon, 05 May 2014 16:29:53 test_logging.py[line:10] INFO info message
     Mon, 05 May 2014 16:29:53 test_logging.py[line:11] WARNING warning message
     Mon, 05 May 2014 16:29:53 test_logging.py[line:12] ERROR error message
     Mon, 05 May 2014 16:29:53 test_logging.py[line:13] CRITICAL critical message
    
  • logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,参数解释:
  • filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
  • filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
  • format:指定handler使用的日志显示格式。
  • datefmt:指定日期时间格式。
  • level:设置rootlogger(后边会讲解具体概念)的日志级别
  • stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
  • format参数中可能用到的格式化串:
    • %(name)s Logger的名字
    • %(levelno)s 数字形式的日志级别
    • %(levelname)s 文本形式的日志级别
    • %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
    • %(filename)s 调用日志输出函数的模块的文件名
    • %(module)s 调用日志输出函数的模块名
    • %(funcName)s 调用日志输出函数的函数名
    • %(lineno)d 调用日志输出函数的语句所在的代码行
    • %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
    • %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
    • %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
    • %(thread)d 线程ID。可能没有
    • %(threadName)s 线程名。可能没有
    • %(process)d 进程ID。可能没有
    • %(message)s用户输出的消息

安装 Oracle 需要调整的内核参数

安装Oracle的时候需要调整linux内核参数,但是各参数代表什么含义呢,下面做详细解析。

Linux安装文档中给出的最小值:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
fs.aio-max-nr = 1048576
fs.file-max = 6815744
kernel.shmall = 2097152
kernel.shmmax = 4294967295
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
net.ipv4.ip_local_port_range = 9000 65500
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048586

各参数详解:

CentOS6 安装 Oracle11g

安装依赖

1
2
3
4
5
yum install binutils compat-libstdc++-33 compat-libstdc++-33.i686 \
elfutils-libelf elfutils-libelf-devel gcc gcc-c++ glibc glibc.i686 \
glibc-common glibc-devel glibc-devel.i686 glibc-headers ksh libaio \
libaio.i686 libaio-devel libaio-devel.i686 libgcc libgcc.i686 libstdc++ \
libstdc++.i686 libstdc++-devel make sysstat unixODBC unixODBC-devel

创建用户和用户组

1
2
groupadd dba oinstall
useradd -g oinstall -m oracle

配置oracle用户环境变量

  • 打开 oracle 用户的的默认shell配置文件 ~/.bashrc,在最后添加以下代码

Python 的 cx_Oracle 模块

导入 cx_Oracle 模块

1
import cx_Oracle    # 导入模块

连接数据库

1
2
3
db = cx_Oracle.connect('user', 'password', 'host:port/SID') #建立连接,3个参数分开写
print db.version
##输出 10.2.0.1.0 测试成功

自动提交

1
2
db.autocommit=True #开启自动提交
db.autocommit=False #关闭自动提交

建立 cursor 光标

1
cursor = db.cursor()    #建立一个cursor

执行sql

1
2
3
4
cursor.execute(‘select * from tabs’)    # 执行一条sql
sql = "insert into person(name, age, telephone) values(%s, %s, %s)"
tmp = (('ninini', 89, '888999'), ('koko', 900, '999999'))
conn.executemany(sql, tmp) #执行多条sql

获取执行结果

1
2
3
4
5
6
row=cursor.fetchone() #取一行结果,元组(a,b,c,d)
row=cursor.fetchall() #获取所有结果,列表[(a,b,c,d),(e,f,g,h),...]
for x in row:
    For y in x:
        Print y
print cursor.rowcount() #获取输出记录数量

提交

1
db.commit()

回滚

1
db.rollback()

关闭连接

1
2
cursor.close()
db.close()

CentOS 安装官方编译的 Mariadb 10.1 二进制通用包

环境

  • centos 5.4/6.2/6.5/7.2 x86_64

安装

  1. 下载官方编译好的 linux 通用安装包,解压之自定义目录(如/opt)下

    1
    2
    3
    4
    5
    6
    7
    
    # rhel 7 地址:
    wget https://mirrors.tuna.tsinghua.edu.cn/mariadb//mariadb-10.1.19/bintar-linux-glibc_214-x86_64/mariadb-10.1.19-linux-glibc_214-x86_64.tar.gz
    # rhel 5/6 地址:
    wget https://mirrors.tuna.tsinghua.edu.cn/mariadb//mariadb-10.1.19/bintar-linux-x86_64/mariadb-10.1.19-linux-x86_64.tar.gz
    tar zxf mariadb-10.1.19-linux*-x86_64.tar.gz -C /opt/
    cd /opt
    mv mariadb-10.1.19-linux* mariadb
    
  2. 创建服务文件和配置文件,创建日志目录

Python 的 re 模块

match

  • 定义
    1
    
    re.match(pattern, string, flags)
    
  • 尝试从字符串的开始匹配一个模式
  • 第一个参数是正则表达式,如果匹配成功,则返回一个Match,否则返回一个None;
  • 第二个参数表示要匹配的字符串;
  • 第三个参数是标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
  • 定义
    1
    
    re.search(pattern, string, flags)
    
  • 在字符串内查找模式匹配,只到找到第一个匹配然后返回,如果字符串没有匹配,则返回None。
  • 每个参数的含意与re.match一样。

sub

  • 定义
    1
    
    re.sub(pattern, repl, string, count)
    
  • 替换字符串中的匹配项
  • 其中第二个函数是替换后的字符串
  • 第四个参数指替换个数。默认为0,表示每个匹配项都替换。 re.sub还允许使用函数对匹配项的替换进行复杂的处理,如:re.sub(r’\s’, lambda m: ‘[’ + m.group(0) + ‘]’, text, 0);将字符串中的空格’ ‘替换为’[ ]’。

split

  • 定义
    1
    
    re.split(pattern, string)
    
  • 分割字符串

findall

  • 定义
    1
    
    re.findall(pattern, text)
    
  • 获取字符串中所有匹配的字符串

compile

  • 定义
    1
    
    re.compile(pattern)
    
  • 把正则表达式编译成一个正则表达式对象
  • 示例
    1
    2
    3
    4
    5
    
    import re
    text = "JGood is a handsome boy, he is cool, clever, and so on..."
    regex = re.compile(r'\w*oo\w*')
    print regex.findall(text)  #查找所有包含'oo'的单词
    print regex.sub(lambda m: '[' + m.group(0) + ']', text) #将字符串中含有'oo'的单词用[]括起来