redis哨兵集群、docker入门

redis-sentinel主从复制高可用

Redis-Sentinel

Redis-Sentinel是redis官方推荐的高可用性解决方案,
当用redis做master-slave的高可用时,若是master自己宕机,redis自己或者客户端都没有实现主从切换的功能。html

而redis-sentinel就是一个独立运行的进程,用于监控多个master-slave集群,node

自动发现master宕机,进行自动切换slave > master。python

sentinel主要功能

不时的监控redis是否良好运行,若是节点不可达就会对节点进行下线标识mysql

若是被标识的是主节点,sentinel就会和其余的sentinel节点“协商”,若是其余节点也人为主节点不可达,就会选举一个sentinel节点来完成自动故障转义linux

在master-slave进行切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换nginx

Sentinel的工做方式

每一个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其余 Sentinel 实例发送一个 PING 命令
 

若是一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。

若是一个Master被标记为主观下线,则正在监视这个Master的全部 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。

当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线

在通常状况下, 每一个 Sentinel 会以每 10 秒一次的频率向它已知的全部Master,Slave发送 INFO 命令

当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的全部 Slave 发送 INFO 命令的频率会从 10 秒一次改成每秒一次

若没有足够数量的 Sentinel 赞成 Master 已经下线, Master 的客观下线状态就会被移除。

若 Master 从新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。

主观下线和客观下线

主观下线:Subjectively Down,简称 SDOWN,指的是当前 Sentinel 实例对某个redis服务器作出的下线判断。
客观下线:Objectively Down, 简称 ODOWN,指的是多个 Sentinel 实例在对Master Server作出 SDOWN 判断,而且经过 SENTINEL is-master-down-by-addr 命令互相交流以后,得出的Master Server下线判断,而后开启failover.

SDOWN适合于Master和Slave,只要一个 Sentinel 发现Master进入了ODOWN, 这个 Sentinel 就可能会被其余 Sentinel 推选出, 并对下线的主服务器执行自动故障迁移操做。

ODOWN只适用于Master,对于Slave的 Redis 实例,Sentinel 在将它们判断为下线前不须要进行协商, 因此Slave的 Sentinel 永远不会达到ODOWN。

sentinel公做方式
View Code

redis主从复制背景问题

Redis主从复制可将主节点数据同步给从节点,从节点此时有两个做用:git

  • 一旦主节点宕机,从节点做为主节点的备份能够随时顶上来。
  • 扩展主节点的读能力,分担主节点读压力。

可是问题是:程序员

  • 一旦主节点宕机,从节点上位,那么须要人为修改全部应用方的主节点地址(改成新的master地址),还须要命令全部从节点复制新的主节点

那么这个问题,redis-sentinel就能够解决了github

主从复制架构

Redis Sentinel架构

redis的一个进程,可是不存储数据,只是监控redisweb

 

 

redis命令整理

官网地址:http://redisdoc.com/

redis-cli info #查看redis数据库信息

redis-cli info replication #查看redis的复制受权信息


redis-cli info sentinel   #查看redis的哨兵信息

安装与配置

服务器环境,一台便可完成操做

准备三个redis实例,一主两从
redis-6379.conf 
    [root@qishione sb]# cat redis-6379.conf 
    port 6379
    daemonize yes
    logfile "6379.log"
    dbfilename "dump-6379.rdb"
    dir "/var/redis/data/"


redis-6380.conf 
    [root@qishione sb]# cat redis-6380.conf 
    port 6380
    daemonize yes
    logfile "6380.log"
    dbfilename "dump-6380.rdb"
    dir "/var/redis/data/"
    slaveof 127.0.0.1 6379



redis-6381.conf 
    [root@qishione sb]# cat redis-6381.conf 
    port 6381
    daemonize yes
    logfile "6381.log"
    dbfilename "dump-6381.rdb"
    dir "/var/redis/data/"
    slaveof 127.0.0.1 6379

准备好了三个数据库实例,启动三个数据库实例
redis-server  redis-6379.conf
redis-server  redis-6380.conf
redis-server  redis-6381.conf
# Redis 配置文件

# 当配置中须要配置内存大小时,可使用 1k, 5GB, 4M 等相似的格式,其转换方式以下(不区分大小写)
#
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
#
# 内存配置大小写是同样的.好比 1gb 1Gb 1GB 1gB

# daemonize no 默认状况下,redis不是在后台运行的,若是须要在后台运行,把该项的值更改成yes
daemonize yes

# 当redis在后台运行的时候,Redis默认会把pid文件放在/var/run/redis.pid,你能够配置到其余地址。
# 当运行多个redis服务时,须要指定不一样的pid文件和端口
pidfile /var/run/redis.pid

# 指定redis运行的端口,默认是6379
port 6379

# 指定redis只接收来自于该IP地址的请求,若是不进行设置,那么将处理全部请求,
# 在生产环境中最好设置该项
# bind 127.0.0.1

# Specify the path for the unix socket that will be used to listen for
# incoming connections. There is no default, so Redis will not listen
# on a unix socket when not specified.
#
# unixsocket /tmp/redis.sock
# unixsocketperm 755

# 设置客户端链接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么关闭该链接
# 0是关闭此设置
timeout 0

# 指定日志记录级别
# Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
# debug    记录不少信息,用于开发和测试
# varbose    有用的信息,不像debug会记录那么多
# notice    普通的verbose,经常使用于生产环境
# warning    只有很是重要或者严重的信息会记录到日志
loglevel debug

# 配置log文件地址
# 默认值为stdout,标准输出,若后台模式会输出到/dev/null
#logfile stdout
logfile /var/log/redis/redis.log

# To enable logging to the system logger, just set 'syslog-enabled' to yes,
# and optionally update the other syslog parameters to suit your needs.
# syslog-enabled no

# Specify the syslog identity.
# syslog-ident redis

# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.
# syslog-facility local0

# 可用数据库数
# 默认值为16,默认数据库为0,数据库范围在0-(database-1)之间
databases 16

################################ 快照 #################################
#
# 保存数据到磁盘,格式以下:
#
# save <seconds> <changes>
#
# 指出在多长时间内,有多少次更新操做,就将数据同步到数据文件rdb。
# 至关于条件触发抓取快照,这个能够多个条件配合
# 
# 好比默认配置文件中的设置,就设置了三个条件
#
# save 900 1 900秒内至少有1个key被改变
# save 300 10 300秒内至少有300个key被改变
# save 60 10000 60秒内至少有10000个key被改变

save 900 1
save 300 10
save 60 10000

# 存储至本地数据库时(持久化到rdb文件)是否压缩数据,默认为yes
rdbcompression yes

# 本地持久化数据库文件名,默认值为dump.rdb
dbfilename dump.rdb

# 工做目录
#
# 数据库镜像备份的文件放置的路径。
# 这里的路径跟文件名要分开配置是由于redis在进行备份时,先会将当前数据库的状态写入到一个临时文件中,等备份完成时,
# 再把该该临时文件替换为上面所指定的文件,而这里的临时文件和上面所配置的备份文件都会放在这个指定的路径当中。
# 
# AOF文件也会存放在这个目录下面
# 
# 注意这里必须制定一个目录而不是文件
dir ./

