redis-sentinel主從復制高可用
Redis-Sentinel
Redis-Sentinel是redis官方推薦的高可用性解決方案,
當用redis作master-slave的高可用時,如果master本身宕機,redis本身或者客戶端都沒有實現主從切換的功能。
而redis-sentinel就是一個獨立運行的進程,用於監控多個master-slave集群,
自動發現master宕機,進行自動切換slave > master。
sentinel主要功能
不時的監控redis是否良好運行,如果節點不可達就會對節點進行下線標識
如果被標識的是主節點,sentinel就會和其他的sentinel節點“協商”,如果其他節點也人為主節點不可達,就會選舉一個sentinel節點來完成自動故障轉義
在master-slave進行切換后,master_redis.conf、slave_redis.conf和sentinel.conf的內容都會發生改變,即master_redis.conf中會多一行slaveof的配置,sentinel.conf的監控目標會隨之調換
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公作方式
redis主從復制背景問題
Redis主從復制可將主節點數據同步給從節點,從節點此時有兩個作用:
- 一旦主節點宕機,從節點作為主節點的備份可以隨時頂上來。
- 擴展主節點的讀能力,分擔主節點讀壓力。
但是問題是:
- 一旦主節點宕機,從節點上位,那么需要人為修改所有應用方的主節點地址(改為新的master地址),還需要命令所有從節點復制新的主節點
那么這個問題,redis-sentinel就可以解決了
主從復制架構


Redis Sentinel架構
redis的一個進程,但是不存儲數據,只是監控redis



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詳解--補充--
此時可以在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內存,你怎么辦?解決方案如下
- 配置一個超級牛逼的計算機,超大內存,超強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 在法國期間發起的一個公司內部項目,於 2013 年 3 月以 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容器內沒有任務在運行中,容器就退出
