一、Redis概述
1、Redis就是一個(gè)數(shù)據(jù)庫、但是數(shù)據(jù)存在內(nèi)存中
2、Redis的優(yōu)勢
①性能極高:讀11萬次/s、寫8.1萬次/s
②支持?jǐn)?shù)據(jù)持久化(注:指服務(wù)重啟后數(shù)據(jù)不會丟失)
③支持豐富的數(shù)據(jù)結(jié)構(gòu):String(字符串)、hash(哈希)、list (列表)、set(集合)、sorted set(有序集合)等
3、Redis與Memcache的區(qū)別
相同點(diǎn):都是基于內(nèi)存以鍵值對形式存儲
不同點(diǎn):支持?jǐn)?shù)據(jù)持久化
不同點(diǎn):Redis數(shù)據(jù)類型比Memcache多
二、Redis的基礎(chǔ)操作命令
1、添加、修改(CU)
語法:set 鍵 值
說明:鍵不存在-則創(chuàng)建,鍵存在-則修改
2、取指定key的值(R)
語法:get 鍵
說明:返回對應(yīng)的值(注:nil表示無值)
3、刪除指定key的值(D)
語法: del 鍵1 鍵2 鍵3....
說明:返回刪除成功的個(gè)數(shù)(可以同時(shí)刪除多個(gè)key多個(gè)之間用空格隔開)

三、常用的五種數(shù)據(jù)類型
1、字符串型(String)
①概念:key value{string/int/float}
②設(shè)置N個(gè)鍵(mset)
語法:mset 鍵1 值1 ..... 鍵n 值n
說明:鍵存在-則修改,鍵不存在-則創(chuàng)建(注:redis中m表示多個(gè)值)
③獲取N個(gè)鍵(mget)
語法:mget 鍵 .... 鍵n
說明:一次性返回多個(gè)值,不存在返回nil表示無值
④遞增遞減(incr和decr)
語法:incr/decr 鍵
說明:返回遞增遞減后的數(shù)字
⑤增減指定值(incrby和decrby)
語法:incrby/decrby 鍵 數(shù)字
說明:返回遞增遞減后的值
⑥拼接-字符串追加(append)
語法:append 鍵 值
說明:返回拼接后的長度
⑦字符串截?。?code>substr)
語法:substr 鍵 起始位置 結(jié)束為止
說明:下標(biāo)0開始(含前下標(biāo)&含后下標(biāo))

案例:
計(jì)數(shù)器:網(wǎng)站詳情訪問量,網(wǎng)站流量統(tǒng)計(jì)(百度統(tǒng)計(jì)、站長統(tǒng)計(jì))
網(wǎng)站緩存服務(wù)器
SESSION入Redis
接口請求次數(shù)限制等功能
2、哈希類型(Hash)
①概念:Redis hash 是一個(gè)string類型的field和value的映射表,hash特別適合用于存儲對象。
②設(shè)置/獲取hash字段(hset)
語法:hset 鍵 字段 值
說明:如果字段是哈希表中的一個(gè)新建字段,并且值設(shè)置成功,返回 1;如果哈希表中域字段已經(jīng)存在且舊值已被新值覆蓋,返回 0
③鍵獲取字段值(hget)
語法:hget 鍵 字段
④鍵添加N個(gè)字段(hmset)
語法:hmset 鍵 字段1 值1 ..... 字段n 值n
⑤鍵獲取N個(gè)字段(hmget)
語法:hmget 鍵 字段1 ... 字段n
說明:獲取指定鍵的哈希字段值
⑥字段增值(hincrby)
語法:hincrby 鍵 字段 數(shù)字
說明:給指定的鍵字段遞增值
⑦檢測鍵字段(hexists)
語法:hexists 鍵 字段
說明:返回(1-存在,0-不存在)
⑧刪除鍵字段(hdel)
語法:hdel 鍵 字段1 ... 字段n
⑨字段個(gè)數(shù)(hlen)
語法:hlen 鍵
說明:返回鍵字段個(gè)數(shù)
⑩哈希查詢(hkeys 和 hvals 和 hgetall)
hkeys key # 返回全字段
hvals key # 返回全值
hgetall key # 返回全字段和值
案例:
存放復(fù)雜的數(shù)據(jù)結(jié)構(gòu),如:用戶信息、商品信息等
3、列表類型(List)
①概念

lpush lpop先進(jìn)先出
lpush rpop②左進(jìn)(
lpush) 和 右進(jìn)(rpush)語法:
lpush 鍵 數(shù)據(jù)說明:從左/右側(cè)壓入數(shù)據(jù),返回壓入后數(shù)據(jù)長度
③查詢(
lrange)語法:
lrange 鍵 起始位置 結(jié)束為止說明:返回列表中數(shù)據(jù)(注:下標(biāo)從0開始,含前含后 結(jié)束為止-1表示最后一個(gè),-2表示倒數(shù)第二個(gè) 依次類推)
④頭出(
lpop)和 尾出(rpop)語法:
lpop/rpop 鍵說明:返回彈出后的數(shù)據(jù)