################################# 复制 #################################

# 主从复制. 设置该数据库为其余数据库的从数据库. 
# 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
#
# slaveof <masterip> <masterport>

# 当master服务设置了密码保护时(用requirepass制定的密码)
# slav服务链接master的密码
# 
# masterauth <master-password>


# 当从库同主机失去链接或者复制正在进行,从机库有两种运行方式:
#
# 1) 若是slave-serve-stale-data设置为yes(默认设置),从库会继续相应客户端的请求
# 
# 2) 若是slave-serve-stale-data是指为no,出去INFO和SLAVOF命令以外的任何请求都会返回一个
# 错误"SYNC with master in progress"
#
slave-serve-stale-data yes

# 从库会按照一个时间间隔向主库发送PINGs.能够经过repl-ping-slave-period设置这个时间间隔,默认是10秒
#
# repl-ping-slave-period 10

# repl-timeout 设置主库批量数据传输时间或者ping回复时间间隔,默认值是60秒
# 必定要确保repl-timeout大于repl-ping-slave-period
# repl-timeout 60

################################## 安全 ###################################

# 设置客户端链接后进行任何其余指定前须要使用的密码。
# 警告:由于redis速度至关快,因此在一台比较好的服务器下,一个外部的用户能够在一秒钟进行150K次的密码尝试,这意味着你须要指定很是很是强大的密码来防止暴力破解
#
# requirepass foobared

# 命令重命名.
#
# 在一个共享环境下能够重命名相对危险的命令。好比把CONFIG重名为一个不容易猜想的字符。
#
# 举例:
#
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
#
# 若是想删除一个命令,直接把它重命名为一个空字符""便可,以下:
#
# rename-command CONFIG ""

################################### 约束 ####################################

# 设置同一时间最大客户端链接数,默认无限制,Redis能够同时打开的客户端链接数为Redis进程能够打开的最大文件描述符数,
# 若是设置 maxclients 0,表示不做限制。
# 当客户端链接数到达限制时,Redis会关闭新的链接并向客户端返回max number of clients reached错误信息
#
# maxclients 128

# 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key
# Redis同时也会移除空的list对象
#
# 当此方法处理后,仍然到达最大内存设置,将没法再进行写入操做,但仍然能够进行读取操做
# 
# 注意:Redis新的vm机制,会把Key存放内存,Value会存放在swap区
#
# maxmemory的设置比较适合于把redis看成于相似memcached的缓存来使用,而不适合当作一个真实的DB。
# 当把Redis当作一个真实的数据库使用的时候,内存使用将是一个很大的开销
# maxmemory <bytes>

# 当内存达到最大值的时候Redis会选择删除哪些数据?有五种方式可供选择
# 
# volatile-lru -> 利用LRU算法移除设置过过时时间的key (LRU:最近使用 Least Recently Used )
# allkeys-lru -> 利用LRU算法移除任何key
# volatile-random -> 移除设置过过时时间的随机key
# allkeys->random -> remove a random key, any key 
# volatile-ttl -> 移除即将过时的key(minor TTL)
# noeviction -> 不移除任何能够,只是返回一个写错误
# 
# 注意:对于上面的策略,若是没有合适的key能够移除,当写的时候Redis会返回一个错误
#
# 写命令包括: set setnx setex append
# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
# getset mset msetnx exec sort
#
# 默认是:
#
# maxmemory-policy volatile-lru

# LRU 和 minimal TTL 算法都不是精准的算法,可是相对精确的算法(为了节省内存),随意你能够选择样本大小进行检测。
# Redis默认的灰选择3个样本进行检测,你能够经过maxmemory-samples进行设置
#
# maxmemory-samples 3

############################## AOF ###############################


# 默认状况下,redis会在后台异步的把数据库镜像备份到磁盘,可是该备份是很是耗时的,并且备份也不能很频繁,若是发生诸如拉闸限电、拔插头等情况,那么将形成比较大范围的数据丢失。
# 因此redis提供了另一种更加高效的数据库备份及灾难恢复方式。
# 开启append only模式以后,redis会把所接收到的每一次写操做请求都追加到appendonly.aof文件中,当redis从新启动时,会从该文件恢复出以前的状态。
# 可是这样会形成appendonly.aof文件过大,因此redis还支持了BGREWRITEAOF指令,对appendonly.aof 进行从新整理。
# 你能够同时开启asynchronous dumps 和 AOF

appendonly no

# AOF文件名称 (默认: "appendonly.aof")
# appendfilename appendonly.aof

# Redis支持三种同步AOF文件的策略:
#
# no: 不进行同步,系统去操做 . Faster.
# always: always表示每次有写操做都进行同步. Slow, Safest.
# everysec: 表示对写操做进行累积,每秒同步一次. Compromise.
#
# 默认是"everysec",按照速度和安全折中这是最好的。
# 若是想让Redis能更高效的运行,你也能够设置为"no",让操做系统决定何时去执行
# 或者相反想让数据更安全你也能够设置为"always"
#
# 若是不肯定就用 "everysec".

# appendfsync always
appendfsync everysec
# appendfsync no

# AOF策略设置为always或者everysec时,后台处理进程(后台保存或者AOF日志重写)会执行大量的I/O操做
# 在某些Linux配置中会阻止过长的fsync()请求。注意如今没有任何修复,即便fsync在另一个线程进行处理
#
# 为了减缓这个问题,能够设置下面这个参数no-appendfsync-on-rewrite
#
# This means that while another child is saving the durability of Redis is
# the same as "appendfsync none", that in pratical terms means that it is
# possible to lost up to 30 seconds of log in the worst scenario (with the
# default Linux settings).
# 
# If you have latency problems turn this to "yes". Otherwise leave it as
# "no" that is the safest pick from the point of view of durability.
no-appendfsync-on-rewrite no

# Automatic rewrite of the append only file.
# AOF 自动重写
# 当AOF文件增加到必定大小的时候Redis可以调用 BGREWRITEAOF 对日志文件进行重写 
# 
# 它是这样工做的:Redis会记住上次进行些日志后文件的大小(若是从开机以来还没进行太重写,那日子大小在开机的时候肯定)
#
# 基础大小会同如今的大小进行比较。若是如今的大小比基础大小大制定的百分比,重写功能将启动
# 同时须要指定一个最小大小用于AOF重写,这个用于阻止即便文件很小可是增加幅度很大也去重写AOF文件的状况
# 设置 percentage 为0就关闭这个特性

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

################################## SLOW LOG ###################################

# Redis Slow Log 记录超过特定执行时间的命令。执行时间不包括I/O计算好比链接客户端,返回结果等,只是命令执行时间
# 
# 能够经过两个参数设置slow log:一个是告诉Redis执行超过多少时间被记录的参数slowlog-log-slower-than(微妙),
# 另外一个是slow log 的长度。当一个新命令被记录的时候最先的命令将被从队列中移除

# 下面的时间以微妙微单位,所以1000000表明一分钟。
# 注意制定一个负数将关闭慢日志,而设置为0将强制每一个命令都会记录
slowlog-log-slower-than 10000

# 对日志长度没有限制,只是要注意它会消耗内存
# 能够经过 SLOWLOG RESET 回收被慢日志消耗的内存
slowlog-max-len 1024

