❶ linux上怎麼配置redis的aof持久化
Redis 持久化和配置文件
Reids 持久化
Redis提供了兩種持久化的方式,分別是RDB(Redis DataBase)和AOF(Append Only File)。
RDB,簡而言之,就是在不同的時間點,將redis存儲的數據生成快照並存儲到磁碟等介質上。
AOF,則是換了一個角度來實現持久化,那就是將redis執行過的所有寫指令記錄下來,在下次redis重新啟動時,只要把這些寫指令從前到後再重復執行一遍,就可以實現數據恢復了。
其實RDB和AOF兩種方式也可以同時使用,在這種情況下,如果redis重啟的話,則會優先採用AOF方式來進行數據恢復,這是因為AOF方式的數據恢復完整度更高。
如果你沒有數據持久化的需求,也完全可以關閉RDB和AOF方式,這樣的話,redis將變成一個純內存資料庫,就像memcache一樣。
redis配置文件
daemonize no # 默認情況下,redis並不是以daemon形式來運行的。通過daemonize配置項可以控制redis的運行形式
pidfile /path/to/redis.pid #當以daemon形式運行時,redis會生成一個pid文件,默認會生成在/var/run/redis.pid
bind 192.168.1.2 10.8.4.2 # 指定綁定的ip,可以有多個
port 6379 #指定監聽埠
unixsocket /tmp/redis.sock #也可以監聽socket
unixsocketperm 755 #當監聽socket時可以指定許可權為755
timeout 0 #當一個redis-client一直沒有請求發向server端,那麼server端有權主動關閉這個連接,可以通過timeout來設置「空閑超時時限」,0表示永不關閉。
Redis通用配置
tcp-keepalive0 #TCP連接保活策略,可以通過tcp-keepalive配置項來進行設置,單位為秒,假如設置為60秒,則server端會每60秒向連接空閑的客戶端發起一次ACK請求,以檢查客戶端是否已經掛掉,對於無響應的客戶端則會關閉其連接。如果設置為0,則不會進行保活檢測。
loglevelnotice #日誌級別,有四種debug, verbose, notice, warning
logfile「」 #定義日誌路徑,
syslog-identredis #如果希望日誌列印到syslog中,通過syslog-enabled來控制。另外,syslog-ident還可以讓你指定syslog里的日誌標志。
syslog-facility local0 #指定syslog的設備,可以是USER或者local0-local7
databases 16 #設置資料庫的總數量
Redis快照配置(rdb持久化)
save 900 1 #表示每15分鍾且至少有1個key改變,就觸發一次持久化
save 300 10 #表示每5分鍾且至少有10個key改變,就觸發一次持久化
save 60 10000 #表示每60秒至少有10000個key改變,就觸發一次持久
save 「」 #這樣可以禁用rdb持久化
stop-writes-on-bgsave-error yes #rdb持久化寫入磁碟避免不了會出現失敗的情況,默認一旦出現失敗,redis會馬上停止寫操作。如果你覺得無所謂,那就可以使用該選項關閉這個功能。
rdbcompressionyes #是否要壓縮
rdbchecksumyes #是否進行數據校驗
dbfilenamemp.rdb #定義快照文件的名字
dir ./ #定義快照文件儲存路勁
Redis安全相關配置
requirepassaminglinux
#設置redis-server的密碼
rename-command CONFIG aminglinux.config
#將CONFIG命令更名為aminglinux.config,這樣可以避免誤操作,但如果使用了AOF持久化,建議不要啟用該功能
rename-command CONFIG 「」
#也可以後面定義為空,這樣就禁掉了該CONFIG命令
Redis限制相關配置
maxclients10000 #限制最大客戶端連接數
maxmemory<bytes> #設定最大內存使用數,單位是byte
maxmemory-policy volatile-lru#指定內存移除規則
maxmemory-samples 3 #LRU演算法和最小TTL演算法都並非是精確的演算法,而是估算值。所以你可以設置樣本的大小。假如redis默認會檢查三個key並選擇其中LRU的那個,那麼你可以改變這個key樣本的數量。
Redis AOF持久化相關配置
appendonlyno #如果是no,則開啟aof持久化
appendfilename「appendonly.aof」 #指定aof文件名字
appendfsynceverysec#指定fsync()調用模式,有三種no(不調用fsync),always(每次寫都會調用fsync),everysec(每秒鍾調用一次fsync)。第一種最快,第二種數據最安全,但性能會差一些,第三種為這種方案,默認為第三種。
no-appendfsync-on-rewrite no #使用no,可以避免當寫入量非常大時的磁碟io阻塞
auto-aof-rewrite-percentage 10 #規定什麼情況下會觸發aof重寫。該值為一個比例,10表示當aof文件增幅達到10%時則會觸發重寫機制。
auto-aof-rewrite-min-size 64mb #重寫會有一個條件,就是不能低於64Mb
Redis 慢日誌相關配置
針對慢日誌,你可以設置兩個參數,一個是執行時長,單位是微秒,另一個是慢日誌的長度。當一個新的命令被寫入日誌時,最老的一條會從命令日誌隊列中被移除。
❷ php redis如何使用
開始在
PHP
中使用
Redis
前,要確保已經安裝了
redis
服務及
PHP
redis
驅動,且你的機器上能正常使用
PHP。
PHP安裝redis擴展
/usr/local/php/bin/phpize
#php安裝後的路徑
./configure
--with-php-config=/usr/local/php/bin/php-config
make
&&
make
install
修改php.ini文件
vi
/usr/local/php/lib/php.ini
增加如下內容:
extension_dir
=
"/usr/local/php/lib/php/extensions/no-debug-zts-20090626"
extension=redis.so
安裝完成後重啟php-fpm
或
apache。查看phpinfo信息,就能看到redis擴展。
連接到
redis
服務
<?php
//連接本地的
Redis
服務
$redis
=
new
Redis();
$redis->connect('127.0.0.1',
6379);
echo
"Connection
to
server
sucessfully";
//查看服務是否運行
echo
"Server
is
running:
"
.
$redis->ping();
?>
執行腳本,輸出結果為:
Connection
to
server
sucessfully
Server
is
running:
PONG
Redis
PHP
String(字元串)
實例
<?php
//連接本地的
Redis
服務
$redis
=
new
Redis();
$redis->connect('127.0.0.1',
6379);
echo
"Connection
to
server
sucessfully";
//設置
redis
字元串數據
$redis->set("tutorial-name",
"Redis
tutorial");
//
獲取存儲的數據並輸出
echo
"Stored
string
in
redis::
"
.
jedis.get("tutorial-name");
?>
執行腳本,輸出結果為:
Connection
to
server
sucessfully
Stored
string
in
redis::
Redis
tutorial
Redis
PHP
List(列表)
實例
<?php
//連接本地的
Redis
服務
$redis
=
new
Redis();
$redis->connect('127.0.0.1',
6379);
echo
"Connection
to
server
sucessfully";
//存儲數據到列表中
$redis->lpush("tutorial-list",
"Redis");
$redis->lpush("tutorial-list",
"Mongodb");
$redis->lpush("tutorial-list",
"Mysql");
//
獲取存儲的數據並輸出
$arList
=
$redis->lrange("tutorial-list",
0
,5);
echo
"Stored
string
in
redis::
"
print_r($arList);
?>
執行腳本,輸出結果為:
Connection
to
server
sucessfully
Stored
string
in
redis::
Redis
Mongodb
Mysql
Redis
PHP
Keys
實例
<?php
//連接本地的
Redis
服務
$redis
=
new
Redis();
$redis->connect('127.0.0.1',
6379);
echo
"Connection
to
server
sucessfully";
//
獲取數據並輸出
$arList
=
$redis->keys("*");
echo
"Stored
keys
in
redis::
"
print_r($arList);
?>
執行腳本,輸出結果為:
Connection
to
server
sucessfully
Stored
string
in
redis::
tutorial-name
tutorial-list
❸ PHP操作redis如何設置有效期
自己寫方法對比呀 寫入的時候加時間戳,然後定時幹掉超時的
❹ redis可以默認並發多少
redis並發問題
redis中的並發問題
使用redis作為緩存已經很久了,redis是以單進程的形式運行的,命令是一個接著一個執行的,一直以為不會存在並發的問題,直到今天看到相關的資料,才恍然大悟~~
具體問題實例
有個鍵,假設名稱為myNum,裡面保存的是阿拉伯數字,假設現在值為1,存在多個連接對myNum進行操作的情況,這個時候就會有並發的問題。假設有兩個連接linkA和linkB,這兩個連接都執行下面的操作,取出myNum的值,+1,然後再存回去,看看下面的交互:
linkA get myNum => 1linkB get myNum => 1linkA set muNum => 2linkB set myNum => 2
執行完操作之後,結果可能是2,這和我們預期的3不一致。
再看一個具體的例子:
<?phprequire "vendor/autoload.php";$client = new Predis\Client([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,]);for ($i = 0; $i < 1000; $i++) { $num = intval($client->get("name"));
$num = $num + 1;
$client->setex("name", $num, 10080);
usleep(10000);}
設置name初始值為0,然後同時用兩個終端執行上面的程序,最後name的值可能不是2000,而是一個<2000的值,這也就證明了我們上面的並發問題的存在,這個該怎麼解決呢?
redis中的事務
redis中也是有事務的,不過這個事務沒有mysql中的完善,只保證了一致性和隔離性,不滿足原子性和持久性。
redis事務使用multi、exec命令
原子性,redis會將事務中的所有命令執行一遍,哪怕是中間有執行失敗也不會回滾。kill信號、宿主機宕機等導致事務執行失敗,redis也不會進行重試或者回滾。
持久性,redis事務的持久性依賴於redis所使用的持久化模式,遺憾的是各種持久化模式也都不是持久化的。
隔離性,redis是單進程,開啟事務之後,會執行完當前連接的所有命令直到遇到exec命令,才處理其他連接的命令。
一致性,看了文檔,覺得挺扯的,但是貌似說的沒有問題。
redis中的事務不支持原子性,所以解決不了上面的問題。
當然了redis還有一個watch命令,這個命令可以解決這個問題,看下面的例子,對一個鍵執行watch,然後執行事務,由於watch的存在,他會監測鍵a,當a被修該之後,後面的事務就會執行失敗,這就確保了多個連接同時來了,都監測著a,只有一個能執行成功,其他都返回失敗。
127.0.0.1:6379> set a 1OK127.0.0.1:6379> watch aOK127.0.0.1:6379> multi OK127.0.0.1:6379> incr aQUEUED127.0.0.1:6379> exec1) (integer) 2
127.0.0.1:6379> get a"2"
失敗時候的例子,從最後可以看出,test的值被其他連接修改了:
127.0.0.1:6379> set test 1OK127.0.0.1:6379> watch testOK127.0.0.1:6379> multiOK127.0.0.1:6379> incrby test 11QUEUED127.0.0.1:6379> exec(nil)
127.0.0.1:6379> get test"100"
我的問題如何解決
redis中命令是滿足原子性的,因此在值為阿拉伯數字的時候,我可以將get和set命令修改為incr或者incrby來解決這個問題,下面的代碼開啟兩個終端同時執行,得到的結果是滿足我們預期的2000。
<?phprequire "vendor/autoload.php";$client = new Predis\Client([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,]);for ($i = 0; $i < 1000; $i++) { $client->incr("name");
$client->expire("name", 10800);
usleep(10000);}
@manzilu 提到的方法
評論中manzilu提到的方法查了下資料,確實可行,效果還不錯,這里寫了個例子
<?phprequire "vendor/autoload.php";$client = new Predis\Client([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,]);class RedisLock{ public $objRedis = null;
public $timeout = 3;
/** * @desc 設置redis實例 * * @param obj object | redis實例 */
public function __construct($obj)
{ $this->objRedis = $obj;
} /** * @desc 獲取鎖鍵名 */
public function getLockCacheKey($key)
{ return "lock_{$key}";
} /** * @desc 獲取鎖 * * @param key string | 要上鎖的鍵名 * @param timeout int | 上鎖時間 */
public function getLock($key, $timeout = NULL)
{ $timeout = $timeout ? $timeout : $this->timeout;
$lockCacheKey = $this->getLockCacheKey($key);
$expireAt = time() + $timeout;
$isGet = (bool)$this->objRedis->setnx($lockCacheKey, $expireAt);
if ($isGet) { return $expireAt;
} while (1) { usleep(10);
$time = time();
$oldExpire = $this->objRedis->get($lockCacheKey);
if ($oldExpire >= $time) { continue;
} $newExpire = $time + $timeout;
$expireAt = $this->objRedis->getset($lockCacheKey, $newExpire);
if ($oldExpire != $expireAt) { continue;
} $isGet = $newExpire;
break;
} return $isGet;
} /** * @desc 釋放鎖 * * @param key string | 加鎖的欄位 * @param newExpire int | 加鎖的截止時間 * * @return bool | 是否釋放成功 */
public function releaseLock($key, $newExpire)
{ $lockCacheKey = $this->getLockCacheKey($key);
if ($newExpire >= time()) { return $this->objRedis->del($lockCacheKey);
} return true;
}
}$start_time = microtime(true);$lock = new RedisLock($client);$key = "name";for ($i = 0; $i < 10000; $i++) { $newExpire = $lock->getLock($key);
$num = $client->get($key);
$num++;
$client->set($key, $num);
$lock->releaseLock($key, $newExpire);}$end_time = microtime(true);echo "花費時間 : ". ($end_time - $start_time) . "\n";
執行shell php setnx.php & php setnx.php&,最後會得到結果:
$ 花費時間 : 4.3004920482635
[2] + 72356 done php setnx.php# root @ ritoyan-virtual-pc in ~/PHP/redis-high-concurrency [20:23:41] $ 花費時間 : 4.4319710731506
[1] + 72355 done php setnx.php
同樣循環1w次,去掉usleep,使用incr直接進行增加,耗時在2s左右。
而獲取所得時候取消usleep,時間不但沒減少,反而增加了,這個usleep的設置要合理,免得進程做無用的循環
總結
看了這么多,簡單的總結下,其實redis本事是不會存在並發問題的,因為他是單進程的,再多的command都是one by one執行的。我們使用的時候,可能會出現並發問題,比如get和set這一對。
2016-8-22 20:31:30
❺ php中redis和memcached區別和應用場景
redis比memcached功能更多更強大,現在基本都是只用redis了.
利用redis的原子性可以給數據加鎖
可以保存臨時數據,比如簡訊驗證碼和session
可以用於實現簡單的隊列任務
可以實現排行榜功能
可以實現經緯度距離計算
........
當然不止這些,redis是一種key-value資料庫,他的業務場景還可以自己擴展.
❻ 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做隊列 運行過程是什麼樣的
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)
❽ Redis 持久化有幾種方式
Redis 的持久化有兩種策略:
RDB(Redis Database):指定的時間間隔能對你的數據進行快照存儲。
AOF(Append Only File):每一個收到的寫命令都通過write函數追加到文件中。
❾ php 使用redis鎖限制並發訪問類示例
本文介紹了php
使用redis鎖限制並發訪問類,並詳細的介紹了並發訪問限制方法。
1.並發訪問限制問題
對於一些需要限制同一個用戶並發訪問的場景,如果用戶並發請求多次,而伺服器處理沒有加鎖限制,用戶則可以多次請求成功。
例如換領優惠券,如果用戶同一時間並發提交換領碼,在沒有加鎖限制的情況下,用戶則可以使用同一個換領碼同時兌換到多張優惠券。
偽代碼如下:
if
A(可以換領)
B(執行換領)
C(更新為已換領)
D(結束)
如果用戶並發提交換領碼,都能通過可以換領(A)的判斷,因為必須有一個執行換領(B)後,才會更新為已換領(C)。因此如果用戶在有一個更新為已換領之前,有多少次請求,這些請求都可以執行成功。
2.並發訪問限制方法
使用文件鎖可以實現並發訪問限制,但對於分布式架構的環境,使用文件鎖不能保證多台伺服器的並發訪問限制。
Redis是一個開源的使用ANSI
C語言編寫、支持網路、可基於內存亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。
本文將使用其setnx方法實現分布式鎖功能。setnx即Set
it
N**ot
eX**ists。
當鍵值不存在時,插入成功(獲取鎖成功),如果鍵值已經存在,則插入失敗(獲取鎖失敗)
RedisLock.class.PHP
<?php
/**
*
Redis鎖操作類
*
Date:
2016-06-30
*
Author:
fdipzone
*
Ver:
1.0
*
*
Func:
*
public
lock
獲取鎖
*
public
unlock
釋放鎖
*
private
connect
連接
*/
class
RedisLock
{
//
class
start
private
$_config;
private
$_redis;
/**
*
初始化
*
@param
Array
$config
redis連接設定
*/
public
function
__construct($config=array()){
$this->_config
=
$config;
$this->_redis
=
$this->connect();
}
/**
*
獲取鎖
*
@param
String
$key
鎖標識
*
@param
Int
$expire
鎖過期時間
*
@return
Boolean
*/
public
function
lock($key,
$expire=5){
$is_lock
=
$this->_redis->setnx($key,
time()+$expire);
//
不能獲取鎖
if(!$is_lock){
//
判斷鎖是否過期
$lock_time
=
$this->_redis->get($key);
//
鎖已過期,刪除鎖,重新獲取
if(time()>$lock_time){
$this->unlock($key);
$is_lock
=
$this->_redis->setnx($key,
time()+$expire);
}
}
return
$is_lock?
true
:
false;
}
/**
*
釋放鎖
*
@param
String
$key
鎖標識
*
@return
Boolean
*/
public
function
unlock($key){
return
$this->_redis->del($key);
}
/**
*
創建redis連接
*
@return
Link
*/
private
function
connect(){
try{
$redis
=
new
Redis();
$redis->connect($this->_config['host'],$this->_config['port'],$this->_config['timeout'],$this->_config['reserved'],$this->_config['retry_interval']);
if(empty($this->_config['auth'])){
$redis->auth($this->_config['auth']);
}
$redis->select($this->_config['index']);
}catch(RedisException
$e){
throw
new
Exception($e->getMessage());
return
false;
}
return
$redis;
}
}
//
class
end
?>
demo.php
<?php
require
'RedisLock.class.php';
$config
=
array(
'host'
=>
'localhost',
'port'
=>
6379,
'index'
=>
0,
'auth'
=>
'',
'timeout'
=>
1,
'reserved'
=>
NULL,
'retry_interval'
=>
100,
);
//
創建redislock對象
$oRedisLock
=
new
RedisLock($config);
//
定義鎖標識
$key
=
'mylock';
//
獲取鎖
$is_lock
=
$oRedisLock->lock($key,
10);
if($is_lock){
echo
'get
lock
success<br>';
echo
'do
sth..<br>';
sleep(5);
echo
'success<br>';
$oRedisLock->unlock($key);
//
獲取鎖失敗
}else{
echo
'request
too
frequently<br>';
}
?>
測試方法:
打開兩個不同的瀏覽器,同時在A,B中訪問demo.php
如果先訪問的會獲取到鎖
輸出
get
lock
success
do
sth..
success
另一個獲取鎖失敗則會輸出request
too
frequently
保證同一時間只有一個訪問有效,有效限制並發訪問。
為了避免系統突然出錯導致死鎖,所以在獲取鎖的時候增加一個過期時間,如果已超過過期時間,即使是鎖定狀態都會釋放鎖,避免死鎖導致的問題。
源碼下載地址:點擊查看