Redis和memcache

redisnode

1. 性能測試工具(批量寫入) ./bin/redis-benchmark -n 10000 一次性寫入10000條數據
2.使用select 1能夠切換到1號數據庫(共有16個數據庫)。
 
【Redis對於key的操做命令】
keys */?/[]:查詢相應的key;完整匹配:keys site;模糊匹配:keys s*、keys sit[ey]
randomkey:隨機返回key
type key:判斷key的類型 string,set,zset,link,hash
exists key:判斷key是否存在,返回1/0
del key1 key2 ... KeyN :刪除1個或多個鍵
rename key newkey:給key賦一個新的key名,原值被覆蓋
renamenx key newkey:同rename,不覆蓋
move key 2:移動key到2號數據庫
ttl/pttl key:查詢key的剩餘生命週期(秒/毫秒)
expire/pexpire key: 設置key的生命週期(秒/毫秒)
persist key: 設置key永久有效
 
【Redis字符串類型的操做】
set key value [ex]/[px]:多少[秒]/[毫秒]有效。
set key value [nx]/[xx]:設置一個[已存在]/[不存在]的key。
mset:一次性設置多個鍵值,mset key1 v1 key2 v2 ...。
get key: 獲取key的值。
mget key1 key2 ... keyN: 獲取多個key的值。
setrange key offset value:從offset個字符開始替換成value。
append key value:把value追加到key的原值上。
getrange key start stop :獲取[start, stop]範圍。
getset key newvalue :返回舊值並設置新值。
incr/decr key:值加/減1。
incrby/decrby key number:值加/減number。
incrbyfloat key floatnumber:值加浮點值(沒有decrbyfloat)
 
【link 鏈表結構】
lpush/rpush key value: 把值插入到連接頭部/尾部;
lpop/rpop key value: 從連接頭部/尾部刪除值;
lrange key start stop: 返回[start ,stop]的值,所有:0到-1.
lrem key count value: 從key中刪除count個value值
ltrim key start stop: 剪切[start,stop]一段賦給key
lindex key index: 返回index索引上的值。
llen key:計算連接表的元素個數。
linsert key after/before s v: 尋找's'並在其值以前/以後插入v;
rpoplpush source bak: 把source的尾部剪切放在bak的頭部;
brpop/blpop key timeout:等待彈出key的尾/頭元素
 
【set無序集合(集合的性質: 惟一性,無序性,肯定性)】
sadd key value1 value2: 往集合key中增長元素.
scard key : 返回元素個數。
smembers key: 返回全部元素。
srandmember key: 返回隨機的1個元素。
sismember key v: 判斷v是否存在key中,1/0。
srem key v1 v2:刪除值爲v1和v2的元素,返回真正刪除掉的個數。
spop key:返回並刪除集合key中1個隨機元素。
smove key1 key2 value:把key1中的value值移動到key2中。
sinter k1 k2 k3: 求三者的交集而後返回。
sinterstore dest1 k1 k2 k3: 求交集而後賦給dest1。
sunion k1 k2 k3: 求並集而後返回。
sunionstore dest2 k1 k2 k3: 求並集而後賦給dest2。
sdiff k1 k2 k3: 求差集而後返回。
sdiffstore dest3 k1 k2 k3: 求差集而後賦給dest3。
 
【order set 有序集合】
zadd key score1 value1 score2 value2 .. :給有序集合添加元素。
zcard key: 返回元素個數。
zcount key min max:分數在[min,max]區間內元素的數量。
zrange/zrevrange key start stop [WITHSCORES] :集合升序/降序排列後返回名次[start,stop]的元素。所有:[0,-1]。
zrangebyscore/zrevrangebyscore key min max [withscores] [limit offset N]: 分數min和max按照分數升續/降序排序。
zrank/zrevrank key member:升序/降序後查詢member的排名。
zrem key value1 value2... : 刪除集合中的元素。
zremrangebyscore key min max :刪除socre在[min,max]之間的。
zremrangebyrank key start end: 刪除排名在[start,end]之間的。
zinterstore/zunionstore destination numkeys key1 [key2 ...]:取交集/並集。
 
【Hash 哈希數據類型】
hset key field value:把key中filed域的值設爲value。
hget key field:返回key中field域的值。
hgetall key :返回key中全部域與其值。
hmset key field1 value1 [field2 value2...]:設置多個域和值。
hmget key field1 field2: 返回多個域的值。
hlen key:返回key中元素的數量。
hkeys key:返回key中全部的field。
hvals key:返回key中全部的value。
hexists key field:判斷key中有沒有field域。
hincrby/hincrbyfloat key field value:把key中的field域的值增加整型值/浮點值value。
hdel key field:刪除key中field域。
 