################################ VM ###############################

### WARNING! Virtual Memory is deprecated in Redis 2.4
### The use of Virtual Memory is strongly discouraged.

# Virtual Memory allows Redis to work with datasets bigger than the actual
# amount of RAM needed to hold the whole dataset in memory.
# In order to do so very used keys are taken in memory while the other keys
# are swapped into a swap file, similarly to what operating systems do
# with memory pages.
#
# To enable VM just set 'vm-enabled' to yes, and set the following three
# VM parameters accordingly to your needs.

vm-enabled no
# vm-enabled yes

# This is the path of the Redis swap file. As you can guess, swap files
# can't be shared by different Redis instances, so make sure to use a swap
# file for every redis process you are running. Redis will complain if the
# swap file is already in use.
#
# The best kind of storage for the Redis swap file (that's accessed at random) 
# is a Solid State Disk (SSD).
#
# *** WARNING *** if you are using a shared hosting the default of putting
# the swap file under /tmp is not secure. Create a dir with access granted
# only to Redis user and configure Redis to create the swap file there.
vm-swap-file /tmp/redis.swap

# vm-max-memory configures the VM to use at max the specified amount of
# RAM. Everything that deos not fit will be swapped on disk *if* possible, that
# is, if there is still enough contiguous space in the swap file.
#
# With vm-max-memory 0 the system will swap everything it can. Not a good
# default, just specify the max amount of RAM you can in bytes, but it's
# better to leave some margin. For instance specify an amount of RAM
# that's more or less between 60 and 80% of your free RAM.
vm-max-memory 0

# Redis swap files is split into pages. An object can be saved using multiple
# contiguous pages, but pages can't be shared between different objects.
# So if your page is too big, small objects swapped out on disk will waste
# a lot of space. If you page is too small, there is less space in the swap
# file (assuming you configured the same number of total swap file pages).
#
# If you use a lot of small objects, use a page size of 64 or 32 bytes.
# If you use a lot of big objects, use a bigger page size.
# If unsure, use the default :)
vm-page-size 32

# Number of total memory pages in the swap file.
# Given that the page table (a bitmap of free/used pages) is taken in memory,
# every 8 pages on disk will consume 1 byte of RAM.
#
# The total swap size is vm-page-size * vm-pages
#
# With the default of 32-bytes memory pages and 134217728 pages Redis will
# use a 4 GB swap file, that will use 16 MB of RAM for the page table.
#
# It's better to use the smallest acceptable value for your application,
# but the default is large in order to work in most conditions.
vm-pages 134217728

# Max number of VM I/O threads running at the same time.
# This threads are used to read/write data from/to swap file, since they
# also encode and decode objects from disk to memory or the reverse, a bigger
# number of threads can help with big objects even if they can't help with
# I/O itself as the physical device may not be able to couple with many
# reads/writes operations at the same time.
#
# The special value of 0 turn off threaded I/O and enables the blocking
# Virtual Memory implementation.
vm-max-threads 4

############################### ADVANCED CONFIG ###############################

# 当hash中包含超过指定元素个数而且最大的元素没有超过临界时,
# hash将以一种特殊的编码方式(大大减小内存使用)来存储,这里能够设置这两个临界值
# Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不一样实现,
# 这个Hash的成员比较少时Redis为了节省内存会采用相似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,
# 当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。
hash-max-zipmap-entries 512
hash-max-zipmap-value 64

# list数据类型多少节点如下会采用去指针的紧凑存储格式。
# list数据类型节点值大小小于多少字节会采用紧凑存储格式。
list-max-ziplist-entries 512
list-max-ziplist-value 64

# set数据类型内部数据若是所有是数值型,且包含多少节点如下会采用紧凑格式存储。
set-max-intset-entries 512

# zsort数据类型多少节点如下会采用去指针的紧凑存储格式。
# zsort数据类型节点值大小小于多少字节会采用紧凑存储格式。
zset-max-ziplist-entries 128
zset-max-ziplist-value 64

# Redis将在每100毫秒时使用1毫秒的CPU时间来对redis的hash表进行从新hash,能够下降内存的使用
# 
# 当你的使用场景中,有很是严格的实时性须要,不可以接受Redis时不时的对请求有2毫秒的延迟的话,把这项配置为no。
#
# 若是没有这么严格的实时性要求,能够设置为yes,以便可以尽量快的释放内存
activerehashing yes

################################## INCLUDES ###################################

# 指定包含其它的配置文件,能够在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有本身的特定配置文件

# include /path/to/local.conf
# include /path/to/other.conf

redis.conf详解--补充--
redis.conf详解--补充--

此时能够在master上写入数据,在slave上查看数据,此时主从复制配置完成

开始配置Redis Sentinel

准备三个配置文件,哨兵文件

// Sentinel节点的端口
redis-26379.conf
port 26379  
dir /var/redis/data/
logfile "26379.log"
// 当前Sentinel节点监控 192.168.119.10:6379 这个主节点
// 2表明判断主节点失败至少须要2个Sentinel节点节点赞成
// qsmaster是主节点的别名
sentinel monitor qsmaster  127.0.0.1 6379 2
sentinel down-after-milliseconds qsmaster 30000
sentinel parallel-syncs qsmaster 1
sentinel failover-timeout qsmaster 180000
daemonize yes 

redis-26380.conf
port 26380  
dir /var/redis/data/
logfile "26380.log"
sentinel monitor qsmaster  127.0.0.1 6379 2
//每一个Sentinel节点都要按期PING命令来判断Redis数据节点和其他Sentinel节点是否可达,若是超过30000毫秒30s且没有回复,则断定不可达
sentinel down-after-milliseconds qsmaster 30000
//当Sentinel节点集合对主节点故障断定达成一致时,Sentinel领导者节点会作故障转移操做,选出新的主节点,
原来的从节点会向新的主节点发起复制操做,限制每次向新的主节点发起复制操做的从节点个数为1
sentinel parallel-syncs qsmaster 1
//故障转移超时时间为180000毫秒
sentinel failover-timeout qsmaster 180000
daemonize yes 



redis-26381.conf
port 26381  
dir /var/redis/data/
logfile "26381.log"
sentinel monitor qsmaster  127.0.0.1 6379 2
sentinel down-after-milliseconds qsmaster 30000
sentinel parallel-syncs qsmaster 1
sentinel failover-timeout qsmaster 180000
daemonize yes 

redis-sentinel-26380.conf和redis-sentinel-26381.conf的配置仅仅差别是port(端口)的不一样。

启动三个哨兵实例

redis-sentinel redis-26379.conf 
 redis-sentinel redis-26380.conf 
 redis-sentinel redis-26381.conf 

注意!!若是发现实验不成功,需删掉全部的哨兵配置文件,重新来过
注意!!若是发现实验不成功,需删掉全部的哨兵配置文件,重新来过
注意!!若是发现实验不成功,需删掉全部的哨兵配置文件,重新来过

检查哨兵状态是否正常

 redis-cli -p 26379 info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=qsmaster,status=ok,address=127.0.0.1:6380,slaves=2,sentinels=3
