『壹』 php面試題 memcache和redis的區別
Redis與Memcached的區別
傳統MySQL+ Memcached架構遇到的問題
實際MySQL是適合進行海量數據存儲的,通過Memcached將熱點數據載入到cache,加速訪問,很多公司都曾經使用過這樣的架構,但隨著業務數據量的不斷增加,和訪問量的持續增長,我們遇到了很多問題:
1.MySQL需要不斷進行拆庫拆表,Memcached也需不斷跟著擴容,擴容和維護工作占據大量開發時間。
2.Memcached與MySQL資料庫數據一致性問題。
3.Memcached數據命中率低或down機,大量訪問直接穿透到DB,MySQL無法支撐。
4.跨機房cache同步問題。
眾多NoSQL百花齊放,如何選擇
最近幾年,業界不斷涌現出很多各種各樣的NoSQL產品,那麼如何才能正確地使用好這些產品,最大化地發揮其長處,是我們需要深入研究和思考的
問題,實際歸根結底最重要的是了解這些產品的定位,並且了解到每款產品的tradeoffs,在實際應用中做到揚長避短,總體上這些NoSQL主要用於解
決以下幾種問題
1.少量數據存儲,高速讀寫訪問。此類產品通過數據全部in-momery 的方式來保證高速訪問,同時提供數據落地的功能,實際這正是Redis最主要的適用場景。
2.海量數據存儲,分布式系統支持,數據一致性保證,方便的集群節點添加/刪除。
3.這方面最具代表性的是dynamo和bigtable 2篇論文所闡述的思路。前者是一個完全無中心的設計,節點之間通過gossip方式傳遞集群信息,數據保證最終一致性,後者是一個中心化的方案設計,通過類似一個分布式鎖服務來保證強一致性,數據寫入先寫內存和redo log,然後定期compat歸並到磁碟上,將隨機寫優化為順序寫,提高寫入性能。
4.Schema free,auto-sharding等。比如目前常見的一些文檔資料庫都是支持schema-free的,直接存儲json格式數據,並且支持auto-sharding等功能,比如mongodb。
面對這些不同類型的NoSQL產品,我們需要根據我們的業務場景選擇最合適的產品。
Redis適用場景,如何正確的使用
前面已經分析過,Redis最適合所有數據in-momory的場景,雖然Redis也提供持久化功能,但實際更多的是一個disk-
backed的功能,跟傳統意義上的持久化有比較大的差別,那麼可能大家就會有疑問,似乎Redis更像一個加強版的Memcached,那麼何時使用
Memcached,何時使用Redis呢?
如果簡單地比較Redis與Memcached的區別,大多數都會得到以下觀點:
1 Redis不僅僅支持簡單的k/v類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。
2 Redis支持數據的備份,即master-slave模式的數據備份。
3 Redis支持數據的持久化,可以將內存中的數據保持在磁碟中,重啟的時候可以再次載入進行使用。
拋開這些,可以深入到Redis內部構造去觀察更加本質的區別,理解Redis的設計。
在
Redis中,並不是所有的數據都一直存儲在內存中的。這是和Memcached相比一個最大的區別。Redis只會緩存所有的
key的信息,如果Redis發現內存的使用量超過了某一個閥值,將觸發swap的操作,Redis根據「swappability =
age*log(size_in_memory)」計
算出哪些key對應的value需要swap到磁碟。然後再將這些key對應的value持久化到磁碟中,同時在內存中清除。這種特性使得Redis可以
保持超過其機器本身內存大小的數據。當然,機器本身的內存必須要能夠保持所有的key,畢竟這些數據是不會進行swap操作的。同時由於Redis將內存
中的數據swap到磁碟中的時候,提供服務的主線程和進行swap操作的子線程會共享這部分內存,所以如果更新需要swap的數據,Redis將阻塞這個
操作,直到子線程完成swap操作後才可以進行修改。
使用Redis特有內存模型前後的情況對比:
VM off: 300k keys, 4096 bytes values: 1.3G used
VM on: 300k keys, 4096 bytes values: 73M used
VM off: 1 million keys, 256 bytes values: 430.12M used
VM on: 1 million keys, 256 bytes values: 160.09M used
VM on: 1 million keys, values as large as you want, still: 160.09M used
當
從Redis中讀取數據的時候,如果讀取的key對應的value不在內存中,那麼Redis就需要從swap文件中載入相應數據,然後再返回給請求方。
這里就存在一個I/O線程池的問題。在默認的情況下,Redis會出現阻塞,即完成所有的swap文件載入後才會相應。這種策略在客戶端的數量較小,進行
批量操作的時候比較合適。但是如果將Redis應用在一個大型的網站應用程序中,這顯然是無法滿足大並發的情況的。所以Redis運行我們設置I/O線程
池的大小,對需要從swap文件中載入相應數據的讀取請求進行並發操作,減少阻塞的時間。
如果希望在海量數據的環境中使用好Redis,我相信理解Redis的內存設計和阻塞的情況是不可缺少的。
補充的知識點:
memcached和redis的比較
1 網路IO模型
Memcached是多線程,非阻塞IO復用的網路模型,分為監聽主線程和worker子線程,監聽線程監聽網路連接,接受請求後,將連接描述
字pipe 傳遞給worker線程,進行讀寫IO, 網路層使用libevent封裝的事件庫,多線程模型可以發揮多核作用,但是引入了cache
coherency和鎖的問題,比如,Memcached最常用的stats
命令,實際Memcached所有操作都要對這個全局變數加鎖,進行計數等工作,帶來了性能損耗。
(Memcached網路IO模型)
Redis使用單線程的IO復用模型,自己封裝了一個簡單的AeEvent事件處理框架,主要實現了epoll、kqueue和select,
對於單純只有IO操作來說,單線程可以將速度優勢發揮到最大,但是Redis也提供了一些簡單的計算功能,比如排序、聚合等,對於這些操作,單線程模型實
際會嚴重影響整體吞吐量,CPU計算過程中,整個IO調度都是被阻塞住的。
2.內存管理方面
Memcached使用預分配的內存池的方式,使用slab和大小不同的chunk來管理內存,Item根據大小選擇合適的chunk存儲,內
存池的方式可以省去申請/釋放內存的開銷,並且能減小內存碎片產生,但這種方式也會帶來一定程度上的空間浪費,並且在內存仍然有很大空間時,新的數據也可
能會被剔除,原因可以參考Timyang的文章:http://timyang.net/data/Memcached-lru-evictions/
Redis使用現場申請內存的方式來存儲數據,並且很少使用free-list等方式來優化內存分配,會在一定程度上存在內存碎片,Redis
跟據存儲命令參數,會把帶過期時間的數據單獨存放在一起,並把它們稱為臨時數據,非臨時數據是永遠不會被剔除的,即便物理內存不夠,導致swap也不會剔
除任何非臨時數據(但會嘗試剔除部分臨時數據),這點上Redis更適合作為存儲而不是cache。
3.數據一致性問題
Memcached提供了cas命令,可以保證多個並發訪問操作同一份數據的一致性問題。 Redis沒有提供cas 命令,並不能保證這點,不過Redis提供了事務的功能,可以保證一串 命令的原子性,中間不會被任何操作打斷。
4.存儲方式及其它方面
Memcached基本只支持簡單的key-value存儲,不支持枚舉,不支持持久化和復制等功能
Redis除key/value之外,還支持list,set,sorted set,hash等眾多數據結構,提供了KEYS
進行枚舉操作,但不能在線上使用,如果需要枚舉線上數據,Redis提供了工具可以直接掃描其mp文件,枚舉出所有數據,Redis還同時提供了持久化和復制等功能。
5.關於不同語言的客戶端支持
在不同語言的客戶端方面,Memcached和Redis都有豐富的第三方客戶端可供選擇,不過因為Memcached發展的時間更久一些,目
前看在客戶端支持方面,Memcached的很多客戶端更加成熟穩定,而Redis由於其協議本身就比Memcached復雜,加上作者不斷增加新的功能
等,對應第三方客戶端跟進速度可能會趕不上,有時可能需要自己在第三方客戶端基礎上做些修改才能更好的使用。
根據以上比較不難看出,當我們不希望數據被踢出,或者需要除key/value之外的更多數據類型時,或者需要落地功能時,使用Redis比使用Memcached更合適。
關於Redis的一些周邊功能
Redis除了作為存儲之外還提供了一些其它方面的功能,比如聚合計算、pubsub、scripting等,對於此類功能需要了解其實現原
理,清楚地了解到它的局限性後,才能正確的使用,比如pubsub功能,這個實際是沒有任何持久化支持的,消費方連接閃斷或重連之間過來的消息是會全部丟
失的,又比如聚合計算和scripting等功能受Redis單線程模型所限,是不可能達到很高的吞吐量的,需要謹慎使用。
總的來說Redis作者是一位非常勤奮的開發者,可以經常看到作者在嘗試著各種不同的新鮮想法和思路,針對這些方面的功能就要求我們需要深入了解後再使用。
總結:
1.Redis使用最佳方式是全部數據in-memory。
2.Redis更多場景是作為Memcached的替代者來使用。
3.當需要除key/value之外的更多數據類型支持時,使用Redis更合適。
4.當存儲的數據不能被剔除時,使用Redis更合適。
談談Memcached與Redis(一)
1. Memcached簡介
Memcached是以LiveJurnal旗下Danga Interactive公司的Bard
Fitzpatric為首開發的高性能分布式內存緩存伺服器。其本質上就是一個內存key-value資料庫,但是不支持數據的持久化,伺服器關閉之後數
據全部丟失。Memcached使用C語言開發,在大多數像Linux、BSD和Solaris等POSIX系統上,只要安裝了libevent即可使
用。在Windows下,它也有一個可用的非官方版本(http://code.jellycan.com/memcached/)。Memcached
的客戶端軟體實現非常多,包括C/C++, PHP, Java, python, Ruby, Perl, Erlang,
Lua等。當前Memcached使用廣泛,除了LiveJournal以外還有Wikipedia、Flickr、Twitter、Youtube和
WordPress等。
在Window系統下,Memcached的安裝非常方便,只需從以上給出的地址下載可執行軟體然後運行memcached.exe –d
install即可完成安裝。在Linux等系統下,我們首先需要安裝libevent,然後從獲取源碼,make && make
install即可。默認情況下,Memcached的伺服器啟動程序會安裝到/usr/local/bin目錄下。在啟動Memcached時,我們可
以為其配置不同的啟動參數。
1.1 Memcache配置
Memcached伺服器在啟動時需要對關鍵的參數進行配置,下面我們就看一看Memcached在啟動時需要設定哪些關鍵參數以及這些參數的作用。
1)-p <num> Memcached的TCP監聽埠,預設配置為11211;
2)-U <num> Memcached的UDP監聽埠,預設配置為11211,為0時表示關閉UDP監聽;
3)-s <file> Memcached監聽的UNIX套接字路徑;
4)-a <mask> 訪問UNIX套接字的八進制掩碼,預設配置為0700;
5)-l <addr> 監聽的伺服器IP地址,默認為所有網卡;
6)-d 為Memcached伺服器啟動守護進程;
7)-r 最大core文件大小;
8)-u <username> 運行Memcached的用戶,如果當前為root的話需要使用此參數指定用戶;
9)-m <num> 分配給Memcached使用的內存數量,單位是MB;
10)-M 指示Memcached在內存用光的時候返回錯誤而不是使用LRU演算法移除數據記錄;
11)-c <num> 最大並發連數,預設配置為1024;
12)-v –vv –vvv 設定伺服器端列印的消息的詳細程度,其中-v僅列印錯誤和警告信息,-vv在-v的基礎上還會列印客戶端的命令和相應,-vvv在-vv的基礎上還會列印內存狀態轉換信息;
13)-f <factor> 用於設置chunk大小的遞增因子;
14)-n <bytes> 最小的chunk大小,預設配置為48個位元組;
15)-t <num> Memcached伺服器使用的線程數,預設配置為4個;
16)-L 嘗試使用大內存頁;
17)-R 每個事件的最大請求數,預設配置為20個;
18)-C 禁用CAS,CAS模式會帶來8個位元組的冗餘;
2. Redis簡介
Redis是一個開源的key-value存儲系統。與Memcached類似,Redis將大部分數據存儲在內存中,支持的數據類型包括:字
符串、哈希表、鏈表、集合、有序集合以及基於這些數據類型的相關操作。Redis使用C語言開發,在大多數像Linux、BSD和Solaris等
POSIX系統上無需任何外部依賴就可以使用。Redis支持的客戶端語言也非常豐富,常用的計算機語言如C、C#、C++、Object-C、PHP、
Python、Java、Perl、Lua、Erlang等均有可用的客戶端來訪問Redis伺服器。當前Redis的應用已經非常廣泛,國內像新浪、淘
寶,國外像Flickr、Github等均在使用Redis的緩存服務。
Redis的安裝非常方便,只需從http://redis.io/download獲取源碼,然後make && make
install即可。默認情況下,Redis的伺服器啟動程序和客戶端程序會安裝到/usr/local/bin目錄下。在啟動Redis伺服器時,我們
需要為其指定一個配置文件,預設情況下配置文件在Redis的源碼目錄下,文件名為redis.conf。
『貳』 php redis做mysql的緩存,怎麼非同步redis同步到mysql資料庫
對於變化頻率非常快的數據來說,如果還選擇傳統的靜態緩存方式(Memocached、File System等)展示數據,可能在緩存的存取上會有很大的開銷,並不能很好的滿足需要,而Redis這樣基於內存的NoSQL資料庫,就非常適合擔任實時數據的容器。
但是往往又有數據可靠性的需求,採用MySQL作為數據存儲,不會因為內存問題而引起數據丟失,同時也可以利用關系資料庫的特性實現很多功能。
所以就會很自然的想到是否可以採用MySQL作為數據存儲引擎,Redis則作為Cache。而這種需求目前還沒有看到有特別成熟的解決方案或工具,因此採用Gearman+PHP+MySQL UDF的組合非同步實現MySQL到Redis的數據復制。
MySQL到Redis數據復制方案
無論MySQL還是Redis,自身都帶有數據同步的機制,比較常用的MySQL的Master/Slave模式,就是由Slave端分析Master的binlog來實現的,這樣的數據復制其實還是一個非同步過程,只不過當伺服器都在同一內網時,非同步的延遲幾乎可以忽略。
那麼理論上也可以用同樣方式,分析MySQL的binlog文件並將數據插入Redis。但是這需要對binlog文件以及MySQL有非常深入的理解,同時由於binlog存在Statement/Row/Mixedlevel多種形式,分析binlog實現同步的工作量是非常大的。
因此這里選擇了一種開發成本更加低廉的方式,借用已經比較成熟的MySQL UDF,將MySQL數據首先放入Gearman中,然後通過一個自己編寫的PHP Gearman Worker,將數據同步到Redis。比分析binlog的方式增加了不少流程,但是實現成本更低,更容易操作。
Gearman的安裝與使用
Gearman是一個支持分布式的任務分發框架。設計簡潔,獲得了非常廣泛的支持。一個典型的Gearman應用包括以下這些部分:
Gearman Job Server:Gearman核心程序,需要編譯安裝並以守護進程形式運行在後台
Gearman Client:可以理解為任務的收件員,比如在後台執行一個發送郵件的任務,可以在程序中調用一個Gearman Client並傳入郵件的信息,然後就可以將執行結果立即展示給用戶,而任務本身會慢慢在後台運行。
Gearman Worker:任務的真正執行者,一般需要自己編寫具體邏輯並通過守護進程方式運行,Gearman Worker接收到Gearman Client傳遞的任務內容後,會按順序處理。
以前曾經介紹過類似的後台任務處理項目Resque。兩者的設計其實非常接近,簡單可以類比為:
Gearman Job Server:對應Resque的Redis部分
Gearman Client:對應Resque的Queue操作
Gearman Worker:對應Resque的Worker和Job
這里之所以選擇Gearman而不是Resque是因為Gearman提供了比較好用的MySQL UDF,工作量更小。
安裝Gearman及PHP Gearman擴展
以下均以Ubuntu12.04為例。
apt-get install gearman gearman-server libgearman-dev
檢查Gearman的運行狀況:
/etc/init.d/gearman-job-server status
* gearmand is running
說明Gearman已經安裝成功。
PHP的Gearman擴展可以通過pecl直接安裝
pecl install gearman
echo "extension=gearman.so">/etc/php5/conf.d/gearman.ini
service php5-fpm restart
但是實測發現ubuntu默認安裝的gearman版本過低,直接運行pecl install gearman會報錯
configure: error: libgearman version 1.1.0or later required
因此Gearman + PHP擴展建議通過編譯方式安裝,這里為了簡單說明,選擇安裝舊版本擴展:
pecl install gearman-1.0.3
Gearman + PHP實例
為了更容易理解後文Gearman的運行流程,這里不妨從一個最簡單的Gearman實例來說明,比如要進行一個文件處理的操作,首先編寫一個Gearman Client並命名為client.php:
<?php
$client =newGearmanClient();
$client->addServer();
$client->doBackground('writeLog','Log content');
echo '文件已經在後台操作';
運行這個文件,相當於模擬用戶請求一個Web頁面後,將處理結束的信息返回用戶:
php client.php
查看一下Gearman的狀況:
(echo status ; sleep 0.1)| netcat127.0.0.14730
可以看到輸出為
writeLog 100.
說明已經在Gearman中建立了一個名為writeLog的任務,並且有1個任務在隊列等待中。
而上面的4列分別代表當前的Gearman的運行狀態:
任務名稱
在等待隊列中的任務
正在運行的任務
正在運行的Worker進程
可以使用watch進行實時監控:
watch -n 1"(echo status; sleep 0.1) | nc 127.0.0.1 4730"
然後我們需要編寫一個Gearman Worker命名為worker.php:
<?php
$worker =newGearmanWorker();
$worker->addServer();
$worker->addFunction('writeLog','writeLog');while($worker->work());function writeLog($job){
$log = $job->workload();file_put_contents(__DIR__ .'/gearman.log', $log ." ", FILE_APPEND | LOCK_EX);}
Worker使用一個while死循環實現守護進程,運行
php worker.php
可以看到Gearman狀態變為:
writeLog 001
同時查看同目錄下gearman.log,內容應為從Client傳入的值Log content。
通過MySQL UDF + Trigger同步數據到Gearman
MySQL要實現與外部程序互通的最好方式還是通過MySQL UDF(MySQL user defined functions)來實現。為了讓MySQL能將數據傳入Gearman,這里使用了lib_mysqludf_json和gearman-mysql-udf的組合。
安裝lib_mysqludf_json
使用lib_mysqludf_json的原因是因為Gearman只接受字元串作為入口參數,可以通過lib_mysqludf_json將MySQL中的數據編碼為JSON字元串
apt-get install libmysqlclient-dev
wget https://github.com/mysqludf/lib_mysqludf_json/archive/master.zip
unzip master.zip
cd lib_mysqludf_json-master/
rm lib_mysqludf_json.so
gcc $(mysql_config --cflags)-shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
可以看到重新編譯生成了 lib_mysqludf_json.so 文件,此時需要查看MySQL的插件安裝路徑:
mysql -u root -pPASSWORD --execute="show variables like '%plugin%';"+---------------+------------------------+|Variable_name|Value|+---------------+------------------------+| plugin_dir |/usr/lib/mysql/plugin/|+---------------+------------------------+
然後將 lib_mysqludf_json.so 文件復制到對應位置:
cp lib_mysqludf_json.so /usr/lib/mysql/plugin/
最後登入MySQL運行語句注冊UDF函數:
CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so';
安裝gearman-mysql-udf
方法幾乎一樣:
apt-get install libgearman-dev
wget https://launchpad.net/gearman-mysql-udf/trunk/0.6/+download/gearman-mysql-udf-0.6.tar.gz
tar -xzf gearman-mysql-udf-0.6.tar.gz
cd gearman-mysql-udf-0.6./configure --with-mysql=/usr/bin/mysql_config
-libdir=/usr/lib/mysql/plugin/
make && make install
登入MySQL運行語句注冊UDF函數:
CREATE FUNCTION gman_do_background RETURNS STRING SONAME 'libgearman_mysql_udf.so';
CREATE FUNCTION gman_servers_set RETURNS STRING SONAME 'libgearman_mysql_udf.so';
最後指定Gearman伺服器的信息:
SELECT gman_servers_set('127.0.0.1:4730');
通過MySQL觸發器實現數據同步
最終同步哪些數據,同步的條件,還是需要根據實際情況決定,比如將數據表data的數據在每次更新時同步,那麼編寫Trigger如下:
DELIMITER $$
CREATE TRIGGER datatoredis AFTER UPDATE ON data
FOR EACH ROW BEGIN
SET @ret=gman_do_background('syncToRedis', json_object(NEW.id as`id`, NEW.volume as`volume`));END$$
DELIMITER ;
嘗試在資料庫中更新一條數據查看Gearman是否生效。
Gearman PHP Worker將MySQL數據非同步復制到Redis
Redis作為時下當熱的NoSQL緩存解決方案無需過多介紹,其安裝及使用也非常簡單:
apt-get install redis-server
pecl install redis
echo "extension=redis.so">/etc/php5/conf.d/redis.ini
然後編寫一個Gearman Worker:redis_worker.php
#!/usr/bin/env php<?
$worker =newGearmanWorker();
$worker->addServer();
$worker->addFunction('syncToRedis','syncToRedis');
$redis =newRedis();
$redis->connect('127.0.0.1',6379);while($worker->work());function syncToRedis($job){global $redis;
$workString = $job->workload();
$work = json_decode($workString);if(!isset($work->id)){returnfalse;}
$redis->set($work->id, $workString);}
最後需要將Worker在後台運行:
nohup php redis_worker.php &
通過這種方式將MySQL數據復制到Redis,經測試單Worker基本可以瞬時完成。
『叄』 tomcat,apache,nginx,php,redis,memcached,lvs-keeplived是什麼意思
Tomcat 伺服器是一個免費的開放源代碼的Web 應用伺服器,屬於輕量級應用伺服器,在中小型系統和並發訪問用戶不是很多的場合下被普遍使用,是開發和調試JSP 程序的首選。
Apache是世界使用排名第一的Web伺服器軟體。它可以運行在幾乎所有廣泛使用的計算機平台上,由於其跨平台和安全性被廣泛使用,是最流行的Web伺服器端軟體之一。它快速、可靠並且可通過簡單的API擴充,將Perl/Python等解釋器編譯到伺服器中。
Nginx是一款輕量級的Web 伺服器/反向代理伺服器及電子郵件(IMAP/POP3)代理伺服器,並在一個BSD-like 協議下發行。
PHP(外文名:PHP: Hypertext Preprocessor,中文名:「超文本預處理器」)是一種通用開源腳本語言。
Redis是一個開源的使用ANSI C語言編寫、支持網路、可基於內存亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。
Memcached 是一個高性能的分布式內存對象緩存系統,用於動態Web應用以減輕資料庫負載。它通過在內存中緩存數據和對象來減少讀取資料庫的次數,從而提高動態、資料庫驅動網站的速度。Memcached基於一個存儲鍵/值對的hashmap。其守護進程(daemon )是用C寫的,但是客戶端可以用任何語言來編寫,並通過memcached協議與守護進程通信。
LVS是Linux Virtual Server的簡寫,意即Linux虛擬伺服器,是一個虛擬的伺服器集群系統。
Keepalived的作用是檢測伺服器的狀態,如果有一台web伺服器死機,或工作出現故障,Keepalived將檢測到,並將有故障的伺服器從系統中剔除,同時使用其他伺服器代替該伺服器的工作,當伺服器工作正常後Keepalived自動將伺服器加入到伺服器群中,這些工作全部自動完成,不需要人工干涉,需要人工做的只是修復故障的伺服器。
『肆』 zabbix,redis,nginx三者有什麼關系,分別同做什麼語言的伺服器例如:php等,最近被這三個東西搞得很暈
zabbix:是一套伺服器性能監控軟體,這個沒怎麼用過,沒有發言權。
redis:你可以當成是資料庫,和MYSQL差不多(實際上差很多)
nginx:是一個web 伺服器,提供網頁服務(如果它壞了,用戶輸入域名就不能正常訪問網站)
memcached:基於內存的分布式緩存系統,是redis的長江前浪。
這幾個東西和PHP都沒關系,但可以這樣理解:
nginx 可以做php的WEB伺服器
redis 可以做php的資料庫或緩存
memcached 可以做PHP的緩存
zabbix 既然能監控伺服器性能,能把他們全都監控起來?
『伍』 redis是怎麼分布式緩存數據的
Redis使用單線程的IO復用模型,自己封裝了一個簡單的AeEvent事件處理框架,主要實現了epoll、kqueue和select,對於單純只有IO操作來說,單線程可以將速度優勢發揮到最大,但是Redis也提供了一些簡單的計算功能
比如排序、聚合等,對於這些操作,單線程模型實際會嚴重影響整體吞吐量,CPU計算過程中,整個IO調度都是被阻塞住的。
『陸』 redis到底是個什麼東西
1. 什麼是Redis
Redis是由義大利人Salvatore Sanfilippo(網名:antirez)開發的一款內存高速緩存資料庫。Redis全稱為:Remote Dictionary Server(遠程數據服務),該軟體使用C語言編寫,Redis是一個key-value存儲系統,它支持豐富的數據類型,如:string、list、set、zset(sorted set)、hash。
2. Redis特點
Redis以內存作為數據存儲介質,所以讀寫數據的效率極高,遠遠超過資料庫。以設置和獲取一個256位元組字元串為例,它的讀取速度可高達110000次/s,寫速度高達81000次/s。
Redis跟memcache不同的是,儲存在Redis中的數據是持久化的,斷電或重啟後,數據也不會丟失。因為Redis的存儲分為內存存儲、磁碟存儲和log文件三部分,重啟後,Redis可以從磁碟重新將數據載入到內存中,這些可以通過配置文件對其進行配置,正因為這樣,Redis才能實現持久化。
Redis支持主從模式,可以配置集群,這樣更利於支撐起大型的項目,這也是Redis的一大亮點。
3. Redis應用場景,它能做什麼
眾多語言都支持Redis,因為Redis交換數據快,所以在伺服器中常用來存儲一些需要頻繁調取的數據,這樣可以大大節省系統直接讀取磁碟來獲得數據的I/O開銷,更重要的是可以極大提升速度。
拿大型網站來舉個例子,比如a網站首頁一天有100萬人訪問,其中有一個板塊為推薦新聞。要是直接從資料庫查詢,那麼一天就要多消耗100萬次資料庫請求。上面已經說過,Redis支持豐富的數據類型,所以這完全可以用Redis來完成,將這種熱點數據存到Redis(內存)中,要用的時候,直接從內存取,極大的提高了速度和節約了伺服器的開銷。
總之,Redis的應用是非常廣泛的,而且極有價值,真是伺服器中的一件利器,所以從現在開始,我們就來一步步學好它。
『柒』 php 用 redis做隊列 運行過程是什麼樣的
Reids是一個比較高級的開源key-value存儲系統,採用ANSI C實現。其與memcached類似,但是支持持久化數據存儲入隊操作
復制代碼 代碼如下:
<?php
$redis = new Redis();
$redis->connect('127.0.0.1',6379);
while(True){
try{
$value = 'value_'.date('Y-m-d H:i:s');
$redis->LPUSH('key1',$value);
sleep(rand()%3);
echo $value."\n";
}catch(Exception $e){
echo $e->getMessage()."\n";
}
}
?>
出隊操作
復制代碼 代碼如下:
<?php
$redis = new Redis();
$redis->pconnect('127.0.0.1',6379);
while(True){
try{
echo $redis->LPOP('key1')."\n";
}catch(Exception $e){
echo $e->getMessage()."\n";
}
sleep(rand()%3);
}?>
如何使用Redis 做隊列操作
Reids是一個比較高級的開源key-value存儲系統,採用ANSI C實現。其與memcached類似,但是支持持久化數據存儲,同時value支持多種類型:字元串 (同memcached中的value),列表 ,集合 (Set),有序集合 (OrderSet)和Hash 。所有的值類型均支持原子操作,如列表中追加彈出元素,集合中插入移除元素等。Rdids的數據大部分位於內存中,其讀寫效率非常高,其提供AOF(追加 式操作記錄文件)和DUMP(定期數據備份)兩種持久化方式。Redis支持自定義的VM(虛擬內存)機制,當數據容量超過內存時,可以將部分Value 存儲到文件中。同時Redis支持Master-Slave機制,可以進行數據復制。
可以把Redis的list結構當隊列來用.
從上面Redis的場景和作用來說,對於我們現在的開發活動,究竟能把Redis引入在那些場景,而不是把這么好的東東演變成「為了使用Redis,而Redis」的慘烈局面呢?當然,具體問題具體分析,這個真的很重要哈。
緩存?分布式緩存?
隊列?分布式隊列?
某些系統應用(例如,電信、銀行和大型互聯網應用等)都會使用到,當然,現在大行其道的memcache就是很好的證明;但從某一方面來說,memcache是否能把兩張囊括其中,而且能做到更好(沒有實際的應用過,所以只是拋出)。但從Redis身上,我就能感覺到,Redis,就能把隊列和緩存兩張都囊括其中,而且都不會產生並發環境下的困擾,因為Redis中的操作都是原子操作來著。
至於評論兩者的孰好孰壞就免了,存在就是理由,選擇適合的就是最好的。
下面開始玩玩Redis中的隊列(分布式)設計YY吧,請大蝦們多多指點。
狀況場景:
現在的項目,都是部署在多個伺服器,或者多個IP上,而且前台經由F5分發,所以用戶的請求究竟落在那一台的伺服器上,是無法確定的。對於項目中,有一秒殺設計,剛開始沒有考慮到這種部署,同時也是使用最容易處理的方式,直接給資料庫表鎖行記錄(Oracle上的)。可以說,對於不同的應用部署,而只有一台資料庫伺服器來說,很「輕松」的就解決了這個並發的問題。所以現在考慮一下,是不是挪到應用上,避免資料庫伺服器也摻雜到業務上。
比如,現在有2台應用伺服器,1台資料庫伺服器。想法是,把Redis部署在資料庫伺服器上,兩台伺服器在操作並發緩存或者隊列時,先從Redis伺服器上,取得在兩台應用伺服器的代理對象,再做入列出列的操作。
看代碼實現(PHP)
入隊列操作文件 list_push.php
復制代碼 代碼如下:
<?php
$redis = getRedisInstance();//從Redis伺服器拿到redis實例$redis->connect('Redis伺服器IP', 6379);
while (true) {
$redis->lPush('list1', 'A_'.date('Y-m-d H:i:s'));sleep(rand()%3);
}
?>
執行# php list_push.php &
出隊列操作 list_pop.php文件
復制代碼 代碼如下:
<?php
$redis = getRedisInstance();//從Redis伺服器拿到redis實例$redis->pconnect('Redis伺服器IP', 6379);
while(true) {
try {
var_export( $redis->blPop('list1', 10) );} catch(Exception $e) {
//echo $e;
}
}
實現方法(Python)
1.入隊列(write.py)
復制代碼 代碼如下:
#!/usr/bin/env python
import time
from redis import Redis
redis = Redis(host='127.0.0.1', port=6379)while True:
now = time.strftime("%Y/%m/%d %H:%M:%S")
redis.lpush('test_queue', now)
time.sleep(1)
2.出隊列(read.py)
復制代碼 代碼如下:
#!/usr/bin/env python
import sys
from redis import Redis
redis = Redis(host='127.0.0.1', port=6379)while True:
res = redis.rpop('test_queue')
if res == None:
pass
else:
print str(res)
『捌』 php面試題 memcache和redis的區別
Redis與Memcached的區別傳統MySQL+ Memcached架構遇到的問題實際MySQL是適合進行海量數據存儲的,通過Memcached將熱點數據載入到cache,加速訪問,很多公司都曾經使用過這樣的架構,但隨著業務數據量的不斷增加,和訪問量的持續增長,我們遇到了很多問題:1.MySQL需要不斷進行拆庫拆表,Memcached也需不斷跟著擴容,擴容和維護工作占據大量開發時間。2.Memcached與MySQL資料庫數據一致性問題。3.Memcached數據命中率低或down機,大量訪問直接穿透到DB,MySQL無法支撐。4.跨機房cache同步問題。眾多NoSQL百花齊放,如何選擇最近幾年,業界不斷涌現出很多各種各樣的NoSQL產品,那麼如何才能正確地使用好這些產品,最大化地發揮其長處,是我們需要深入研究和思考的問題,實際歸根結底最重要的是了解這些產品的定位,並且了解到每款產品的tradeoffs,在實際應用中做到揚長避短,總體上這些NoSQL主要用於解決以下幾種問題1.少量數據存儲,高速讀寫訪問。此類產品通過數據全部in-momery 的方式來保證高速訪問,同時提供數據落地的功能,實際這正是Redis最主要的適用場景。2.海量數據存儲,分布式系統支持,數據一致性保證,方便的集群節點添加/刪除。3.這方面最具代表性的是dynamo和bigtable 2篇論文所闡述的思路。前者是一個完全無中心的設計,節點之間通過gossip方式傳遞集群信息,數據保證最終一致性,後者是一個中心化的方案設計,通過類似一個分布式鎖服務來保證強一致性,數據寫入先寫內存和redo log,然後定期compat歸並到磁碟上,將隨機寫優化為順序寫,提高寫入性能。4.Schema free,auto-sharding等。比如目前常見的一些文檔資料庫都是支持schema-free的,直接存儲json格式數據,並且支持auto-sharding等功能,比如mongodb。面對這些不同類型的NoSQL產品,我們需要根據我們的業務場景選擇最合適的產品。Redis適用場景,如何正確的使用前面已經分析過,Redis最適合所有數據in-momory的場景,雖然Redis也提供持久化功能,但實際更多的是一個disk-backed的功能,跟傳統意義上的持久化有比較大的差別,那麼可能大家就會有疑問,似乎Redis更像一個加強版的Memcached,那麼何時使用Memcached,何時使用Redis呢?如果簡單地比較Redis與Memcached的區別,大多數都會得到以下觀點:1 Redis不僅僅支持簡單的k/v類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。2 Redis支持數據的備份,即master-slave模式的數據備份。3 Redis支持數據的持久化,可以將內存中的數據保持在磁碟中,重啟的時候可以再次載入進行使用。拋開這些,可以深入到Redis內部構造去觀察更加本質的區別,理解Redis的設計。在Redis中,並不是所有的數據都一直存儲在內存中的。這是和Memcached相比一個最大的區別。Redis只會緩存所有的 key的信息,如果Redis發現內存的使用量超過了某一個閥值,將觸發swap的操作,Redis根據「swappability = age*log(size_in_memory)」計 算出哪些key對應的value需要swap到磁碟。然後再將這些key對應的value持久化到磁碟中,同時在內存中清除。這種特性使得Redis可以 保持超過其機器本身內存大小的數據。當然,機器本身的內存必須要能夠保持所有的key,畢竟這些數據是不會進行swap操作的。同時由於Redis將內存 中的數據swap到磁碟中的時候,提供服務的主線程和進行swap操作的子線程會共享這部分內存,所以如果更新需要swap的數據,Redis將阻塞這個 操作,直到子線程完成swap操作後才可以進行修改。使用Redis特有內存模型前後的情況對比:VM off: 300k keys, 4096 bytes values: 1.3G usedVM on: 300k keys, 4096 bytes values: 73M usedVM off: 1 million keys, 256 bytes values: 430.12M usedVM on: 1 million keys, 256 bytes values: 160.09M usedVM on: 1 million keys, values as large as you want, still: 160.09M used當 從Redis中讀取數據的時候,如果讀取的key對應的value不在內存中,那麼Redis就需要從swap文件中載入相應數據,然後再返回給請求方。 這里就存在一個I/O線程池的問題。在默認的情況下,Redis會出現阻塞,即完成所有的swap文件載入後才會相應。這種策略在客戶端的數量較小,進行 批量操作的時候比較合適。但是如果將Redis應用在一個大型的網站應用程序中,這顯然是無法滿足大並發的情況的。所以Redis運行我們設置I/O線程 池的大小,對需要從swap文件中載入相應數據的讀取請求進行並發操作,減少阻塞的時間。如果希望在海量數據的環境中使用好Redis,我相信理解Redis的內存設計和阻塞的情況是不可缺少的。補充的知識點:memcached和redis的比較1 網路IO模型Memcached是多線程,非阻塞IO復用的網路模型,分為監聽主線程和worker子線程,監聽線程監聽網路連接,接受請求後,將連接描述字pipe 傳遞給worker線程,進行讀寫IO, 網路層使用libevent封裝的事件庫,多線程模型可以發揮多核作用,但是引入了cache coherency和鎖的問題,比如,Memcached最常用的stats 命令,實際Memcached所有操作都要對這個全局變數加鎖,進行計數等工作,帶來了性能損耗。(Memcached網路IO模型)Redis使用單線程的IO復用模型,自己封裝了一個簡單的AeEvent事件處理框架,主要實現了epoll、kqueue和select,對於單純只有IO操作來說,單線程可以將速度優勢發揮到最大,但是Redis也提供了一些簡單的計算功能,比如排序、聚合等,對於這些操作,單線程模型實際會嚴重影響整體吞吐量,CPU計算過程中,整個IO調度都是被阻塞住的。2.內存管理方面Memcached使用預分配的內存池的方式,使用slab和大小不同的chunk來管理內存,Item根據大小選擇合適的chunk存儲,內存池的方式可以省去申請/釋放內存的開銷,並且能減小內存碎片產生,但這種方式也會帶來一定程度上的空間浪費,並且在內存仍然有很大空間時,新的數據也可能會被剔除,原因可以參考Timyang的文章:/memcached/)。Memcached的客戶端軟體實現非常多,包括C/C++, PHP, Java, Python, Ruby, Perl, Erlang, Lua等。當前Memcached使用廣泛,除了LiveJournal以外還有Wikipedia、Flickr、Twitter、Youtube和WordPress等。在Window系統下,Memcached的安裝非常方便,只需從以上給出的地址下載可執行軟體然後運行memcached.exe –d install即可完成安裝。在Linux等系統下,我們首先需要安裝libevent,然後從獲取源碼,make && make install即可。默認情況下,Memcached的伺服器啟動程序會安裝到/usr/local/bin目錄下。在啟動Memcached時,我們可以為其配置不同的啟動參數。1.1 Memcache配置Memcached伺服器在啟動時需要對關鍵的參數進行配置,下面我們就看一看Memcached在啟動時需要設定哪些關鍵參數以及這些參數的作用。1)-p Memcached的TCP監聽埠,預設配置為11211;2)-U Memcached的UDP監聽埠,預設配置為11211,為0時表示關閉UDP監聽;3)-s Memcached監聽的UNIX套接字路徑;4)-a 訪問UNIX套接字的八進制掩碼,預設配置為0700;5)-l 監聽的伺服器IP地址,默認為所有網卡;6)-d 為Memcached伺服器啟動守護進程;7)-r 最大core文件大小;8)-u 運行Memcached的用戶,如果當前為root的話需要使用此參數指定用戶;9)-m 分配給Memcached使用的內存數量,單位是MB;10)-M 指示Memcached在內存用光的時候返回錯誤而不是使用LRU演算法移除數據記錄;11)-c 最大並發連數,預設配置為1024;12)-v –vv –vvv 設定伺服器端列印的消息的詳細程度,其中-v僅列印錯誤和警告信息,-vv在-v的基礎上還會列印客戶端的命令和相應,-vvv在-vv的基礎上還會列印內存狀態轉換信息;13)-f 用於設置chunk大小的遞增因子;14)-n 最小的chunk大小,預設配置為48個位元組;15)-t Memcached伺服器使用的線程數,預設配置為4個;16)-L 嘗試使用大內存頁;17)-R 每個事件的最大請求數,預設配置為20個;18)-C 禁用CAS,CAS模式會帶來8個位元組的冗餘;2. Redis簡介Redis是一個開源的key-value存儲系統。與Memcached類似,Redis將大部分數據存儲在內存中,支持的數據類型包括:字元串、哈希表、鏈表、集合、有序集合以及基於這些數據類型的相關操作。Redis使用C語言開發,在大多數像Linux、BSD和Solaris等POSIX系統上無需任何外部依賴就可以使用。Redis支持的客戶端語言也非常豐富,常用的計算機語言如C、C#、C++、Object-C、PHP、Python、Java、Perl、Lua、Erlang等均有可用的客戶端來訪問Redis伺服器。當前Redis的應用已經非常廣泛,國內像新浪、淘寶,國外像Flickr、Github等均在使用Redis的緩存服務。Redis的安裝非常方便,只需從bin目錄下。在啟動Redis伺服器時,我們需要為其指定一個配置文件,預設情況下配置文件在Redis的源碼目錄下,文件名為redis.conf。php面試題 memcache和redis的區別