【Redis的事務】
Mysql:開啓[start transaction],語句[普通sql],失敗[rollback回滾], 成功[commit].
Redis: 開啓[muitl],語句[普通命令],失敗[discard取消],成功[exec].
watch key1 key2 keyN:監聽key1,key2,keyN有沒有變化,若是有變則事務取消。
unwatch:取消全部watch監聽。
 
【消息訂閱】
訂閱端: Subscribe 頻道名稱。發佈端: publish 頻道名稱 發佈內容。psubscribe 通配符匹配接收。
 
【運維經常使用的server端命令(不區分大小寫)】
time 查看時間戳與微秒數,
dbsize 查看當前庫中的key數量,
BgRewriteAof 後臺進程重寫AOF,
BgSave 後臺保存rdb快照,
save 保存rdb快照,
LastSave 上次保存時間,
SlaveOf 設爲slave服務器,
shutdown[""|save|nosave] 斷開鏈接,關閉服務器,
SlowLog 顯示慢查詢,
config get 獲取配置信息,
config set 設置配置信息,
monitor 打開控制檯,
sync 主從同步,
client list 客戶端列表,
client kill 關閉某個客戶端,
client setname 爲客戶端設置名字,
client getname 獲取客戶端名字,
FlushAll 清空全部db,
FlushDB 清空當前db。
備註:不當心flushall,當即shutdown nosave,編輯aof文件,去掉flushall,而後導入。
 
【info:顯示服務器所有信息】
Memory 內存
Persistence 持久化的信息
Status中的fork耗時
Replication 主從複製的信息
 




 
【開發中Redis的key的設計技巧】
MySQL的user表:id:9|name:lisi|pwd:123;
Redis存儲:set user:id:9:name lisi|set user:id:9:pwd 123;
查詢有哪些字段:keys user:id:9*;
查詢某個字段的值:get user:id:9:name;
要按照name查id:set user:name:lisi:id 9;
 
【Redis實戰】
MySQL的user表:
|userid:9|username:lisi|password:222|email: lisi@163.com|
轉換爲Redis存儲:
set user:userid:9:username lisi
set user:userid:9:password 111111
set user:userid:9:email lisi@163.com
查詢方法
(1)查詢有哪些字段:keys user:userid:9* ,結果以下:
(2)查詢某個字段的值:get user:userid:9:username ===> lisi
注意:冗餘字段
按照username查詢,須要生成一條按照username列爲主的key-value:set user:username:lisi:uid 9
這樣就能夠根據username:lisi:uid ,查出userid=9。 再查user:9:password/email ...
 
【增刪改查分頁完整操做】
使用hash類型存儲數據。hmset:批量添加數據,例如:
$redis->hmset(‘user:1’,array(‘name’=>「renxing」,‘age’=>「28」));
hgetall:獲取全部數據;
del:刪除數據。
$redis->incr("userid"); //設定一個自增的數值,相似於主鍵
$redis->hmset("user:".$uid,array $add_data); //批量添加
$incr_id = $redis->get("uid"); //獲取當前自增的數值
for($i=1;$i<=$incr_id;$i++){
$data[] = $redis->hgetall("user:".$i); //使用hgetall獲取數據
}
$res = $redis->del("user:".$uid); //刪除數據
[分頁操做思路分析] 將全部的uid存在鏈表結構list中,用rpush uid 1 存儲,用lrange uid 0 -1 獲取所有數據。在刪除數據的時候,用lrem刪除對應的id號。PHP中用lsize能夠獲取list的總數。假設每頁顯示3條,那麼,第1頁:lrange uid 0 2,第2頁:lrange uid 3 5,第3頁:lrange uid 6 8。
 
【PHP操做Redis】
$redis = new Redis();
$flag = $redis->connect('localhost',6379);
$redis->auth("renxing");//受權
$redis->set('user:id:2:name','lisi');
$value = $redis->get('user:id:2:name');
print_r($value);
 
【使用hash類型存儲數據】
hmset:批量添加數據:$redis->hmset('user:1',array('name'=>'renxing','age'=>'28'));
hgetall:獲取全部數據;
del:刪除數據。
 