看到最后一条信息正确即成功了哨兵,哨兵主节点名字叫作qsmaster,状态ok,监控地址是127.0.0.1:6380,有两个从节点,3个哨兵

redis高可用故障实验

1.干掉6379的redis数据库
2.查看6380和6381的身份信息,是否自动的进行主从切换
3.手动启动6379挂掉的数据库,查看是否会被哨兵,添加进信息的主从集群(redis-cli -p 6379 info replication)

 

为何要用redis-cluster

并发问题

redis官方生成能够达到 10万/每秒,每秒执行10万条命令
假如业务须要每秒100万的命令执行呢?

数据量太大

一台服务器内存正常是16~256G,假如你的业务须要500G内存,你怎么办?解决方案以下

  1. 配置一个超级牛逼的计算机,超大内存,超强cpu,可是问题是。。。。

2.正确的应该是考虑分布式,加机器,把数据分到不一样的位置,分摊集中式的压力,一堆机器作一件事

客户端分片

redis实例集群主要思想是将redis数据的key进行散列,经过hash函数特定的key会映射到指定的redis节点上

数据分布理论

分布式数据库首要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每一个节点负责整个数据的一个子集。

常见的分区规则有哈希分区和顺序分区。Redis Cluster采用哈希分区规则,所以接下来会讨论哈希分区规则。

  • 节点取余分区
  • 一致性哈希分区
  • 虚拟槽分区(redis-cluster采用的方式)

顺序分区

哈希分区

节点取余

例如按照节点取余的方式,分三个节点

1~100的数据对3取余,能够分为三类

  • 余数为0
  • 余数为1
  • 余数为2

 

那么一样的分4个节点就是hash(key)%4

节点取余的优势是简单,客户端分片直接是哈希+取余

一致性哈希

客户端进行分片,哈希+顺时针取余

虚拟槽分区 

Redis Cluster采用虚拟槽分区

虚拟槽分区巧妙地使用了哈希空间,使用分散度良好的哈希函数把全部的数据映射到一个固定范围内的整数集合,整数定义为槽(slot)。

Redis Cluster槽的范围是0 ~ 16383。

槽是集群内数据管理和迁移的基本单位。采用大范围的槽的主要目的是为了方便数据的拆分和集群的扩展,

每一个节点负责必定数量的槽。

搭建redis cluster

搭建集群分为几部

  •  准备节点(几匹马儿)
  • 节点通讯(几匹马儿分配主从)
  • 分配槽位给节点(slot分配给马儿)

redis-cluster集群架构

多个服务端,负责读写,彼此通讯,redis指定了16384个槽。

多匹马儿,负责运输数据,马儿分配16384个槽位,管理数据。

ruby的脚本自动就把分配槽位这事作了

安装方式

官方提供经过ruby语言的脚本一键安装

环境准备

经过配置,开启redis-cluster

port 7000
daemonize yes
dir "/opt/redis/data"
logfile "7000.log"
dbfilename "dump-7000.rdb"
cluster-enabled yes   #开启集群模式
cluster-config-file nodes-7000.conf  #集群内部的配置文件
cluster-require-full-coverage no  #redis cluster须要16384个slot都正常的时候才能对外提供服务,换句话说,只要任何一个slot异常那么整个cluster不对外提供服务。 所以生产环境通常为no

redis支持多实例的功能,咱们在单机演示集群搭建,须要6个实例,三个是主节点,三个是从节点,数量为6个节点才能保证高可用的集群。

每一个节点仅仅是端口运行的不一样!

[root@yugo /opt/redis/config 17:12:30]#ls
redis-7000.conf  redis-7002.conf  redis-7004.conf
redis-7001.conf  redis-7003.conf  redis-7005.conf

#确保每一个配置文件中的端口修改!!

运行redis实例

  redis-server redis-7000.conf 
 redis-server redis-7001.conf 
  redis-server redis-7002.conf 
  redis-server redis-7003.conf 
 redis-server redis-7004.conf 
  redis-server redis-7005.conf 

下载安装Ruby

准备ruby的编程环境
    1.下载ruby的源码包
    wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz
    2.解压缩ruby远吗
    tar -xvf ruby-2.3.1.tar.gz
    3.开始编译安装ruby
    进入ruby源码包
    ./configure --prefix=/opt/ruby/
    4.开始编译且编译安装
    make && make install
    5.配置ruby的环境变量
    vim /etc/profile 
    追加写入以下配置
    PATH=$PATH:/opt/ruby/bin 
    source /etc/profile

安装ruby操做redis的模块

1.下载ruby操做redis的模块雷士python的pip
    wget http://rubygems.org/downloads/redis-3.3.0.gem
    2.安装
    gem install -l redis-3.3.0.gem
    3.搜索建立redis集群的命令
    find /opt  -name  redis-trib.rb

一键建立redis集群

执行下面一行命令:
/opt/redis-4.0.10/src/redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --replicas 进行身份受权 后面的1 表明,每一个主节点,只有一个从节点 默认将 7000 7001 70002 设置为主库 将7003 7004 7005 设置为从库

查看集群节点,是否能正常写入数据

redis-cli -p 7000  -c  
    -p  指定数据库端口
    -c  指定开启集群模式
127.0.0.1:7000> set name chao     
-> Redirected to slot [5798] located at 127.0.0.1:7001       
OK
127.0.0.1:7001> exit
[root@yugo /opt/redis/src 18:46:07]#redis-cli -c -p 7000
127.0.0.1:7000> ping
PONG
127.0.0.1:7000> keys *
(empty list or set)
127.0.0.1:7000> get name
-> Redirected to slot [5798] located at 127.0.0.1:7001
"chao"

docker入门

docker简介

Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,于 20133 月以 Apache 2.0 受权协议开源,主要项目代码在 GitHub 上进行维护。
Docker 使用 Google 公司推出的 Go 语言 进行开发实现。
docker是linux容器的一种封装,提供简单易用的容器使用接口。它是最流行的Linux容器解决方案。
docker的接口至关简单,用户能够方便的建立、销毁容器。
docker将应用程序与程序的依赖,打包在一个文件里面。运行这个文件就会生成一个虚拟容器。
程序运行在虚拟容器里,如同在真实物理机上运行同样,有了docker,就不用担忧环境问题了。

docker应用场景

web应用的自动化打包和发布
自动化测试和持续集成、发布
在服务型环境中部署和调整数据库或其余应用

docker  VS 传统虚拟机

特性

容器

虚拟机

启动

秒级

分钟级

硬盘使用

通常为 MB

通常为 GB

性能

接近原生

系统支持量

单机支持上千个容器

通常几十个

环境配置的难题

让开发人员最头疼的麻烦事之一就是环境配置了,每台计算机的环境都不相同,应该如何确保本身的程序换一台机器能运行起来呢?

用户必须确保的是:

操做系统的相同
各类平台库和组件的安装
例如python依赖包,环境变量等
如何一些低版本的依赖模块和当前环境不兼容,那就头疼了。。。。。

若是环境配置这么痛苦的话,换一台机器,就得从新配置一下,那么在安装软件的时候,带着原始环境如出一辙的复制过来。

虚拟机

虚拟机也能够制做模板,基于模板建立虚拟机,保证环境问题一致

