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容器內沒有任務在運行中,容器就退出

相關文章
相關標籤/搜索