【執行添加/修改操做 hmset】
$uid = $redis->incr("id");//設定自增
$add_data = array(
"uid"=>$uid,
"username"=>'lisi',
"password"=>'123',
);
$res = $redis->hmset("user:".$uid,$add_data);
此時終端hgetall user:1,獲得:uid 1 username lisi password 123。
 
【獲取數據 hgetall】
$incr_id = $redis->get("uid");
for($i=1;$i<=$incr_id;$i++){
$data[] = $redis->hgetall("user:".$i);
}
print_r($data);
 
【刪除操做】
$res = $redis->del("user:".$uid);
 
【分頁】
用lsize獲取list的總數,假設每頁顯示3條,
那麼第1頁:lrange uid 0 2,第2頁:lrange uid 3 5,第3頁:lrange uid 6 8。
$count = $redis->lsize("uid"); //用戶總數
$page_size = 3;
$page_num = $_GET['page'];
$page_count = ceil($count/$page_size);
$page_up = ($page_num-1)<=1?1:($page_num-1);
$page_down = ($page_num+1)>=$page_count?$page_count:($page_num+1);
$a = ($page_num-1)*$page_size;
$b = $a+$page_size-1;
$ids = $redis->lrange("uid",$a,$b);
foreach($ids as $v){
$data[] = $redis->hgetall("user:".$v);
}
 