虚拟机(virtual machine)就是带环境安装的一种解决方案。它能够在一种操做系统里面运行另外一种操做系统,好比在 Windows 系统里面运行 Linux 系统。应用程序对此毫无感知,由于虚拟机看上去跟真实系统如出一辙,而对于底层系统来讲,虚拟机就是一个普通文件,不须要了就删掉,对其余部分毫无影响。

虽然用户能够经过虚拟机还原软件的原始环境。可是,这个方案有几个缺点。

(1)资源占用多

虚拟机会独占一部份内存和硬盘空间。它运行的时候,其余程序就不能使用这些资源了。哪怕虚拟机里面的应用程序,真正使用的内存只有 1MB,虚拟机依然须要几百 MB 的内存才能运行。

(2)冗余步骤多

虚拟机是完整的操做系统,一些系统级别的操做步骤,每每没法跳过,好比用户登陆。

(3)启动慢

启动操做系统须要多久,启动虚拟机就须要多久。可能要等几分钟,应用程序才能真正运行。

Linux容器

如今:自从用上docker容器后,能够实现开发、测试和生产环境的统一化和标准化。

镜像做为标准的交付件,可在开发、测试和生产环境上以容器来运行,最终实现三套环境上的应用以及运行所依赖内容的彻底一致。

 因为虚拟机的诸多问题,Linux发展出了另外一种虚拟化技术:Linux容器(Linux Containers,缩写LXC)

Linux容器不是模拟一个完整的操做系统,而是对进程进行隔离。在正常进程的外面套了一个保护层,对于容器里面进程来讲,它接触的资源都是虚拟的,从而实现和底层系统的隔离。

(1)启动快

容器里面的应用,直接就是底层系统的一个进程,而不是虚拟机内部的进程。因此,启动容器至关于启动本机的一个进程,而不是启动一个操做系统,速度就快不少。

(2)资源占用少

容器只占用须要的资源,不占用那些没有用到的资源;虚拟机因为是完整的操做系统,不可避免要占用全部资源。另外,多个容器能够共享资源,虚拟机都是独享资源。

(3)体积小

容器只要包含用到的组件便可,而虚拟机是整个操做系统的打包,因此容器文件比虚拟机文件要小不少。

总之,容器有点像轻量级的虚拟机,可以提供虚拟化的环境,可是成本开销小得多。

docker容器的优点

 

更高效的利用系统资源
因为容器不须要进行硬件虚拟以及运行完整操做系统等额外开销,Docker 对系统 资源的利用率更高。
不管是应用执行速度、内存损耗或者文件存储速度,都要比传 统虚拟机技术更高效。所以,相比虚拟机技术,一个相同配置的主机,每每能够运 行更多数量的应用。
更快速的启动时间 传统的虚拟机技术启动应用服务每每须要数分钟,而 Docker 容器应用,因为直接 运行于宿主内核,无需启动完整的操做系统,所以能够作到秒级、甚至毫秒级的启 动时间。大大的节约了开发、测试、部署的时间。 一致的运行环境 开发过程当中一个常见的问题是环境一致性问题。因为开发环境、测试环境、生产环 境不一致,致使有些 bug 并未在开发过程当中被发现。 而 Docker 的镜像提供了除内 核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 “这段代码 在我机器上没问题啊” 这类问题。
持续交付和部署 对开发和运维(DevOps)人员来讲,最但愿的就是一次建立或配置,能够在任意 地方正常运行。 使用 Docker 能够经过定制应用镜像来实现持续集成、持续交付、部署。开发人员 能够经过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) 系 统进行集成测试, 而运维人员则能够直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery
/Deployment) 系统进行自动部署。 并且使用 Dockerfile 使镜像构建透明化,不只仅开发团队能够理解应用运行环 境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。
更轻松的迁移 因为 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 能够在 不少平台上运行,不管是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运 行结果是一致的。 所以用户能够很轻易的将在一个平台上运行的应用,迁移到另外一 个平台上,而不用担忧运行环境的变化致使应用没法正常运行的状况。

工做中的虚拟化和容器

 

 

docker三大概念

容器三大基本概念

镜像 image

容器 container

仓库 repository

 

docker镜像

Docker镜像就是一个只读的模板。

例如:一个镜像能够包含一个完整的CentOS操做系统环境,里面仅安装了Apache或用户须要的其余应用程序。

镜像能够用来建立Docker容器。

Docker提供了一个很简单的机制来建立镜像或者更新现有的镜像,用户甚至能够直接从其余人那里下载一个已经作好的镜像来直接使用。
image的分层存储

由于镜像包含完整的root文件系统,体积是很是庞大的,所以docker在设计时按照Union FS的技术,将其设计为分层存储的架构。
镜像不是ISO那种完整的打包文件,镜像只是一个虚拟的概念,他不是一个完整的文件,而是由一组文件组成,或者多组文件系统联合组成。
docker容器(container)

image和container的关系,就像面向对象程序设计中的 类和实例同样,镜像是静态的定义(class),容器是镜像运行时的实体(object)。
容器能够被建立、启动、中止、删除、暂停
Docker利用容器来运行应用。

容器是从镜像建立的运行实例。它能够被启动、开始、中止、删除。每一个容器都是相互隔离的,保证安全的平台。

能够把容器看作是一个简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

注意:镜像是只读的,容器在启动的时候建立一层可写层做为最上层。
docker仓库(repository)

仓库是集中存放镜像文件的场所。有时候把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上每每存放着多个仓库,每一个仓库中又包含了多个镜像,每一个镜像有不一样的标签(tag)。

仓库分为公开仓库(Public)和私有仓库(Private)两种形式。

最大的公开仓库是Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库包括Docker Pool等,能够提供大陆用户更稳定快读的访问。

当用户建立了本身的镜像以后就可使用push命令将它上传到公有或者私有仓库,这样下载在另一台机器上使用这个镜像时候,只需须要从仓库上pull下来就能够了。

注意:Docker仓库的概念跟Git相似,注册服务器能够理解为GitHub这样的托管服务。

docker Registry

Docker Registry 公开服务是开放给用户使用、容许用户管理镜像的 Registry 服 务。通常这类公开服务容许用户免费上传、下载公开的镜像,并可能提供收费服务 供用户管理私有镜像。

最常使用的 Registry 公开服务是官方的 Docker Hub,这也是默认的 Registry,并 拥有大量的高质量的官方镜像。

除此之外,还有 CoreOS 的 Quay.io,CoreOS 相 关的镜像存储在这里;Google 的 Google Container Registry,Kubernetes 的镜像 使用的就是这个服务。
因为某些缘由,在国内访问这些服务可能会比较慢。
国内的一些云服务商提供了针 对 Docker Hub 的镜像服务(Registry Mirror),这些镜像服务被称为加速器。常见 的有 阿里云加速器、DaoCloud 加速器、灵雀云加速器等。
使用加速器会直接从国内的地址下载 Docker Hub 的镜像,比直接从官方网站下载速度会提升不少。在后 面的章节中会有进一步如何配置加速器的讲解。
国内也有一些云服务商提供相似于 Docker Hub 的公开服务。好比 时速云镜像仓 库、网易云镜像服务、DaoCloud 镜像市场、阿里云镜像库等。