案例:
秒殺消息隊(duì)列
微博最新關(guān)注列表,某用戶個(gè)人中心只顯示最新關(guān)注的5個(gè)用戶
需求:微博最新關(guān)注的用戶
明確:鍵 - 關(guān)注張三的用戶ID
實(shí)現(xiàn):
#1.有新用戶關(guān)注,就將新用戶ID壓入隊(duì)列中
$隊(duì)列長度 = lpush 關(guān)注張三的用戶ID 關(guān)注的用戶ID
#2.如果隊(duì)列長度大于5,則彈出開始關(guān)注用戶(目的:為了保證隊(duì)列中是最新關(guān)注的5個(gè)用戶)
if ($隊(duì)列長度 > 5) {
rpop 關(guān)注張三的用戶ID
}
滿足上述需求后,后期打開微博只需要:【lrange 關(guān)注張三的用戶ID 0 -1】就可以查詢出最新關(guān)注的5個(gè)用戶
4、集合類型(Set)
①概念

語法:
sadd 集合名 數(shù)據(jù) [數(shù)據(jù)2... 數(shù)據(jù)n]說明:給指定集合添加數(shù)據(jù)
③移除(srem)
語法:
srem 集合名 數(shù)據(jù) [數(shù)據(jù)2... 數(shù)據(jù)n] 說明:從指定集合移除數(shù)據(jù)
④查看 (smembers key)
語法:
smembers 集合名作用:獲取集合中的數(shù)據(jù)

語法:
sdiff 集合名1 ... 集合名n作用:我有其他人沒有

語法:
sunion 集合1 ... 集合n作用:合并去重

語法:
sinter 集合1 ... 集合n作用:取集合公共部分

5、有序集合(sorted set)
①概述:Redis 有序集合和集合一樣也是string類型元素的集合,且不允許重復(fù)的成員。不同的是每個(gè)元素都會關(guān)聯(lián)一個(gè)double類型的分?jǐn)?shù)。redis正是通過分?jǐn)?shù)來為集合中的成員進(jìn)行從小到大的排序。
有序集合的成員是唯一的,但分?jǐn)?shù)(score)卻可以重復(fù)。
②添加(zadd)
語法:zadd 集合名 分?jǐn)?shù) 成員
說明:如果某個(gè)成員已經(jīng)是有序集的成員,那么更新這個(gè)成員的分?jǐn)?shù)值,并通過重新插入這個(gè)成員元素,來保證該成員在正確的位置上。

語法:
zrem 集合名 成員 [成員2...成員n]說明:從指定集合移除數(shù)據(jù)
④查看 (zrange)
語法:
zrange 集合名 起始位置 結(jié)束位置 [WITHSCORES]作用:獲取集合中的數(shù)據(jù)(注:WITHSCORES指既顯示成員又顯示數(shù)據(jù))
⑤升降序排名 (zrange & zrevrange)
語法(升序):
zrange 鍵 起始位置 結(jié)束位置 WITHSCORES 語法(降序):
zrevrange 鍵 起始位置 結(jié)束位置 WITHSCORES
四、鍵(Key)操作
1、鍵是否存在(exists)
語法:exists 鍵
說明:判斷指定的鍵是否存在(1-存在,0-不存在)
2、鍵類型(type)
語法:type 鍵
說明:查看鍵類型,如:sring、hash、list、set等

3、鍵查詢 (keys *)
keys * 查看當(dāng)前數(shù)據(jù)庫所有鍵
keys php* 查看當(dāng)前數(shù)據(jù)庫以php開頭的所有鍵
keys *php 查看當(dāng)前數(shù)據(jù)庫以php結(jié)尾的所有鍵
keys *php* 查看當(dāng)前數(shù)據(jù)庫包含php的所有鍵
4、鍵更名(rename)
語法:rename 舊鍵 新鍵
5、鍵統(tǒng)計(jì)(dbsize)
語法:dbsize
6、鍵設(shè)置過期時(shí)間(expire key 秒數(shù) 和 ttl key)
語法1:expire 鍵 秒數(shù)
含義1:設(shè)置指定鍵過期時(shí)間
語法2:ttl 鍵
含義2:檢測鍵是否過期(明確:過期就不存在了。-2:不存在 -1:未設(shè)置 )
7、選擇數(shù)據(jù)庫(select)
語法:select 下標(biāo)
說明:默認(rèn)有16個(gè)數(shù)據(jù)庫,下標(biāo)從0開始,最大下標(biāo)為15,默認(rèn)在第一個(gè)數(shù)據(jù)庫下。
(注:可以通過修改配置文件更改)