【登陸操做】
存儲username和uid的對應關係 $redis->set("username:".$username,$uid);
登陸的時候,使用get 判斷username是否存在 $id = $redis->get("username:".$username);
經過$id獲得存儲在數據庫中的password,和用戶輸入的密碼進行判斷 $pwd = $redis->hget("user:".$id,"password」);
若是正確了,設置SESSION或者cookie。
Redis與Memcached的區別與比較
1 、Redis不只僅支持簡單的k/v類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。memcache只支持簡單的數據類型,String。
2 、Redis支持數據的備份,即master-slave模式的數據備份。
3 、Redis支持數據的持久化,能夠將內存中的數據保持在磁盤中,重啓的時候能夠再次加載進行使用,而Memecache把數據所有存在內存之中。
四、 Memcached是多線程,非阻塞IO複用的網絡模型;Redis使用單線程的IO複用模型。
 
使用Redis緩存查詢數據
與Memcache的區別:性能相差不大
Redis在2.0版本後增長了本身的VM特性,突破物理內存的限制,Memcache能夠修改最大可用內存, 採用LRU算法。
Redis 依賴客戶端來實現分佈式讀寫,Memcache自己沒有數據冗餘機制。
Redis支持(快照、AOF),依賴快照進行持久化,aof加強了可靠性的同時,也對性能有所影響。
Memcache 不支持持久化,一般作緩存,提高性能。
Memcache在併發場景下,用cas保證一致性,redis事務支持比較弱,只能保證事務中的每一個操做連續執行。
Redis支持多種類的數據類型,Redis 用於數據量較小的高性能操做和運算上;
Memcache用於在動態系統中減小數據庫負載,提高性能;適合作緩存,提升性能。
 
1. 使用redis有哪些好處?
(1) 速度快,由於數據存在內存中,相似於HashMap,HashMap的優點就是查找和操做的時間複雜度都是O(1)
(2) 支持豐富數據類型,支持string,list,set,sorted set,hash
(3) 支持事務,操做都是原子性,所謂的原子性就是對數據的更改要麼所有執行,要麼所有不執行
(4) 豐富的特性:可用於緩存,消息,按key設置過時時間,過時後將會自動刪除
 
3. redis常見性能問題和解決方案:
(1) Master最好不要作任何持久化工做,如RDB內存快照和AOF日誌文件
(2) 若是數據比較重要,某個Slave開啓AOF備份數據,策略設置爲每秒同步一次
(3) 爲了主從複製的速度和鏈接的穩定性,Master和Slave最好在同一個局域網內
(4) 儘可能避免在壓力很大的主庫上增長從庫
(5) 主從複製不要用圖狀結構,用單向鏈表結構更爲穩定,即:Master <- Slave1 <- Slave2 <- Slave3...
這樣的結構方便解決單點故障問題,實現Slave對Master的替換。若是Master掛了,能夠馬上啓用Slave1作Master,其餘不變。
 
【redis的rdb和aof】
redis.conf關於rdb的配置:
save 900 1 (900秒以後至少1個關鍵字發生變化),
save 300 10 (300秒以後至少10個關鍵字發生變化),
save 60 10000 (60秒以後至少10000個關鍵字發生變化)。
rdb的缺陷:在2個保存點之間斷電,將會丟失1-N分鐘的數據。
出於對持久化的更精細要求,redis增添了 aof方式 append only file。
把最終的結果逆化爲新的變量,只存儲最終的結果,忽略中間變化的過程,叫作: aof重寫
bgrewriteaof 能夠直接立刻重寫;使用aof後性能稍微會降低。
若是不當心運行了flushall, 當即 shutdown nosave ,關閉服務器。
而後手工編輯aof文件, 去掉文件中的 「flushall 」相關行, 而後開啓服務器,就能夠導入回原來數據。
若是flushall以後,系統剛好bgrewriteaof了,那麼aof就清空了,數據丟失.
aof (append only file)的配置:
appendonly yes (打開aof日誌功能),
appendfsync always (每1個命令都當即同步到aof.安全,速度慢,丟失數據少),
appendfsync everysec (折中方案,每秒寫1次),
appendfsync no (由操做系統判斷緩衝區大小,統一寫入到aof.同步頻率低,速度快。)
aof重寫:只存儲最終的結果,忽略中間變化的過程。
auto-aof-rewrite-percentage 100 (.aof文件增加到多少MB時重寫),
auto-aof-rewrite-min-size 64mb (當至少大於64MB時再重寫),
bgrewriteaof 立刻重寫。
rdb和aof能夠同時使用,優先使用aof恢復。rdb恢復的快,aof是逐條執行的命令。
 
rdb和aof的一些注意事項:
(1)在dump rdb過程當中,aof若是中止同步,會不會丟失? (不會,全部的操做緩存在內存的隊列裏, rdb執行dump完成後,統一操做.)
(2)aof重寫是指什麼? (aof重寫是指把內存中的數據,逆化成命令,寫入到.aof日誌裏.解決 aof日誌過大的問題.)
(3)rdb和aof,兩種是否能夠同時用? (能夠,並且推薦這麼作)
(4)若是rdb文件和aof文件都存在,優先用誰來恢復數據? (優先aof)
(5)恢復時rdb和aof哪一個恢復的快 (rdb快,由於其是數據的內存映射,直接載入到內存,而aof是命令,須要逐條執行)
 
【Redis集羣】
集羣的做用:主從備份,防止主機宕機;讀寫分離,分擔master的任務;任務分離,主從服務器分別負責備份工做與計算工做。
redis集羣的實現:
1.官方cluster方案:
從redis 3.0版本開始支持redis-cluster集羣,redis-cluster採用無中心結構,每一個節點保存數據和整個集羣狀態,每一個節點都和其餘節點鏈接。官方推薦的方案是將node配置成主從結構,即一個master主節點,掛n個slave從節點。若是主節點失效,redis cluster會根據選舉算法從slave節點中選擇一個上升爲master節點,整個集羣繼續對外提供服務。
2.twemproxy代理方案:
Redis代理中間件twemproxy是一種利用中間件作分片的技術。客戶端不直接訪問redis服務器,而是經過twemproxy代理中間件間接訪問。下降了客戶端直連後端服務器的鏈接數量。twemproxy是一個單點,很容易對其形成很大的壓力,因此一般會結合keepalived來實現twemproy的高可用。
3.哨兵模式 Sentinel:
是Redis的高可用性解決方案:由一個或多個Sentinel實例組成的Sentinel系統能夠監視任意多個主服務器以及這些主服務器下的全部從服務器,並在被監視的主服務器進入下線狀態時,自動將下線主服務器屬下的某個從服務器升級爲新的主服務器。
4.codis:
codis是一個分佈式的Redis解決方案,對於上層的應用來講,鏈接codis proxy和鏈接原生的redis server沒什麼明顯的區別,上層應用能夠像使用單機的redis同樣使用,codis底層會處理請求的轉發,不停機的數據遷移等工做,全部後邊的事情,對於前面的客戶端來講是透明的,能夠簡單的認爲後邊鏈接的是一個內存無限大的redis服務。
5.客戶端分片:
分區的邏輯在客戶端實現,由客戶端本身選擇請求到哪一個節點。方案可參考一致性哈希,這種方案一般適用於用戶對客戶端的行爲有徹底控制能力的場景。
 
【總結】
Redis Sentinal着眼於高可用,在master宕機時會自動將slave提高爲master,繼續提供服務。
Redis Cluster着眼於擴展性,在單個redis內存不足時,使用Cluster進行分片存儲。
緩存雪崩和穿透問題:
緩存穿透:通常的緩存系統,都是按照key去緩存查詢,若是不存在對應的value,就應該去後端系統查找(好比DB)。一些惡意的請求會故意查詢不存在的key,請求量很大,就會對後端系統形成很大的壓力。這就叫作緩存穿透。
如何避免?
1:對查詢結果爲空的狀況也進行緩存,緩存時間設置短一點,或者該key對應的數據insert了以後清理緩存。
2:對必定不存在的key進行過濾。能夠把全部的可能存在的key放到一個大的Bitmap中,查詢時經過該bitmap過濾。
 
緩存雪崩:當緩存服務器重啓或者大量緩存集中在某一個時間段失效,這樣在失效的時候,會給後端系統帶來很大壓力。致使系統崩潰。
如何避免?
1:在緩存失效後,經過加鎖或者隊列來控制讀數據庫寫緩存的線程數量。好比對某個key只容許一個線程查詢數據和寫緩存,其餘線程等待。
2:作二級緩存,A1爲原始緩存,A2爲拷貝緩存,A1失效時,能夠訪問A2,A1緩存失效時間設置爲短時間,A2設置爲長期
3:不一樣的key,設置不一樣的過時時間,讓緩存失效的時間點儘可能均勻。
 
Redis裏面的 sub 和 pub?
Pub/Sub功能(means Publish, Subscribe)即發佈及訂閱功能。
基於事件的系統中,Pub/Sub是目前普遍使用的通訊模型,它採用事件做爲基本的通訊機制,提供大規模系統所要求的鬆散耦合的交互模式:
訂閱者(如客戶端)以事件訂閱的方式表達出它有興趣接收的一個事件或一類事件;
發佈者(如服務器)可將訂閱者感興趣的事件隨時通知相關訂閱者。
Redis的pub/sub是一種消息通訊模式,主要的目的是解除消息發佈者和消息訂閱者之間的耦合,
Redis做爲一個pub/sub的server,在訂閱者和發佈者之間起到了消息路由的功能。
 
使用Memcache 緩存查詢數據
memcache的工做原理:
Memcache是一個高性能的發佈式的內存對象緩存系統,經過在內存裏維護一個統一的巨大的hash表,它可以用來存儲各類格式的數據,包括圖片、視頻、文件以及數據庫檢索的結果等。簡單的說就是將數據調用到內存,而後從內存中讀取,從而大大提升讀取速度。
 
memcache的工做流程:
先檢查客戶端的請求數據是否在memcached中,若有,直接把請求數據返回,再也不對數據庫進行任何操做;若是請求的數據不在memcached中,就去查數據庫,把從數據庫中獲取的數據返回給客戶端,同時把數據緩存一份到memcached中。
 
memcache的一些方法:
獲取:get(key)
設置:set(key, val, expire)
刪除:delete(key)

 

【telnet localhost 11211】
stats    查看狀態(stats sizes  表示:64M中使用了 3M)
version 查看版本
添加操做:add myvar1 1 3000 10  //myvar1 鍵值,1 標誌位,3000 存儲時間(秒),10 存儲的字符數(輸入剛纔設置的字符數10,舉例:helloworld,顯示STORED操做成功)。
獲取操做:get myvar1 (此時再設置一個myvar1 就會出錯)
覆蓋操做:set myvar1 1 3000 10
刪除操做:delete myvar1
清除全部操做:flush_all
說明:若是重啓服務數據就會丟失。
 
【啓動memcached】
memcached -d -m 128 -u root -l localhost -p 11211
/usr/local/memcached/bin/memcached -d -m 1024 -u root -l 127.0.0.1 -p 11211 -c 256 -P /tmp/memcached.pid
# 查看內存分配狀況:
/usr/local/memcached/bin/memcached -d -m 1024 -u root -l 127.0.0.1 -p 11211 -c 256 -P /tmp/memcached.pid -vv
 
【PHP中測試 Memcache功能】
$mem=new memcache;
$mem->connect("localhost", 11211) or die ("鏈接失敗");
$key = ‘goods_1’;
$data=$mem->get($key);
if(!$data){    
    $mem->set($key, ‘abcdefg’, MEMCACHE_COMPRESSED, 3600);
} 
 
相關文章
相關標籤/搜索