CentOS安装docker

 官方教程以下

https://docs.docker.com/install/linux/docker-ce/centos/#upgrade-docker-after-using-the-convenience-script

1.卸载旧版本
sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-selinux \
                  docker-engine-selinux \
                  docker-engine

2.设置存储库
sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2

sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

3.安装docker社区版
sudo yum install docker-ce
4.启动关闭docker
systemctl start docker

docker版本

Docker 是一个开源的商业产品,有两个版本:社区版(Community Edition,缩写为 CE)和企业版(Enterprise Edition,缩写为 EE)。
企业版包含了一些收费服务,我的开发者通常用不到。本文的介绍都针对社区版。

系统环境准备

docker最低支持centos7且在64位平台上,内核版本在3.10以上
[root@oldboy_python ~ 10:48:11]#uname -r
3.10.0-693.el7.x86_64

Docker镜像加速器

https://www.daocloud.io/mirror#accelerator-doc


https://www.cnblogs.com/pyyu/p/6925606.html
#一条命令加速
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://95822026.m.daocloud.io


好像有一个坑,请修改配置文件 /etc/docker/daemon.json
    
    改为以下配置便可
    {"registry-mirrors": ["http://f1361db2.m.daocloud.io"]}
    3.重启docker
    systemctl restart docker 

 yum安装

阿里云默认也有docker软件,也能够下载,只是版本较低
    正在安装:
     docker                                       x86_64       2:1.13.1-88.git07f3374.el7.centos         extras         17 M

3.安装docker
yum install docker
检测是否安装完毕
rpm -qi docker

4.启动docker 
systemctl start/status docker 
5.确认docker以及启动
docker version 

docker基础命令注释

[root@docker ~]# docker --help

Usage:
docker [OPTIONS] COMMAND [arg...]

       docker daemon [ --help | ... ]

       docker [ --help | -v | --version ]

 

A
self-sufficient runtime for containers.

 

Options:

 

  --config=~/.docker              Location of client config files  #客户端配置文件的位置

  -D, --debug=false               Enable debug mode  #启用Debug调试模式

  -H, --host=[]                   Daemon socket(s) to connect to  #守护进程的套接字(Socket)链接

  -h, --help=false                Print usage  #打印使用

  -l, --log-level=info            Set the logging level  #设置日志级别

  --tls=false                     Use TLS; implied by--tlsverify  #

  --tlscacert=~/.docker/ca.pem    Trust certs signed only by this CA  #信任证书签名CA

  --tlscert=~/.docker/cert.pem    Path to TLS certificate file  #TLS证书文件路径

  --tlskey=~/.docker/key.pem      Path to TLS key file  #TLS密钥文件路径

  --tlsverify=false               Use TLS and verify the remote  #使用TLS验证远程

  -v, --version=false             Print version information and quit  #打印版本信息并退出

 

Commands:

    attach    Attach to a running container  #当前shell下attach链接指定运行镜像

    build     Build an image from a Dockerfile  #经过Dockerfile定制镜像

    commit    Create a new image from a container's changes  #提交当前容器为新的镜像

    cp    Copy files/folders from a container to a HOSTDIR or to STDOUT  #从容器中拷贝指定文件或者目录到宿主机中

    create    Create a new container  #建立一个新的容器,同run 但不启动容器

    diff    Inspect changes on a container's filesystem  #查看docker容器变化

    events    Get real time events from the server#从docker服务获取容器实时事件

    exec    Run a command in a running container#在已存在的容器上运行命令

    export    Export a container's filesystem as a tar archive  #导出容器的内容流做为一个tar归档文件(对应import)

    history    Show the history of an image  #展现一个镜像造成历史

    images    List images  #列出系统当前镜像

    import    Import the contents from a tarball to create a filesystem image  #从tar包中的内容建立一个新的文件系统映像(对应export)

    info    Display system-wide information  #显示系统相关信息

    inspect    Return low-level information on a container or image  #查看容器详细信息

    kill    Kill a running container  #kill指定docker容器

    load    Load an image from a tar archive or STDIN  #从一个tar包中加载一个镜像(对应save)

    login    Register or log in to a Docker registry#注册或者登录一个docker源服务器

    logout    Log out from a Docker registry  #从当前Docker registry退出

    logs    Fetch the logs of a container  #输出当前容器日志信息

    pause    Pause all processes within a container#暂停容器

    port    List port mappings or a specific mapping for the CONTAINER  #查看映射端口对应的容器内部源端口

    ps    List containers  #列出容器列表

    pull    Pull an image or a repository from a registry  #从docker镜像源服务器拉取指定镜像或者库镜像

    push    Push an image or a repository to a registry  #推送指定镜像或者库镜像至docker源服务器

    rename    Rename a container  #重命名容器

    restart    Restart a running container  #重启运行的容器

    rm    Remove one or more containers  #移除一个或者多个容器

    rmi    Remove one or more images  #移除一个或多个镜像(无容器使用该镜像才能够删除,不然须要删除相关容器才能够继续或者-f强制删除)

    run    Run a command in a new container  #建立一个新的容器并运行一个命令

    save    Save an image(s) to a tar archive#保存一个镜像为一个tar包(对应load)

    search    Search the Docker Hub for images  #在docker
hub中搜索镜像

    start    Start one or more stopped containers#启动容器

    stats    Display a live stream of container(s) resource usage statistics  #统计容器使用资源

    stop    Stop a running container  #中止容器

    tag         Tag an image into a repository  #给源中镜像打标签

    top       Display the running processes of a container #查看容器中运行的进程信息

    unpause    Unpause all processes within a container  #取消暂停容器

    version    Show the Docker version information#查看容器版本号

    wait         Block until a container stops, then print its exit code  #截取容器中止时的退出状态值

 

Run 'docker COMMAND --help' for more information on a command.  #运行docker命令在帮助能够获取更多信息
基础命令注释

使用docker镜像

从仓库获取镜像 管理本地主机的镜像

获取镜像

从docker registry获取镜像的命令是docker pull。命令格式是:
docker pull [选项][docker registry地址] 仓库名:标签
docker register地址:地址的格式通常是 域名:端口,默认地址是docker hub
仓库名:仓库名是两段格式,用户名/软件名,若是不写用户,默认docker hub用户名是library,也就是官方镜像

镜像文件

docker是把应用程序和其依赖打包在image文件里面,只有经过这个镜像文件才能生成docker容器。
一个image文件能够生成多个容器实例。

列出服务器全部镜像文件

#列出全部的image文件
docker image ls
#删除image文件
docker image rm [imagename]

搜索docker镜像

[root@docker ~]# docker search centos  #搜索全部centos的docker镜像

INDEX                NAME(名称)                  DESCRIPTION(描述)                    STARS(下载次数)OFFICIAL(官方)        AUTOMATED(自动化)

docker.io           docker.io/centos         The official build of CentOS.        1781               [OK]

docker.io   docker.io/jdeathe/centos-ssh     CentOS-6 6.7 x86_64 /             14                                               [OK]

……

获取docker镜像

可使用docker pull命令来从仓库获取所须要的镜像。下面的例子将从Docker Hub仓库下载一个Centos操做系统的镜像。

