科普 | Redis七大特性簡(jiǎn)介
來(lái)源:原創(chuàng) 時(shí)間:2017-05-02 瀏覽:0 次
Redis 是一個(gè)開(kāi)源的、高級(jí)的鍵值對(duì)存儲(chǔ)系統(tǒng),經(jīng)常被用作數(shù)據(jù)結(jié)構(gòu)服務(wù)器,因?yàn)槠渲С肿址ash、列表、集合和有序集合等數(shù)據(jù)結(jié)構(gòu)。在Laravel中使用Redis之前,需要通過(guò)Composer安裝 predis/predis 包:
composer require predis/predis
配置
應(yīng)用的Redis配置位于配置文件 config/database.php 。在這個(gè)文件中,可以看到包含被應(yīng)用使用的Redis服務(wù)器的 redis 數(shù)組:
'redis' => [
'cluster' => false,
'default' => [ 'host' => '127.0.0.1',
'port' => 6379, 'database' => 0,
],
],
默認(rèn)服務(wù)器配置可以滿足開(kāi)發(fā)需要,不過(guò),你可以基于自己的環(huán)境修改該數(shù)組。配置文件中定義的每個(gè)Redis服務(wù)器需要一個(gè)名字并指定該Redis服務(wù)器使用的主機(jī)和接口。
cluster 選項(xiàng)告知Laravel Redis 客戶端在多個(gè)Redis節(jié)點(diǎn)間執(zhí)行客戶端分片,從而形成節(jié)點(diǎn)池并創(chuàng)建大量有效的RAM。然而,客戶端分片并不處理故障轉(zhuǎn)移,所以,非常適合從另一個(gè)主數(shù)據(jù)存儲(chǔ)那里獲取有效的緩存數(shù)據(jù)。
此外,你可以在Redis連接定義中定義options數(shù)組值,從而允許你指定一系列Predis客戶端選項(xiàng)。
如果Redis服務(wù)器要求認(rèn)證信息,你可以通過(guò)添加 password 配置項(xiàng)到Redis服務(wù)器配置數(shù)組來(lái)提供密碼。
注意:如果你通過(guò)PECL安裝PHP的Redis擴(kuò)展,需要在 config/app.php 文件中修改Redis的別名。
一、Redis七種特性
Redis的幾種使用方式 Strings、Hashs、Lists、Sets、SortedSets、Pub/Sub、Transactions 也比作七種武器,為大家講解Redis的七種特性,并列舉其適合的應(yīng)用場(chǎng)景。
1.Strings(字符串)
Redis 字符串是一個(gè)字節(jié)序列。在 Redis 中字符串是二進(jìn)制安全的,這意味著它們沒(méi)有任何特殊終端字符來(lái)確定長(zhǎng)度,所以可以存儲(chǔ)任何長(zhǎng)度為 512 兆的字符串。
Strings 數(shù)據(jù)結(jié)構(gòu)是簡(jiǎn)單的key-value類型,value其實(shí)不僅是String,也可以是數(shù)字。使用Strings類型,你可以完全實(shí)現(xiàn)目前 Memcached 的功能,并且效率更高。還可以享受Redis的定時(shí)持久化,操作日志及 Replication等功能。除了提供與 Memcached 一樣的get、set、incr、decr 等操作外,Redis還提供了下面一些操作:
獲取字符串長(zhǎng)度
往字符串a(chǎn)ppend內(nèi)容
設(shè)置和獲取字符串的某一段內(nèi)容
設(shè)置及獲取字符串的某一位(bit)
批量設(shè)置一系列字符串的內(nèi)容
2.Hashs(哈希)
Redis哈希是鍵值對(duì)的集合。 Redis哈希是字符串字段和字符串值之間的映射,所以它們用來(lái)表示對(duì)象。
在Memcached中,我們經(jīng)常將一些結(jié)構(gòu)化的信息打包成hashmap,在客戶端序列化后存儲(chǔ)為一個(gè)字符串的值,比如用戶的昵稱、年齡、性別、積分等,這時(shí)候在需要修改其中某一項(xiàng)時(shí),通常需要將所有值取出反序列化后,修改某一項(xiàng)的值,再序列化存儲(chǔ)回去。這樣不僅增大了開(kāi)銷,也不適用于一些可能并發(fā)操作的場(chǎng)合(比如兩個(gè)并發(fā)的操作都需要修改積分)。而Redis的Hash結(jié)構(gòu)可以使你像在數(shù)據(jù)庫(kù)中Update一個(gè)屬性一樣只修改某一項(xiàng)屬性值。
3.Lists(鏈表)
Redis 列表是簡(jiǎn)單的字符串列表,通過(guò)插入順序排序??梢蕴砑右粋€(gè)元素到 Redis 列表的頭部或尾部。
相信略有數(shù)據(jù)結(jié)構(gòu)知識(shí)的人都應(yīng)該能理解其結(jié)構(gòu)。使用Lists結(jié)構(gòu),我們可以輕松地實(shí)現(xiàn)最新消息排行等功能。Lists的另一個(gè)應(yīng)用就是消息隊(duì)列,可以利用Lists的PUSH操作,將任務(wù)存在Lists中,然后工作線程再用POP操作將任務(wù)取出進(jìn)行執(zhí)行。Redis還提供了操作Lists中某一段的api,你可以直接查詢,刪除Lists中某一段的元素。
4.Sets(集合)
Sets 就是一個(gè)集合,集合的概念就是一堆不重復(fù)值的組合。利用Redis提供的Sets數(shù)據(jù)結(jié)構(gòu),可以存儲(chǔ)一些集合性的數(shù)據(jù),比如在微博應(yīng)用中,可以將一個(gè)用戶所有的關(guān)注人存在一個(gè)集合中,將其所有粉絲存在一個(gè)集合。Redis還為集合提供了求交集、并集、差集等操作,可以非常方便的實(shí)現(xiàn)如共同關(guān)注、共同喜好、二度好友等功能,對(duì)上面的所有集合操作,你還可以使用不同的命令選擇將結(jié)果返回給客戶端還是存集到一個(gè)新的集合中。
4.Sorted Sets(有序集合)
和Sets相比,Sorted Sets增加了一個(gè)權(quán)重參數(shù)score,使得集合中的元素能夠按score進(jìn)行有序排列,比如一個(gè)存儲(chǔ)全班同學(xué)成績(jī)的Sorted Sets,其集合value可以是同學(xué)的學(xué)號(hào),而score就可以是其考試得分,這樣在數(shù)據(jù)插入集合的時(shí)候,就已經(jīng)進(jìn)行了天然的排序。另外還可以用Sorted Sets來(lái)做帶權(quán)重的隊(duì)列,比如普通消息的score為1,重要消息的score為2,然后工作線程可以選擇按score的倒序來(lái)獲取工作任務(wù)。讓重要的任務(wù)優(yōu)先執(zhí)行。
Redis的有序集合類似于 Redis 的集合,但是存儲(chǔ)的值在集合中具有唯一性。另外有序集合的每個(gè)成員都使用分值(score)的東西,這個(gè)分值就是用于將有序集合排序,從分值最小到最大來(lái)排序。
在 Redis 有序集合添加,刪除和測(cè)試成員的存在的時(shí)間復(fù)雜度為 O(1)(恒定時(shí)間,無(wú)論集合內(nèi)包含元素的數(shù)量)。列表的最大長(zhǎng)度為 232 - 1 個(gè)元素(4294967295,每個(gè)集合的元素超過(guò)四十億)。
5.Pub/Sub(Redis發(fā)布訂閱)
Pub/Sub 從字面上理解就是發(fā)布(Publish)與訂閱(Subscribe),在Redis中,你可以設(shè)定對(duì)某一個(gè)key值進(jìn)行消息發(fā)布及消息訂閱,當(dāng)一個(gè)key值上進(jìn)行了消息發(fā)布后,所有訂閱它的客戶端都會(huì)收到相應(yīng)的消息。這一功能最明顯的用法就是用作實(shí)時(shí)消息系統(tǒng),比如普通的即時(shí)聊天,群聊等功能。
Redis訂閱和發(fā)布實(shí)現(xiàn)了通訊系統(tǒng),發(fā)件人(在 Redis 中的術(shù)語(yǔ)稱為發(fā)布者)發(fā)送郵件,而接收器(訂戶)接收它們。信息傳輸?shù)逆溌贩Q為通道。Redis 一個(gè)客戶端可以訂閱任意數(shù)量的通道。
示例
6.Transactions(Redis事務(wù))
誰(shuí)說(shuō)NoSQL都不支持事務(wù),雖然Redis的Transactions提供的并不是嚴(yán)格的ACID的事務(wù)(比如一串用EXEC提交執(zhí)行的命令,在執(zhí)行中服務(wù)器宕機(jī),那么會(huì)有一部分命令執(zhí)行了,剩下的沒(méi)執(zhí)行),但是這個(gè)Transactions還是提供了基本的命令打包執(zhí)行的功能(在服務(wù)器不出問(wèn)題的情況下,可以保證一連串的命令是順序在一起執(zhí)行的,中間有會(huì)有其它客戶端命令插進(jìn)來(lái)執(zhí)行)。Redis還提供了一個(gè)Watch功能,你可以對(duì)一個(gè)key進(jìn)行Watch,然后再執(zhí)行Transactions,在這過(guò)程中,如果這個(gè)Watched的值進(jìn)行了修改,那么這個(gè)Transactions會(huì)發(fā)現(xiàn)并拒絕執(zhí)行。
Redis事務(wù)允許一組命令在單一步驟中執(zhí)行。事務(wù)有兩個(gè)屬性,說(shuō)明如下:
在一個(gè)事務(wù)中的所有命令作為單個(gè)獨(dú)立的操作順序執(zhí)行。在Redis事務(wù)中的執(zhí)行過(guò)程中而另一客戶機(jī)發(fā)出的請(qǐng)求,這是不可以的;
Redis事務(wù)是原子的。原子意味著要么所有的命令都執(zhí)行,要么都不執(zhí)行;
二、Redis使用示范
1.Redis HyperLogLog
Redis HyperLogLog 是用來(lái)做基數(shù)統(tǒng)計(jì)的算法,HyperLogLog 的優(yōu)點(diǎn)是,在輸入元素的數(shù)量或者體積非常非常大時(shí),計(jì)算基數(shù)所需的空間總是固定 的、并且是很小的。
在 Redis 里面,每個(gè) HyperLogLog 鍵只需要花費(fèi) 12 KB 內(nèi)存,就可以計(jì)算接近 2^64 個(gè)不同元素的基 數(shù)。這和計(jì)算基數(shù)時(shí),元素越多耗費(fèi)內(nèi)存就越多的集合形成鮮明對(duì)比。但是,因?yàn)?HyperLogLog 只會(huì)根據(jù)輸入元素來(lái)計(jì)算基數(shù),而不會(huì)儲(chǔ)存輸入元素本身,所以 HyperLogLog 不能像集合那樣,返回輸入的各個(gè)元素。
示例
下面的例子說(shuō)明了 HyperLogLog Redis 的工作原理:
redis 127.0.0.1:6379> PFADD tutorials redis
1) (integer) 1
redis 127.0.0.1:6379> PFADD tutorials mongodb
1) (integer) 1
redis 127.0.0.1:6379> PFADD tutorials mysql
1) (integer) 1
redis 127.0.0.1:6379> PFCOUNT tutorials
(integer) 3
2.Redis鍵
Redis 中的 keys 命令用于管理 redis 中的鍵。Redis keys命令使用的語(yǔ)法如下所示:
語(yǔ)法
redis 127.0.0.1:6379> COMMAND KEY_NAME
示例
redis 127.0.0.1:6379> SET yiibai redis
OK
redis 127.0.0.1:6379> DEL yiibai
(integer) 1
在上面的例子中 DEL 是一個(gè)命令,而 yiibai 是一個(gè)鍵。如果鍵被成功刪除,則該命令的輸出將是(整數(shù))1,否則這將是(整數(shù))0;
3.Redis腳本
Redis 腳本是使用Lua解釋腳本用來(lái)評(píng)估(計(jì)算)。從 Redis 2.6.0 版本開(kāi)始內(nèi)置這個(gè)解釋器。命令 EVAL 用于執(zhí)行 腳本命令。
語(yǔ)法
EVAL命令的基本語(yǔ)法如下:
redis 127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]
示例
下面的例子說(shuō)明了 Redis 腳本是如何工作的:
redis 127.0.0.1:6379> EVAL return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]} 2 key1
key2 first second
1) key1
2) key2
3) first
4) second
3.Redis備份
Redis的SAVE命令用于創(chuàng)建當(dāng)前 Redis 數(shù)據(jù)庫(kù)的備份。
語(yǔ)法
Redis 的 SAVE 命令的基本語(yǔ)法如下所示:
127.0.0.1:6379> SAVE
示例
以下示例顯示了如何在Redis的當(dāng)前數(shù)據(jù)庫(kù)中創(chuàng)建備份。
127.0.0.1:6379> SAVE OK
在執(zhí)行此命令之后,將在 redis 目錄中創(chuàng)建一個(gè) dump.rdb 文件。
恢復(fù) Redis 數(shù)據(jù)
要恢復(fù) redis 數(shù)據(jù)只需要要將 Redis 的備份文件(dump.rdb)放到 Redis 的目錄中,并啟動(dòng)服務(wù)器。要了解知道 Redis 目錄在什么位置,可使用 CONFIG 命令,如下所示:
127.0.0.1:6379> CONFIG get dir
1) dir
2) /user/yiibai/redis-2.8.13/src
在上面的命令命令輸出為 /user/yiibai/redis-2.8.13/src 就是使用的 Redis 目錄,也就是 Redis 的服務(wù)器安裝的目錄。
4.Bgsave
創(chuàng)建 Redis 的備份也可以使用備用命令 BGSAVE 。此命令將啟動(dòng)備份過(guò)程,并在后臺(tái)運(yùn)行此。
示例
127.0.0.1:6379> BGSAVE Background saving started
Redis安全
Redis 數(shù)據(jù)庫(kù)可以配置安全保護(hù)的,所以任何客戶端在連接執(zhí)行命令時(shí)需要進(jìn)行身份驗(yàn)證。為了確保 Redis 的安全,需要在配置文件設(shè)置密碼。
示例
下面給出的例子顯示的步驟是用來(lái)確保 Redis 實(shí)例的安全。
127.0.0.1:6379> CONFIG get requirepass 1) requirepass 2)
默認(rèn)情況下此屬性是空的,這意味著此實(shí)例沒(méi)有設(shè)置密碼??梢酝ㄟ^(guò)執(zhí)行以下命令來(lái)修改設(shè)置此屬性
127.0.0.1:6379> CONFIG set requirepass yiibaipass
OK
127.0.0.1:6379> CONFIG get requirepass
1) requirepass
2) yiibaipass
如果客戶端運(yùn)行命令無(wú)需驗(yàn)證設(shè)置密碼,那么(錯(cuò)誤)NOAUTH 需要驗(yàn)證。錯(cuò)誤將返回。因此,客戶端需要使用 AUTH 命令來(lái)驗(yàn)證自己的身份信息。
語(yǔ)法
AUTH命令的基本語(yǔ)法如下所示:
127.0.0.1:6379> AUTH password
5.Redis性能測(cè)試
Redis的基準(zhǔn)性能測(cè)試是通過(guò)同時(shí)運(yùn)行 N 個(gè)命令以檢查 Redis 性能的工具。
語(yǔ)法
Redis的基準(zhǔn)測(cè)試的基本語(yǔ)法如下所示:
redis-benchmark [option] [option value]
示例
下面給出的示例是通過(guò)調(diào)用 100000 個(gè)(次)命令來(lái)檢查 Redis。
redis-benchmark -n 100000
PING_INLINE: 141043.72 requests per second
PING_BULK: 142857.14 requests per second
SET: 141442.72 requests per second
GET: 145348.83 requests per second
INCR: 137362.64 requests per second
LPUSH: 145348.83 requests per second
LPOP: 146198.83 requests per second
SADD: 146198.83 requests per second
SPOP: 149253.73 requests per second
LPUSH (needed to benchmark LRANGE): 148588.42 requests per second
LRANGE_100 (first 100 elements): 58411.21 requests per second
LRANGE_300 (first 300 elements): 21195.42 requests per second
LRANGE_500 (first 450 elements): 14539.11 requests per second
LRANGE_600 (first 600 elements): 10504.20 requests per second
MSET (10 keys): 93283.58 requests per second
6.Redis客戶端連接
如果啟用了Redis 的接受配置監(jiān)聽(tīng),客戶端可在TCP端口上與Unix套接字連接。以下操作執(zhí)行后新的客戶端連接被服務(wù)器接受:
客戶端套接字在非阻塞狀態(tài),因?yàn)?Redis 使用復(fù)用和非阻塞I/O;
TCP_NODELAY選項(xiàng)設(shè)定以確保不會(huì)在連接時(shí)延遲;
創(chuàng)建一個(gè)可讀的文件事件,以便 Redis 能夠盡快收集客戶端查詢作為新的數(shù)據(jù)可被套接字讀??;
客戶端最大連接數(shù)量
在Redis的配置文件(redis.conf)有一個(gè)屬性 maxclients ,它描述了可以連接到 Redis 的客戶的最大數(shù)量。命令的基本語(yǔ)法是:
config get maxclients
1) maxclients
2) 10000
默認(rèn)情況下此屬性設(shè)置為 10000(取決于OS的文件標(biāo)識(shí)符限制最大數(shù)量),但可以修改這個(gè)屬性。
示例
在下面給出的例子我們已經(jīng)設(shè)置客戶端最大連接數(shù)量為 100000,在之后啟動(dòng)服務(wù)器:
redis-server --maxclients 100000
7.Redis管道
Redis是一個(gè)TCP服務(wù)器,支持請(qǐng)求/響應(yīng)協(xié)議。在 redis 中一個(gè)請(qǐng)求完成以下步驟:
客戶端發(fā)送一個(gè)查詢給服務(wù)器,并從套接字中讀取,通常服務(wù)器的響應(yīng)是在一個(gè)封閉的方式;
服務(wù)器處理命令并將響應(yīng)返回給客戶端;
管道的含義求給服務(wù)器,而不等待全部響應(yīng),最后在單個(gè)步驟中讀取所有響應(yīng)。
管道的基本含義是:客戶端可以發(fā)送多個(gè)請(qǐng)
示例
要檢查 Redis 管道只需要啟動(dòng) Redis 實(shí)例,并在終端輸入以下命令。
$(echo -en PING
SET tutorial redis
GET tutorial
INCR visitor
INCR
visitor
INCR visitor
; sleep 10) | nc localhost 6379
PONG
OK
redis
:1
:2
:3
在上面的例子所示,了解使用 PING 命令連接 Redis,之后我們?cè)?Redis 設(shè)定一個(gè)名為 tutorial 字符串值,之后拿到這個(gè)鍵對(duì)應(yīng)的值并增加訪問(wèn)人數(shù)的三倍。在結(jié)果中,我們可以看到所有的命令都提交給 Redis 一次,Redis是給單步輸出所有命令。
通道的好處
這種技術(shù)的好處是顯著提高協(xié)議的性能。管道localhost 獲得至少達(dá)到百倍的網(wǎng)絡(luò)連接速度。
好了,本文就先說(shuō)到這里,上面這些這只是Redis API的一些使用方式,可謂冰山一角,Redis就像一把瑞士軍刀一樣(或者是更萬(wàn)能的中國(guó)軍鏟),它創(chuàng)造了一系列更接近于應(yīng)用場(chǎng)景的數(shù)據(jù)結(jié)構(gòu)和API,目的在于讓我們更直接的基于應(yīng)用場(chǎng)景進(jìn)行存儲(chǔ)設(shè)計(jì)。更多的應(yīng)用場(chǎng)景和組合式的應(yīng)用還有待您自己的發(fā)掘。
三、總結(jié)
1.查詢的字段加組合索引,在用戶和數(shù)據(jù)庫(kù)中增加緩存
2.添加索引方案:面對(duì)1~2千的并發(fā)是沒(méi)有壓力的,在往上則限制的瓶頸就是數(shù)據(jù)庫(kù)最大連接數(shù)了,超過(guò)這個(gè)數(shù)tomcat直接報(bào)錯(cuò)連接被拒絕或者連接已經(jīng)失效
3.緩存方案:事先把數(shù)據(jù)庫(kù)的千萬(wàn)條數(shù)據(jù)同步到redis緩存中,瓶頸就是硬件設(shè)備性能,換上主機(jī)有幾百個(gè)核心CPU,就算是千萬(wàn)級(jí)的并發(fā)下也可以完全無(wú)壓力,帶個(gè)用戶很好的體驗(yàn),容聯(lián)的短信端口并發(fā)也是使用的這種緩存方式。
4.索引 緩存方案:緩存事先沒(méi)有要查詢的數(shù)據(jù),在一萬(wàn)的并發(fā)下測(cè)試數(shù)據(jù)庫(kù)毫無(wú)壓力,程序先通過(guò)查緩存再查數(shù)據(jù)庫(kù)大大減輕了數(shù)據(jù)庫(kù)的壓力,即使緩存不命中在一萬(wàn)的并發(fā)下也能正常訪問(wèn),在10萬(wàn)并發(fā)下數(shù)據(jù)庫(kù)依然沒(méi)壓力,但是redis服務(wù)器設(shè)置最大連接數(shù)300去處理10萬(wàn)的線程,4核CPU處理不過(guò)來(lái),很多redis連接不了。我用show global status like 'Max_used_connections'查看數(shù)據(jù)庫(kù)發(fā)現(xiàn)最大響應(yīng)連接數(shù)是388,這么低所以數(shù)據(jù)庫(kù)是不會(huì)掛掉的。
5.使用場(chǎng)景:a.幾百或者2000以下并發(fā)直接加上組合索引就可以了。b.不想加索引又高并發(fā)的情況下可以先事先把數(shù)據(jù)放到緩存中,硬件設(shè)備支持下可解決百萬(wàn)級(jí)并發(fā)。c.加索引且緩存事先沒(méi)有數(shù)據(jù),在硬件設(shè)備支持下可解決百萬(wàn)級(jí)并發(fā)問(wèn)題。d.不加索引且緩存事先沒(méi)有數(shù)據(jù),不可取,要80多秒才能得到結(jié)果,用戶體驗(yàn)極差。
6.原理:其實(shí)使用了redis的話為什么數(shù)據(jù)庫(kù)不會(huì)崩潰是因?yàn)閞edis最大連接數(shù)為300,這樣數(shù)據(jù)庫(kù)最大同時(shí)連接數(shù)也是300多,所以不會(huì)掛掉,至于redis為什么設(shè)置為300是因?yàn)樵O(shè)置的太高就會(huì)報(bào)錯(cuò)(連接被拒絕)或者等待超時(shí)(就算設(shè)置等待超時(shí)的時(shí)間很長(zhǎng)也會(huì)報(bào)這個(gè)錯(cuò))。