8、鍵刪除
鍵刪除-當(dāng)前庫(flushdb)
鍵刪除-全部庫(flushall)

五、Redis的持久化方式
1、快照持久化(Snapshotting)
說明:快照模式將內(nèi)存中的數(shù)據(jù)以快照的方式寫入二進(jìn)制文件中(dump.rbd)


2、AOF持久化(Append only file)
①概念:AOF方式是只保存我們的寫、修改、刪除動作(命令)到文件中(appendonly.aof)當(dāng)系統(tǒng)重啟的時(shí)候會將該文件中的數(shù)據(jù)重新加載到內(nèi)存中(執(zhí)行命令獲取數(shù)據(jù))。
②開啟AOF方式





六、主從復(fù)制
1、概述
當(dāng)主服務(wù)器有寫入/刪除/修改數(shù)據(jù)動作,從服務(wù)器會自動同步
2、主服務(wù)器配置
步驟1:打開配置文件,命令:vi /php/server/redis/redis.conf
步驟2:開啟后臺啟動,操作:daemonize yes
步驟3:設(shè)置密碼(重要!因?yàn)閞edis默認(rèn)可以匿名登陸,所以一定要設(shè)置?。?,操作:requirepass 123 #從服務(wù)器連接主服務(wù)器需要使用
步驟4:開啟Redis遠(yuǎn)程訪問,操作:去掉bind 127.0.0.1可以使所有的ip訪問redis

步驟6:注意:主服務(wù)器防火墻開放6379端口(或者直接關(guān)閉防火墻)
3、從服務(wù)器配置
步驟1:打開配置文件,命令:vi /php/server/redis/redis.conf
步驟2:開啟后臺啟動,操作:daemonize yes
步驟3:修改端口,操作:port 6380【注意:如果不在同一臺機(jī)器上配置則不需要修改】
步驟4:聲明需要復(fù)制的主服務(wù)器IP、端口、密碼

測試:

七、PHP操作Redis
phpredis中文手冊:http://www.cnblogs.com/ikodota/archive/2012/03/05/php_redis_cn.html
簡單操作示例:
//步驟1:實(shí)例化redis類
$redis = new Redis;
//步驟2:連接redis
$redis->connect('192.168.142.128', '6379');
$redis->auth('666666');
//步驟3:選擇數(shù)據(jù)庫
$redis->select(0);
//步驟4:操作
$rs = $redis->set('product', '電腦');
var_dump($rs);
echo '<br>';
$rs = $redis->get('product');
var_dump($rs);

八、消息隊(duì)列
1、概述
消息隊(duì)列就是一個(gè)隊(duì)列,將需要操作的數(shù)據(jù)放到隊(duì)列中,通過另個(gè)程序彈出處理。
好處:
①避免同一秒N多用戶操作數(shù)據(jù)庫,導(dǎo)致數(shù)據(jù)庫崩潰
②避免發(fā)送失敗
2、場景
需求:用戶注冊成功,發(fā)送郵件+短信
reg.php:
<?php
#步驟1:通過實(shí)例化redis類
$redis = new Redis;
#步驟2:連接redis,語法:$redis->connect(IP地址,端口)
$redis->connect('192.168.159.128', 6379);
$redis->auth(123);
#步驟3:選擇數(shù)據(jù)庫
$redis->select(0);
#步驟4:操作
$rs = $redis->lPush('email', mt_rand(1111,9999).'@qq.com');
var_dump($rs);
echo '<hr />';
$rs = $redis->lRange('email', 0, -1);
echo '<pre>';
print_r($rs);

send.php:
<?php
#PHP腳本最大執(zhí)行時(shí)間30s 超時(shí)就報(bào)錯(cuò)
#不限時(shí)
set_time_limit(0);
#通過實(shí)例化redis類
$redis = new Redis;
$redis->connect('192.168.159.128', 6379);
$redis->auth(123);
$redis->select(0);
#死循環(huán)
while(true) {
//獲取郵箱賬號
$email = $redis->lPop('email');
if (!$email) {
echo iconv('utf-8', 'gbk', "監(jiān)聽中....\r\n");
sleep(1);
continue;
}
//調(diào)用接口發(fā)送郵件(偽代碼)
$rs = 1;
//判斷
if ($rs) {
echo $email . iconv('utf-8', 'gbk', "發(fā)送成功\r\n");
} else {
//發(fā)送失敗重新入隊(duì)
$redis->lPush('email', $email);
//發(fā)送郵件報(bào)警 開發(fā)者
}
}