[root@docker ~]# docker pull centos  #获取centos镜像

[root@docker ~]# docker run -it centos /bin/bash  #完成后可使用该镜像建立一个容器

查看docker镜像

镜像的ID惟一标识了镜像,若是ID相同,说明是同一镜像。

TAG信息来区分不一样发行版本,若是不指定具体标记,默认使用latest标记信息。

[root@docker ~]# docker images  #查看docker镜像

REPOSITORY(来自那个仓库)       TAG(标签)            IMAGE ID(惟一ID)         CREATED(建立时间)         VIRTUAL SIZE(大小)

docker.io/centos                   latest              60e65a8e4030           5
days ago              196.6 MB

docker.io/nginx             latest              813e3731b203             13
days ago             133.8 MB

删除Docker镜像

若是要移除本地的镜像,可使用docker rmi命令(在删除镜像以前先用docker rm删除依赖于这个镜像的全部容器)。注意docker rm 命令是移除容器。

[root@docker ~]# docker rmi imageID  #删除docker镜像

运行镜像,且产生一个容器记录,且进入容器空间内

docker run  -it  centos  /bin/bash
    -it 交互式的终端,表明我能够在容器中输入命令
    /bin/bash  指定shell解释器

建立一个容器,在容器安装一个vim工具

    docker run  -it  centos  /bin/bash
    #在容器空间内装vim
    yum install vim -y 
    #使用vim
    docker run  -it  容器di  /bin/bash
    vim

容器因为没有后台任务,当即挂掉,可是咱们能够提交这个容器为新的镜像

exit
docker commit  a3bd9bca8c80    shenzhenqishi1qi/centos-vim

#查看已提交的镜像记录
docker images

基于这个拥有vim的镜像,建立新的容器

docker run -it 镜像id  /bin/bash

导出docker镜像

若是要导出镜像到本地文件,可使用docker save命令。

[root@docker ~]#

#exit 先退出docker
docker save shenzhenqishi1qi/centos-vim > /opt/centos-vim.tar.gz

导入docker镜像

可使用docker load从本地文件中导入到本地docker镜像库

[root@docker ~]# docker load < /opt/centos-vim.tar.gz  #导入本地镜像到docker镜像库

[root@docker~]# docker images  #查看镜像导入状况

启动docker容器的方式

    1.基于镜像建立新的容器
    2.对于已运行的容器,进行启停
    docker stop 容器id
    docker start 容器id

#这条命令意思是:建立一个只运行一次的容器
docker run centos /bin/echo "hehe"

 

运行一个容器记录,且给与名字

docker run --name mydocker -it centos /bin/bash#启动一个bash终端,容许用户进行交互
--name:给容器定义一个名称

-i:则让容器的标准输入保持打开。

-t:让Docker分配一个伪终端,并绑定到容器的标准输入上

/bin/bash:执行一个命令
 

docker与"hello docker"

hello world是程序员启蒙语言,咱们经过最简单的image文件“hello-world”,来感觉一下docker。
#获取镜像 hello-world
docker pull hello-world
#检查镜像
docker images
#运行image文件,能够用容器id
docker run hello-world
#检查docker容器进程
docker ps
#检查全部运行过的容器
docker ps -a

运行一个ubuntu容器 

1.查看系统的版本信息
    cat /etc/redhat-release  #这个命令查看红帽系列的系统
    cat /etc/os-release
    2.运行一个ubuntu容器
    docker run -it  ubuntu  /bin/bash 

删除容器记录

docker rm  容器id
docker  -aq  #列出全部容器记录的id
docker stop  `docker ps -aq`  #中止全部正在运行的容器
docker  rm `docker ps -aq`    #一次性删除全部容器记录
docker rmi  `docker images -aq`   #一次性删除全部本地的镜像记录

暴露容器端口,端口映射

-P 参数会随机映射端口到容器开放的网络端口
    docker run -d -P training/webapp python app.py
        -d 后台运行 
        -P  端口映射, 随机映射 ,物理机的随机端口:容器内暴露的端口
        

    若是本地没有镜像文件,docker run会自动帮咱们下载镜像
    在docker run centos  
[root@qishione ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
e3e0be2b22a8        training/webapp     "python app.py"     2 seconds ago       Up 1 second         0.0.0.0:32769->5000/tcp   qishiweb

只要我访问宿主机的32769端口也就是访问到了容器内的5000端口
重启后容器端口号会随机改变
[root@yidashi opt]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                     NAMES
054fda5751a3        training/webapp     "python app.py"     About a minute ago   Up About a minute   0.0.0.0:32768->5000/tcp   kind_euclid
[root@yidashi opt]# netstat -tunlp |grep 32768
tcp6       0      0 :::32768                :::*                    LISTEN      98765/docker-proxy- 
[root@yidashi opt]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
054fda5751a3        training/webapp     "python app.py"     5 minutes ago       Up 5 minutes        0.0.0.0:32768->5000/tcp   kind_euclid
[root@yidashi opt]# docker stop 054
054
[root@yidashi opt]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@yidashi opt]# docker start 054
054
##从原来的32768变成32769了
[root@yidashi opt]# docker port 054
5000/tcp -> 0.0.0.0:32769

指定端口映射,启动容器应用

docker run -d -p 9999:5000 --name my9999webapp training/webapp python app.py

 不间断打印容器的日志信息 

docker  logs  -f  容器id 

利用dockerfile定制镜像

镜像是容器的基础,每次执行docker run的时候都会指定哪一个镜像做为容器运行的基础。咱们以前的例子都是使用来自docker hub的镜像,直接使用这些镜像只能知足必定的需求,当镜像没法知足咱们的需求时,就得自定制这些镜像。

镜像的定制就是定制每一层所添加的配置、文件。若是能够吧每一层修改、安装、构建、操做的命令都写入到一个脚本,用脚原本构建、定制镜像,这个脚本就是dockerfile。
Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令 构建一层,所以每一条指令的内容,就是描述该层应当如何构建。

FROM scratch #制做base image 基础镜像,尽可能使用官方的image做为base image
FROM centos #使用base image
FROM ubuntu:14.04 #带有tag的base image

LABEL version=“1.0” #容器元信息,帮助信息,Metadata,相似于代码注释
LABEL maintainer=“yc_uuu@163.com"

#对于复杂的RUN命令,避免无用的分层,多条命令用反斜线换行,合成一条命令!
RUN yum update && yum install -y vim \
    Python-dev #反斜线换行
RUN /bin/bash -c "source $HOME/.bashrc;echo $HOME”

WORKDIR /root #至关于linux的cd命令,改变目录,尽可能使用绝对路径!!!不要用RUN cd
WORKDIR /test #若是没有就自动建立
WORKDIR demo #再进入demo文件夹
RUN pwd     #打印结果应该是/test/demo

ADD and COPY 
ADD hello /  #把本地文件添加到镜像中,吧本地的hello可执行文件拷贝到镜像的/目录
ADD test.tar.gz /  #添加到根目录并解压

WORKDIR /root
ADD hello test/  #进入/root/ 添加hello可执行命令到test目录下,也就是/root/test/hello 一个绝对路径
COPY hello test/  #等同于上述ADD效果

