Redis初步認識


官網:redis.io

Redis是一個開源的使用ANSI C語言編寫、支持網絡、可基於內存亦可持久化的日志型、Key-Value數據庫,並提供多種語言的API。從2010年3月15日起,Redis的開發工作由VMware主持。從2013年5月開始,Redis的開發由Pivotal贊助

 

redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字符串)、list( 鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些 數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。
Redis 是一個 高性能的key-value數據庫。 redis的出現,很大程度補償了 memcached這類key/value存儲的不足,在部 分場合可以對關系數據庫起到很好的補充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客戶端,使用很方便。[1]  
Redis 支持主從同步。數據可以 從主服務器向任意數量的從服務器上同步,從服務器可以是關聯其他從服務器的主服務器。這使得Redis可執行單層樹復制。存盤可以有意無意的對數據進行寫操作。由於完全實現了發布/訂閱機制,使得從數據庫在任何地方同步樹時,可訂閱一個頻道並接收主服務器完整的消息發布記錄。同步對讀取操作的可擴展性和數據冗余很有幫助。
redis的官網地址,非常好記,是redis.io。(特意查了一下, 域名后綴io屬於國家域名是british Indian Ocean territory,即英屬印度洋領地
目前,Vmware在資助着redis項目的開發和維護。
 
Redis是一個key-value存儲系統。 和Memcached類似,但是解決了斷電后數據完全丟失的情況,而且她支持更多無化的value類型,除了和string外,還支持lists(鏈表)、sets(集合)和zsets(有序集合)幾種數據類型。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。

安裝


獲取源碼、解壓、進入源碼目錄
使用wget工具等下載:
wget (百度不讓用鏈接)
tar xzf redis-1.2.6.tar.gz
cd redis-1.2.6。
編譯生成可執行文件
由於makefile文件已經寫好,我們只需要直接在源碼目錄執行make命令進行編譯即可:
make
make-test
sudo make install
make命令執行完成后,會在當前目錄下生成本個 可執行文件,分別是redis-server、redis-cli、redis-benchmark、redis-stat,它們的作用如下:
redis-server:Redis服務器的daemon啟動程序
redis-cli:Redis命令行操作工具。當然,你也可以用telnet根據其純文本協議來操作
redis-benchmark:Redis 性能測試工具,測試Redis在你的系統及你的配置下的讀寫性能
redis-stat:Redis狀態檢測工具,可以檢測Redis當前狀態參數及延遲狀況。
建立Redis目錄(非必須)
這個過程不是必須的,只是為了將Redis相關的 資源統一管理而進行的操作。
執行以下命令建立相關目錄並拷貝相關文件至目錄中:
sudo -s
mkdir -p /usr/local/redis/bin
mkdir -p /usr/local/redis/etc
mkdir -p /usr/local/redis/var
cp redis-server redis-cli redis-benchmark redis-stat /usr/local/redis/bin/
cp redis.conf /usr/local/redis/etc/
 
配置參數
在我們成功安裝Redis后,我們直接執行redis-server即可運行Redis,此時它是按照默認配置來運行的(默認配置甚至不是 后台運行)。我們希望Redis按我們的要求運行,則我們需要修改配置文件,Redis的配置文件就是我們上面第二個cp操作的redis.conf文件,它被我們拷貝到了/usr/local/redis/etc/目錄下。修改它就可以配置我們的server了。如何修改?下面是redis.conf的主要配置參數的意義:
daemonize:是否以 后台daemon方式運行
pidfile:pid文件位置
port:監聽的端口號
timeout:請求超時時間
loglevel:log信息級別
logfile:log文件位置
databases:開啟數據庫的數量
save * *:保存 快照的頻率,第一個*表示多長時間,第二個*表示執行多少次寫操作。在一定時間內執行一定數量的寫操作時,自動保存 快照。可設置多個條件。
rdbcompression:是否使用壓縮
dbfilename:數據 快照文件名(只是文件名,不包括目錄)
dir:數據 快照的保存目錄(這個是目錄)
appendonly:是否開啟appendonlylog,開啟的話每次寫操作會記一條log,這會提高數據抗風險能力,但影響效率。
appendfsync:appendonlylog如何同步到磁盤(三個選項,分別是每次寫都強制調用fsync、每秒啟用一次fsync、不調用fsync等待系統自己同步)
下面是一個略做修改后的配置文件內容:
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
daemonizeyes
pidfile/usr/local/redis/var/redis.pid
port6379
timeout300
logleveldebug
logfile/usr/local/redis/var/redis. log
databases16
save9001
save30010
save6010000
rdbcompressionyes
dbfilenamedump.rdb
dir/usr/local/redis/var/
appendonlyno
appendfsyncalways
glueoutputbufyes
shareobjectsno
shareobjectspoolsize1024

 

 

將上面內容寫為redis.conf並保存到/usr/local/redis/etc/目錄下
然后在命令行執行:
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
即可在 后台啟動redis服務,這時你通過
telnet 127.0.0.16379
即可連接到你的redis服務
Redis常用內存優化手段與參數
通過我們上面的一些實現上的分析可以看出redis實際上的內存管理成本非常高,即占用了過多的內存,作者對這點也非常清楚,所以提供了一系列的參數和手段來控制和節省內存,我們分別來討論下。
  首先最重要的一點是不要開啟Redis的VM選項,即虛擬內存功能,這個本來是作為Redis存儲超出物理內存數據的一種數據在內存與磁盤換入換出的一個持久化策略,但是其內存管理成本也非常的高,並且我們后續會分析此種持久化策略並不成熟,所以要關閉VM功能,請檢查你的redis.conf文件中 vm-enabled 為 no。
  其次最好設置下redis.conf中的maxmemory選項,該選項是告訴Redis當使用了多少物理內存后就開始拒絕后續的寫入請求,該參數能很好的保護好你的Redis不會因為使用了過多的物理內存而導致swap,最終嚴重影響性能甚至崩潰。
  另外Redis為不同數據類型分別提供了一組參數來控制內存使用,我們在前面詳細分析過Redis Hash是value內部為一個HashMap,如果該Map的成員數比較少,則 會采用類似一維線性的緊湊格式來存儲該Map, 即省去了大量指針的內存開銷,這個參數控制對應在redis.conf配置文件中下面2項:
  1. hash-max-zipmap-entries 64
  2. hash-max-zipmap-value 512
  3. hash-max-zipmap-entries
含義是當value這個Map內部不超過多少個成員時會采用線性緊湊格式存儲,默認是64,即value內部有64個以下的成員就是使用線性緊湊存儲,超過該值自動轉成真正的HashMap。
  hash-max-zipmap-value 含義是當 value這個Map內部的每個成員值長度不超過多少字節就會采用線性緊湊存儲來節省空間。
  以上2個條件任意一個條件超過設置值都會轉換成真正的HashMap,也就不會再節省內存了,那么這個值是不是設置的越大越好呢,答案當然是否定的,HashMap的優勢就是查找和操作的時間復雜度都是O(1)的,而放棄Hash采用一維存儲則是O(n)的時間復雜度,如果
  成員數量很少,則影響不大,否則會嚴重影響性能,所以要權衡好這個值的設置,總體上還是最根本的時間成本和空間成本上的權衡。
同樣類似的參數
list-max-ziplist-entries 512
  說明:list數據類型多少節點以下會采用去指針的緊湊存儲格式。
  list-max-ziplist-value 64
  說明:list數據類型節點值大小小於多少字節會采用緊湊存儲格式。
  set-max-intset-entries 512
  說明:set數據類型內部數據如果全部是數值型,且包含多少節點以下會采用緊湊格式存儲。
  最后想說的是Redis內部實現沒有對內存分配方面做過多的優化,在一定程度上會存在內存碎片,不過大多數情況下這個不會成為Redis的性能瓶頸,不過如果在Redis內部存儲的大部分數據是數值型的話,Redis內部采用了一個shared integer的方式來省去分配內存的開銷,即在系統啟動時先分配一個從1~n 那么多個數值對象放在一個池子中,如果存儲的數據恰好是這個數值范圍內的數據,則直接從池子里取出該對象,並且通過引用計數的方式來共享,這樣在系統存儲了大量數值下,也能一定程度上節省內存並且提高性能,這個參數值n的設置需要修改源代碼中的一行宏定義REDIS_SHARED_INTEGERS,該值默認是10000,可以根據自己的需要進行修改,修改后重新編譯就可以了。
  另外redis 的6種過期策略redis 中的默認的過期策略是volatile-lru 。設置方式
  config set maxmemory-policy volatile-lru
  maxmemory-policy 六種方式
  volatile-lru:只對設置了過期時間的key進行LRU(默認值)
  allkeys-lru : 是從所有key里 刪除 不經常使用的key
  volatile-random:隨機刪除即將過期key
  allkeys-random:隨機刪除
  volatile-ttl : 刪除即將過期的
  noeviction : 永不過期,返回錯誤
  maxmemory-samples 3 是說每次進行淘汰的時候 會隨機抽取3個key 從里面淘汰最不經常使用的(默認選項)

版本發布

編輯
2012年08月02日,Redis 2.4.16 小更新版本 NoSQL。[3]  
2012年08月31日 ,Redis 2.4.17 小更新版本 NoSQL。[4]  
2012年11月7日 Redis 2.6.3 發布,高性能K/V服務器
2013年4月30日Redis 2.6.13 發布,高性能K/V服務器[5]  
2013年11月25日,Redis 2.8.1發布。[6]  
2015年2月,Redis3.0.0發布.[7]  
 
 

教程網址:http://tengine.taobao.org/book/chapter_02.html

 

nginx是以多進程的方式來工作, 也是nginx的默認方式

nginx在啟動后,會有一個master進程和多個worker進程

master進程主要用來管理worker進程

包含:接收來自外界的信號       ,向各worker進程發送信號,監控worker進程的運行狀態,當worker進程退出后(異常情況下),會自動重新啟動新的worker進程。而基本的網絡事件,則是放在worker進程中來處理了。多個worker進程之間是對等的,他們同等競爭來自客戶端的請求,各進程互相之間是獨立的。一個請求,只可能在一個worker進程中處理,一個worker進程,不可能處理其它進程的請求。worker進程的個數是可以設置的,一般我們會設置與機器cpu核數一致,這里面的原因與nginx的進程模型以及事件處理模型是分不開的。nginx的進程模型,可以由下圖來表示:

 

 

kill -HUP pid  #重啟nginx

 

#nginx在0.8版本之后,有了以下命令,方便管理

./nginx -s reload #重啟nginx

./nginx -s stop #停止nginx的運行

 

nginx采用了異步非阻塞的方式來處理請求,nginx是可以同時處理成千上萬個請求的。想想apache的常用工作方式(apache也有異步非阻塞版本,但因其與自帶某些模塊沖突,所以不常用)

 

請求的完整過程:

首先,請求過來,要建立連接,然后再接收數據,接收數據后,再發送數據。具體到系統底層,就是讀寫事件,而當讀寫事件沒有准備好時,必然不可操作,如果不用非阻塞的方式來調用,那就得阻塞調用了,事件沒有准備好,那就只能等了,等事件准備好了,你再繼續吧。阻塞調用會進入內核等待,cpu就會讓出去給別人用了,對單線程的worker來說,顯然不合適,當網絡事件越多時,大家都在等待呢,cpu空閑下來沒人用,cpu利用率自然上不去了,更別談高並發了。

 

並發數再多也不會導致無謂的資源浪費(上下文切換)。更多的並發數,只是會占用更多的內存而已。 我之前有對連接數進行過測試,在24G內存的機器上,處理的並發請求數達到過200萬。

 

當我們寫nginx代碼時,在處理網絡事件的回調函數時,通常做的第一個事情就是判斷超時,然后再去處理網絡事件。

 

nginx是如何處理一個連接的??

首先,nginx在啟動時,會解析配置文件,得到需要監聽的端口與ip地址,然后在nginx的master進程里面,先初始化好這個監控的socket(創建socket,設置addrreuse等選項,綁定到指定的ip地址端口,再listen),然后再fork出多個子進程出來,然后子進程會競爭accept新的連接。此時,客戶端就可以向nginx發起連接了。當客戶端與服務端通過三次握手建立好一個連接后,nginx的某一個子進程會accept成功,得到這個建立好的連接的socket,然后創建nginx對連接的封裝,即ngx_connection_t結構體。接着,設置讀寫事件處理函數並添加讀寫事件來與客戶端進行數據的交換。最后,nginx或客戶端來主動關掉連接,到此,一個連接就壽終正寢了。

 

 

通過ulimit -n,我們可以得到一個進程所能夠打開的fd的最大數,即nofile,

每個socket連接會占用掉一個fd

 

學習網址(參考):http://www.runoob.com/redis/redis-intro.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM