攻克Redis之基本知識node
摘要: 【攻克Redis】Redis基本知識 發展史 Redis是一種基於鍵值對的Nosql數據庫,Redis值能夠是string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)、Bitmaps(位圖)、 HyperLogLog、GEO(地理信息定位)等多種數據結構和算法組成 Redis會將全部數據都存放在內存 中,因此它的讀寫性能很是驚人。
1.發展史git
Redis是一種基於鍵值對的Nosql數據庫,Redis值能夠是string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)、Bitmaps(位圖)、 HyperLogLog、GEO(地理信息定位)等多種數據結構和算法組成 Redis會將全部數據都存放在內存 中,因此它的讀寫性能很是驚人。不只如此,Redis還能夠將內存的數據利 用快照和日誌的形式保存到硬盤上,這樣在發生相似斷電或者機器故障的時 候,內存中的數據不會「丟失」 Redis提供了鍵過時、發佈訂閱、事務、流水線、Lua腳本等附加功能
2.特性github
1.速度快(10萬/秒)
全部數據存放在內存中
用C語言實現,C語言「距離」操做系統更近
單線程架構,防止多線程可能產生的問題
2.基於鍵值對的數據結構服務器
主要提供了5種數據結構:字符串、哈希、列表、集合、有序集合
在字符串的基礎之上演變 出了位圖(Bitmaps)和HyperLogLog兩種神奇的「數據結構」
Redis3.2版本中 加入有關GEO(地理信息定位)的功能
3.豐富的功能
提供了鍵過時功能,能夠用來實現緩存。
提供了發佈訂閱功能,能夠用來實現消息系統。
支持Lua腳本功能,能夠利用Lua創造出新的Redis命令。
提供了簡單的事務功能,能在必定程度上保證事務特性。
提供了流水線(Pipeline)功能,這樣客戶端能將一批命令一次性傳到 Redis,減小了網絡的開銷。
4.簡單穩定
源碼代碼量少
單線程模型開發簡單
不須要依賴操做系統類庫
5.客戶端語言多
Redis提供了簡單的TCP通訊協議,不少編程語言能夠很方便地接入到 Redis
6.持久化
兩種持久化方式:RDB和 AOF
7.主從複製
Redis提供了複製功能,實現了多個相同數據的Redis副本,複製功能是分佈式Redis的基礎
8.高可用和分佈式redis
3.使用場景算法
能夠作1. 緩存緩存提升訪問速度,下降後端數據庫壓力,能夠設置過時時間,對存儲數據進行淘汰。2.排行榜系統Redis提供了列表和有序集合數據結構,合理地使用這些數據結構能夠很方便地構建各類排行榜系統。3.計數器應用視頻網站有播放數、電商網站有 瀏覽數,爲了保證數據的實時性,每一次播放和瀏覽都要作加1的操做4. 社交網絡贊/踩、粉絲、共同好友/喜愛、推送、下拉刷新等sql
Redis提供了發佈訂閱功能和阻塞隊列的功能,雖然和專業的消息隊列比還不夠足夠強大,可是對於通常的消息隊列功能基本能夠知足。數據庫
4.五種數據結構詳解編程
Redis不只僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。 String——字符串Hash——字典List——列表Set——集合Sorted Set——有序集合 下面咱們就來簡單說明一下它們各自的使用場景:
一、Redis String類型後端
string類型的數據存儲是最簡單的key-value存儲;
[Java] 純文本查看 複製代碼
?
1
2
3
4
5
6
public function testRedis(){緩存
//string類型的數據結構 app()->redis->set('1', 'aa');
//根據key取出value值
$string = app()->redis->get('1');
}
1-2.redis客戶端查看結果:
1-3.string字符串的其餘redis操做方法:
//普通set/get操做$redis->set('library', 'predis');redis->get('library');echo $retval; //顯示 'predis'
//setex set一個存儲時效$redis->setex('str', 10, 'bar'); //表示存儲有效期爲10秒
//setnx/msetnx至關於add操做,不會覆蓋已有值$redis->setnx('foo',12); //true$redis->setnx('foo',34); //false
//getset操做,set的變種,結果返回替換前的值$redis->getset('foo',56);//返回34
// incrby/incr/decrby/decr 對值的遞增和遞減$redis->incr('foo'); //foo爲57$redis->incrby('foo',2); //foo爲59
//exists檢測是否存在某值$redis->exists('foo');//true
//del 刪除$redis->del('foo');//true
//type 類型檢測,字符串返回string,列表返回 list,set表返回set/zset,hash表返回hash$redis->type('foo');//不存在,返回none$redis->set('str','test');$redis->type('str'); //字符串,返回string
//append 鏈接到已存在字符串$redis->append('str','_123'); //返回累加後的字符串長度8,此進str爲 'test_123'
//setrange 部分替換操做$redis->setrange('str',0,'abc'); //返回3,參數2爲0時等同於set操做$redis->setrange('str',2,'cd');//返回4,表示從第2個字符後替換,這時'str'爲'abcd'
//substr 部分獲取操做$redis->substr('str',0,2);//表示從第0個起,取到第2個字符,共3個,返回'abc'
//strlen 獲取字符串長度$redis->strlen('str'); //返回4
//setbit/getbit 位存儲和獲取$redis->setbit('binary',31,1); //表示在第31位存入1,這邊可能會有大小端問題?不過不要緊,getbit 應該不會有問題$redis->getbit('binary',31); //返回1
//keys 模糊查找功能,支持*號以及?號(匹配一個字符)$redis->set('foo1',123);$redis->set('foo2',456);$redis->keys('foo*'); //返回foo1和foo2的array$redis->keys('f?o?'); //同上
//randomkey 隨機返回一個key$redis->randomkey(); //多是返回 'foo1'或者是'foo2'及其它任何一存在redis的key
//rename/renamenx 對key進行更名,所不一樣的是renamenx不容許改爲已存在的key$redis->rename('str','str2'); //把原先命名爲'str'的key改爲了'str2'
//expire 設置key-value的時效性,ttl 獲取剩餘有效期,persist 從新設置爲永久存儲$redis->expire('foo', 1); //設置有效期爲1秒$redis->ttl('foo'); //返回有效期值1s$redis->expire('foo'); //取消expire行爲
//dbsize 返回redis當前數據庫的記錄總數$redis->dbsize();
二、Redis Hash表 redis中hash表存儲數據,比較相似數據庫中表的一條記錄;2-1.hash讀寫實現方式:
[Java] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
public function testRedis()
{//存儲 hash類型 數據結構 app()->redis->hset('goods', 'apple', '蘋果');
//取出 hash表中的數據 $hash = app()->redis->hget('goods', 'apple'); print_r($hash); echo "\n"; die(); }
三、Redis list列表
List數據結構是鏈表結構,是雙向的,能夠在鏈表左,右兩邊分別操做; 也能夠把list當作一種隊列,因此在不少時候能夠用redis用做消息隊列,這個時候它的做用就相似於activeMq啦; 應用案例有時間軸數據,評論列表,消息傳遞等等,它能夠提供簡便的分頁,讀寫操做。
3-1.list 讀寫實現方式:
[Java] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
public function testRedis()
{//存儲 list app()->redis->lpush('news', 'cc'); //從隊列前面插入元素 app()->redis->lpush('news', 'ee'); //從隊列前面插入元素 app()->redis->rpush('news', 'dd');//從隊列後面插入元素 $list = app()->redis->lrange('news', 0, -1);//取出list全部元素 print_r($list); echo "\n";
die(); }
四、Redis Set集合
Set 就是一個集合,集合的概念就是一堆不重複值的組合。利用 Redis 提供的 Set 數據結構,能夠存儲一些集合性的數據。 好比在微博應用中,能夠將一個用戶全部的關注人存在一個集合中,將其全部粉絲存在一個集合。 由於 Redis 很是人性化的爲集合提供了求交集、並集、差集等操做,那麼就能夠很是方便的實現如共同關注、共同喜愛、二度好友等功能,對上面的全部集合操做,你還可使用不一樣的命令選擇將結果返回給客戶端仍是存集到一個新的集合中。
1.共同好友、二度好友2.利用惟一性,能夠統計訪問網站的全部獨立 IP3.好友推薦的時候,根據 tag 求交集,大於某個 threshold 就能夠推薦
4-1.set 讀寫實現方式:
[Java] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public function testRedis()
{//存儲 set
$fans = app()->redis->sadd('fans', 'ff'); if($fans){ print_r('set add ff success'); }else{ print_r('set add ff fail'); } $fans = app()->redis->sadd('fans', 'gg'); //不存在返回true if($fans){ print_r('set add gg success'); }else{ print_r('set add gg fail'); } $fans = app()->redis->sadd('fans', 'gg'); //不存在返回false if($fans){ print_r('set add gg success'); }else{ print_r('set add gg fail'); } //取出set $fans = app()->redis->smembers('fans'); print_r($fans); echo "\n";
}
五、Redis Zset集合(Sorted Sets)
zset是set的一個升級版本,他在set的基礎上增長了一個順序屬性,這一屬性在添加修改元素的時候能夠指定,每次指定後,zset會自動從新按新的值調整順序。 能夠對指定鍵的值進行排序權重的設定,它應用排名模塊比較多。 好比一個存儲全班同窗成績的 Sorted Sets,其集合 value 能夠是同窗的學號,而 score 就能夠是其考試得分,這樣在數據插入集合的時候,就已經進行了自然的排序。另外還能夠用 Sorted Sets 來作帶權重的隊列,好比普通消息的 score 爲1,重要消息的 score 爲2,而後工做線程能夠選擇按 score 的倒序來獲取工做任務,讓重要的任務優先執行。 zset集合能夠完成有序執行、按照優先級執行的狀況;
1.zset 讀寫實現方式:
[Java] 純文本查看 複製代碼
?
01
02
03
04
05
06
07
08
09
10
11
12
public function testRedis()
{//zset 添加元素
app()->redis->zadd('students', '1', '90'); app()->redis->zadd('students', '2', '80'); app()->redis->zadd('students', '3', '95'); app()->redis->zadd('students', '7', '75'); app()->redis->zadd('students', '5', '55'); //取出 zset $zset = app()->redis->zrange('students', 0, -1); print_r($zset); echo "\n";
}
4.集羣
Redis 集羣是Redis 的一個分佈式實現,它是一個網狀結構,每一個節點都經過 TCP 鏈接跟其餘每一個節點鏈接。如今來看看Redis集羣實現了哪些目標? 在1000個節點的時候仍能表現得很好而且可擴展性(scalability)是線性的。集羣之間使用異步複製,而且沒有合併的操做。 可接受的寫入安全(Write safety)級別:那些與大多數節點相連的客戶端所作的寫入操做,系統嘗試所有都保存下來。不過仍是會有小部分寫入會丟失。 可用性(Availability):在絕大多數的主節點(master node)是可達的,而且對於每個不可達的主節點都至少有一個它的從節點(slave)可達的狀況下,Redis 集羣仍能進行分區(partitions)操做。 那麼Redis集羣環境與非分佈式Redis環境在功能上有沒有什麼不一樣的呢? 集羣的數據庫只有0,且不支持SELECT 因爲集羣將鍵分佈在不一樣的槽(slot)中,因此涉及到多鍵值的複製操做也是不支持的,像set裏的並集(unions)和交集(intersections)操做
1 集羣環境介紹
本文搭建的集羣環境有3個主節點,每一個主節點都有兩個從節點,架構圖以下
2 修改配置文件
關於集羣的配置以下:
[Java] 純文本查看 複製代碼
?
1
2
3
4
5
6
7
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 5000
cluster-enabled表示是否開啓集羣模式
cluster-conf-file 表示保存節點配置文件的路徑
cluster-node-timeout表示節點超時時間
完整的配置文件在https://github.com/rainbowda/... ,有須要的能夠去下載
3 節點配置及啓動
因爲採用一個服務器運行三個Redis實例,因此每一個節點的配置有些許不一樣,像端口號、文件位置、文件名稱等等。這裏就不將每一個配置文件貼出來了,Github上有主節點和兩個從節點的配置文件。 我在redis文件夾下建立一個cluster文件夾,而後在cluster文件夾下建立一個master文件,存放主節點的配置文件master.conf和一些其餘文件;再而後建立兩個從節點文件7001和7002,也是存放配置文件等。 mkdir cluster cd cluster mkdir master 7001 7002 將配置文件拷貝到相應文件夾後,根據配置文件啓動Redis,這裏就不在說明了。