ADD与COPY
   - 优先使用COPY命令
    -ADD除了COPY功能还有解压功能
添加远程文件/目录使用curl或wget

ENV #环境变量,尽量使用ENV增长可维护性
ENV MYSQL_VERSION 5.6 #设置一个mysql常量
RUN yum install -y mysql-server=“${MYSQL_VERSION}” 

------这里须要稍微理解一下了-------中级知识---先不讲

VOLUME and EXPOSE 
存储和网络

RUN and CMD and ENTRYPOINT
RUN:执行命令并建立新的Image Layer
CMD:设置容器启动后默认执行的命令和参数
ENTRYPOINT:设置容器启动时运行的命令

Shell格式和Exec格式
RUN yum install -y vim
CMD echo ”hello docker”
ENTRYPOINT echo “hello docker”

Exec格式
RUN [“apt-get”,”install”,”-y”,”vim”]
CMD [“/bin/echo”,”hello docker”]
ENTRYPOINT [“/bin/echo”,”hello docker”]


经过shell格式去运行命令,会读取$name指令,而exec格式是仅仅的执行一个命令,而不是shell指令
cat Dockerfile
    FROM centos
    ENV name Docker
    ENTRYPOINT [“/bin/echo”,”hello $name”]#这个仅仅是执行echo命令,读取不了shell变量
    ENTRYPOINT  [“/bin/bash”,”-c”,”echo hello $name"]

CMD
容器启动时默认执行的命令
若是docker run指定了其余命令(docker run -it [image] /bin/bash ),CMD命令被忽略
若是定义多个CMD,只有最后一个执行

ENTRYPOINT
让容器以应用程序或服务形式运行
不会被忽略,必定会执行
最佳实践:写一个shell脚本做为entrypoint
COPY docker-entrypoint.sh /usr/local/bin
ENTRYPOINT [“docker-entrypoint.sh]
EXPOSE 27017
CMD [“mongod”]

[root@master home]# more Dockerfile
FROm centos
ENV name Docker
#CMD ["/bin/bash","-c","echo hello $name"]
ENTRYPOINT ["/bin/bash","-c","echo hello $name”]

发布docker image到仓库

1.docker提供了一个相似于github的仓库dockerhub,
网址https://hub.docker.com/须要注册使用
2.注册docker id后,在linux中登陆dockerhub
docker login

注意要保证image的tag是帐户名,若是镜像名字不对,须要改一下tag
docker tag chaoyu/centos-vim yuchao163/centos-vim
语法是: docker tag 仓库名 yuchao163/仓库名


3.推送docker image到dockerhub
docker push yuchao163/centps-cmd-exec:latest
4.在dockerhub中检查镜像
https://hub.docker.com/
5.删除本地镜像,测试下载pull 镜像文件
docker pull yuchao163/centos-entrypoint-exec

私有仓库

1.官方提供的私有仓库docker registry用法
https://yeasy.gitbooks.io/docker_practice/repository/registry.html
2.一条命令下载registry镜像而且启动私有仓库容器
私有仓库会被建立在容器的/var/lib/registry下,所以经过-v参数将镜像文件存储到本地的/opt/data/registry下
端口映射容器中的5000端口到宿主机的5000端口
docker run -d  -p 5000:5000-v /opt/data/registry:/var/lib/registry registry
        #-d 后台运行 
        #-p  端口映射 宿主机的5000:容器内的5000
        #-v  数据卷挂载  宿主机的 /opt/data/registry :/var/lib/registry 
        #registry  镜像名

3.检查启动的registry容器
docker ps
4.测试链接容器
telnet 192.168.119.10 5000
5.修改镜像tag,以docker registry的地址端口开头
docker tag hello-world:latest 192.168.119.10:5000/hello-world:latest
6.查看docker镜像,找到registry的镜像
docker images
7.Docker 默认不容许非 HTTPS 方式推送镜像。咱们能够经过 Docker 的配置选项来取消这个限制,这里必须写正确json数据
[root@master /]# cat /etc/docker/daemon.json
{"registry-mirrors": ["http://95822026.m.daocloud.io"],
"insecure-registries":["192.168.119.10:5000"]
}

写入到docker服务中,写入到[Service]配置块中,加载此配置文件
[root@master home]# grep 'EnvironmentFile=/etc/docker/daemon.json' /lib/systemd/system/docker.service
EnvironmentFile=-/etc/docker/daemon.json
8.修改了docker配置文件,从新加载docker
systemctl daemon-reload
9.重启docker
systemctl restart docker
10.重启了docker,刚才的registry容器进程挂掉了,所以从新启动它
docker ps -a
docker start 容器id
11.推送本地镜像
docker push 192.168.119.10:5000/hello-world

12.因为docker registry没有web节目,可是提供了API数据
官网教程:https://docs.docker.com/registry/spec/api/#listing-repositories

curl http://192.168.119.10:5000/v2/_catalog

或者浏览器访问http://192.168.119.10:5000/v2/_catalog
13.删除本地镜像,从私有仓库中下载
docker pull 192.168.119.10:5000/hello-world

打包flask程序与dockerfile

    1.在宿主机中,编写一个flask代码文件,和Dockerfile
    cd /opt/dockertest/
    touch flasktest.py 
        from flask import Flask
        app=Flask(__name__)
        @app.route('/')
        def hello():
        return "i love china"
        if __name__=="__main__":
        app.run(host='0.0.0.0',port=8080)

     
    
    2.构建Dockerfile(必须首字母大写)
        1.指引一个基础的系统镜像centos 
        2.定义做者标签
        3.解决环境依赖关系,安装python-setuptools
        4.安装flask模块  easy_install  flask 
        5.准备代码文件到容器中   COPY  flasktest.py   /opt/ 
        6.切换到/opt目录下 workdir  /opt 
        7.暴露容器端口
        8.运行代码  python flasktest.py 
        
    3.Dockerfile内容以下
    [root@qishione dockertest]# cat Dockerfile 
        FROM centos
        LABEL maintainer="深圳骑士1期"
        RUN yum install python-setuptools -y 
        RUN  easy_install flask 
        COPY  flasktest.py   /opt/
        WORKDIR /opt
        EXPOSE 8080  
        CMD ["python","flasktest.py"]

    4.构建镜像文件,找到当前目录的Dockerfile,开始构建
    docker build  -t  qishi1qi/flask-web    .  
        -t  打个标记号
        
    5.基于这个镜像,生成容器实例
    docker run -d -p  7777:8080    945
    
    6.推送这个镜像到私有仓库
    docker tag  qishi1qi/flask-web   192.168.11.37:5000/qishi1qi-flaskweb
    docker push 192.168.11.37:5000/qishi1qi-flaskweb

 

容器是运行应用程序的,因此必须得先有一个操做系统为基础

容器是运行应用程序的,因此必须得先有一个操做系统为基础

容器是运行应用程序的,因此必须得先有一个操做系统为基础

 docker容器必须有后台进程在运行,若是docker容器内没有任务在运行中,容器就退出

docker容器必须有后台进程在运行,若是docker容器内没有任务在运行中,容器就退出

docker容器必须有后台进程在运行,若是docker容器内没有任务在运行中,容器就退出

相关文章
相关标签/搜索