Redis
- 概念: redis是一款高性能的NOSQL系列的非關(guān)系型數(shù)據(jù)庫
- 什么是NOSQL
NoSQL(NoSQL = Not Only SQL)愉适,意即“不僅僅是SQL”,是一項(xiàng)全新的數(shù)據(jù)庫理念严蓖,泛指非關(guān)系型的數(shù)據(jù)庫。
隨著互聯(lián)網(wǎng)web2.0網(wǎng)站的興起,傳統(tǒng)的關(guān)系數(shù)據(jù)庫在應(yīng)付web2.0網(wǎng)站雷激,特別是超大規(guī)模和高并發(fā)的SNS類型的web2.0純動(dòng)態(tài)網(wǎng)站已經(jīng)顯得力不從心访圃,暴露了很多難以克服的問題厨幻,而非關(guān)系型的數(shù)據(jù)庫則由于其本身的特點(diǎn)得到了非常迅速的發(fā)展。NoSQL數(shù)據(jù)庫的產(chǎn)生就是為了解決大規(guī)模數(shù)據(jù)集合多重?cái)?shù)據(jù)種類帶來的挑戰(zhàn)腿时,尤其是大數(shù)據(jù)應(yīng)用難題况脆。
- NOSQL和關(guān)系型數(shù)據(jù)庫比較
- 優(yōu)點(diǎn):
- 成本:nosql數(shù)據(jù)庫簡單易部署,基本都是開源軟件批糟,不需要像使用oracle那樣花費(fèi)大量成本購買使用格了,相比關(guān)系型數(shù)據(jù)庫價(jià)格便宜。
- 查詢速度:nosql數(shù)據(jù)庫將數(shù)據(jù)存儲(chǔ)于緩存之中徽鼎,關(guān)系型數(shù)據(jù)庫將數(shù)據(jù)存儲(chǔ)在硬盤中盛末,自然查詢速度遠(yuǎn)不及nosql數(shù)據(jù)庫。
- 存儲(chǔ)數(shù)據(jù)的格式:nosql的存儲(chǔ)格式是key,value形式纬傲、文檔形式满败、圖片形式等等,所以可以存儲(chǔ)基礎(chǔ)類型以及對象或者是集合等各種格式叹括,而數(shù)據(jù)庫則只支持基礎(chǔ)類型算墨。
- 擴(kuò)展性:關(guān)系型數(shù)據(jù)庫有類似join這樣的多表查詢機(jī)制的限制導(dǎo)致擴(kuò)展很艱難。
- 缺點(diǎn):
- 維護(hù)的工具和資料有限汁雷,因?yàn)閚osql是屬于新的技術(shù)净嘀,不能和關(guān)系型數(shù)據(jù)庫10幾年的技術(shù)同日而語。
- 不提供對sql的支持侠讯,如果不支持sql這樣的工業(yè)標(biāo)準(zhǔn)挖藏,將產(chǎn)生一定用戶的學(xué)習(xí)和使用成本。
- 不提供關(guān)系型數(shù)據(jù)庫對事務(wù)的處理厢漩。
- 非關(guān)系型數(shù)據(jù)庫的優(yōu)勢:
- 性能NOSQL是基于鍵值對的膜眠,可以想象成表中的主鍵和值的對應(yīng)關(guān)系,而且不需要經(jīng)過SQL層的解析溜嗜,所以性能非常高宵膨。
- 可擴(kuò)展性同樣也是因?yàn)榛阪I值對,數(shù)據(jù)之間沒有耦合性炸宵,所以非常容易水平擴(kuò)展辟躏。
- 關(guān)系型數(shù)據(jù)庫的優(yōu)勢:
- 復(fù)雜查詢可以用SQL語句方便的在一個(gè)表以及多個(gè)表之間做非常復(fù)雜的數(shù)據(jù)查詢。
- 事務(wù)支持使得對于安全性能很高的數(shù)據(jù)訪問要求得以實(shí)現(xiàn)土全。對于這兩類數(shù)據(jù)庫捎琐,對方的優(yōu)勢就是自己的弱勢会涎,反之亦然。
總結(jié):
關(guān)系型數(shù)據(jù)庫與NoSQL數(shù)據(jù)庫并非對立而是互補(bǔ)的關(guān)系瑞凑,即通常情況下使用關(guān)系型數(shù)據(jù)庫末秃,在適合使用NoSQL的時(shí)候使用NoSQL數(shù)據(jù)庫,讓NoSQL數(shù)據(jù)庫對關(guān)系型數(shù)據(jù)庫的不足進(jìn)行彌補(bǔ)拨黔。一般會(huì)將數(shù)據(jù)存儲(chǔ)在關(guān)系型數(shù)據(jù)庫中蛔溃,在nosql數(shù)據(jù)庫中備份存儲(chǔ)關(guān)系型數(shù)據(jù)庫的數(shù)據(jù)
- 主流的NOSQL產(chǎn)品
redis、memcached篱蝇、mongodb贺待、guava(loadingCache)
- 鍵值(Key-Value)存儲(chǔ)數(shù)據(jù)庫
- 相關(guān)產(chǎn)品: Tokyo Cabinet/Tyrant、Redis零截、Voldemort麸塞、Berkeley DB
- 典型應(yīng)用: 內(nèi)容緩存,主要用于處理大量數(shù)據(jù)的高訪問負(fù)載涧衙。
- 數(shù)據(jù)模型: 一系列鍵值對
- 優(yōu)勢: 快速查詢
- 劣勢: 存儲(chǔ)的數(shù)據(jù)缺少結(jié)構(gòu)化
- 列存儲(chǔ)數(shù)據(jù)庫
- 相關(guān)產(chǎn)品:Cassandra, HBase, Riak
- 典型應(yīng)用:分布式的文件系統(tǒng)
- 數(shù)據(jù)模型:以列簇式存儲(chǔ)哪工,將同一列數(shù)據(jù)存在一起
- 優(yōu)勢:查找速度快,可擴(kuò)展性強(qiáng)弧哎,更容易進(jìn)行分布式擴(kuò)展
- 劣勢:功能相對局限
- 文檔型數(shù)據(jù)庫
- 相關(guān)產(chǎn)品:CouchDB雁比、MongoDB
- 典型應(yīng)用:Web應(yīng)用(與Key-Value類似,Value是結(jié)構(gòu)化的)
- 數(shù)據(jù)模型: 一系列鍵值對
- 優(yōu)勢:數(shù)據(jù)結(jié)構(gòu)要求不嚴(yán)格
- 劣勢: 查詢性能不高撤嫩,而且缺乏統(tǒng)一的查詢語法
- 圖形(Graph)數(shù)據(jù)庫
- 相關(guān)數(shù)據(jù)庫:Neo4J偎捎、InfoGrid、Infinite Graph
- 典型應(yīng)用:社交網(wǎng)絡(luò)
- 數(shù)據(jù)模型:圖結(jié)構(gòu)
- 優(yōu)勢:利用圖結(jié)構(gòu)相關(guān)算法序攘。
- 劣勢:需要對整個(gè)圖做計(jì)算才能得出結(jié)果茴她,不容易做分布式的集群方案。
redis和memcached各有什么優(yōu)勢
- 內(nèi)存管理機(jī)制
- Memcached默認(rèn)使用Slab Allocation機(jī)制管理內(nèi)存程奠,其主要思想是按照預(yù)先規(guī)定的大小丈牢,將分配的內(nèi)存分割成特定長度的塊 以存儲(chǔ)相應(yīng)長度的key-value數(shù)據(jù)記錄,以完全解決內(nèi)存碎片問題瞄沙〖号妫空閑列表進(jìn)行判斷存儲(chǔ)狀態(tài)
- Redis使用現(xiàn)場申請內(nèi)存的方式來存儲(chǔ)數(shù)據(jù),并且很少使用free-list(空閑列表)等方式來優(yōu)化內(nèi)存分配距境,會(huì)在一定程度上存在內(nèi)存碎片【CPU內(nèi)存是連續(xù)泛粹,類似于Java虛擬機(jī)對象的分配,直接內(nèi)存分配(指針碰撞)】
如上肮疗,memcached預(yù)先定義很多內(nèi)存大小的空間,并記錄扒接,然后根據(jù)存儲(chǔ)數(shù)據(jù)的大小來選擇那種大小的空間伪货,而redis則是直接存儲(chǔ)们衙,即使120一段,實(shí)際存儲(chǔ)的數(shù)據(jù)只占用20碱呼,那么就浪費(fèi)了100的內(nèi)存蒙挑。
-
數(shù)據(jù)持久化方案
- memcached不支持內(nèi)存數(shù)據(jù)的持久化操作,所有的數(shù)據(jù)都以in-memory的形式存儲(chǔ)愚臀。
- redis支持持久化操作忆蚀。redis提供了兩種不同的持久化方法來講數(shù)據(jù)存儲(chǔ)到硬盤里面,
- 第一種是rdb形式姑裂,一種是aof形式
- rdb:屬于全量數(shù)據(jù)備份馋袜,備份的是數(shù)據(jù)
- aof:append only if,增量持久化備份,備份的是指令[如:set key舶斧, del key]
- 第一種是rdb形式姑裂,一種是aof形式
-
緩存數(shù)據(jù)過期機(jī)制
- Memcached 在刪除失效主鍵時(shí)也是采用的消極方法欣鳖,即 Memcached 內(nèi)部也不會(huì)監(jiān)視主鍵是否失效,而是在通過 Get 訪問主鍵時(shí)才會(huì)檢查其是否已經(jīng)失效
- Redis 定時(shí)茴厉、定期等多種緩存失效機(jī)制泽台,減少內(nèi)存泄漏
-
支持的數(shù)據(jù)類型
- Memcached支持單一數(shù)據(jù)類型,[k,v]
- redis支持五種數(shù)據(jù)類型
什么是Redis
Redis是用C語言開發(fā)的一個(gè)開源的高性能鍵值對(key-value)數(shù)據(jù)庫,官方提供測試數(shù)據(jù)矾缓,50個(gè)并發(fā)執(zhí)行100000個(gè)請求,讀的速度是110000次/s,寫的速度是81000次/s 怀酷,且Redis通過提供多種鍵值數(shù)據(jù)類型來適應(yīng)不同場景下的存儲(chǔ)需求,目前為止Redis支持的鍵值數(shù)據(jù)類型如下:
- 字符串類型 string
- 哈希類型 hash
- 列表類型 list
- 集合類型 set
- 有序集合類型 sortedset
redis的應(yīng)用場景
- 緩存(數(shù)據(jù)查詢嗜闻、短連接蜕依、新聞內(nèi)容、商品內(nèi)容等等)
- 作為mybatis/hibernate二級(jí)緩存(mapper緩存)使用方案泞辐,當(dāng)然其默認(rèn)也有一級(jí)方案笔横,只不過是內(nèi)存緩存
- 解釋下一級(jí)緩存:sqlSession緩存,進(jìn)程緩存咐吼,單次鏈接有效吹缔;當(dāng)使用了clearCache方法和,或者close方法的話锯茄,這個(gè)緩存失效厢塘,如果還有同樣的查詢,則還會(huì)發(fā)送一次查詢
- 聊天室的在線好友列表
- 任務(wù)隊(duì)列肌幽。(秒殺晚碾、搶購、12306等等)
- 應(yīng)用排行榜
- 網(wǎng)站訪問統(tǒng)計(jì)
- 數(shù)據(jù)過期處理(可以精確到毫秒
- 分布式集群架構(gòu)中的session分離
redis作為數(shù)據(jù)庫的使用有什么優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn):沒有Scheme約束喂急,數(shù)據(jù)結(jié)構(gòu)的變更相對容易格嘁,一開始確定數(shù)據(jù)類型,抗壓能力強(qiáng)廊移,性能極高糕簿,10萬/qps
- 缺點(diǎn):沒有索引探入,沒有外鍵,缺少int/date等基本數(shù)據(jù)類型懂诗,多條件查詢需要通過集合內(nèi)聯(lián)(sinter,zinterstore) 和連接間接實(shí)現(xiàn)開發(fā)效率低蜂嗽,可維護(hù)性不佳
下載安裝方式一
- 官網(wǎng):https://redis.io
- 中文網(wǎng):http://www.redis.net.cn/
- 解壓直接可以使用:
- redis.windows.conf:配置文件
- redis-cli.exe:redis的客戶端
- redis-server.exe:redis服務(wù)器端
下載安裝方式二
-
解決could not retrieve mirrorlist,
- sudo vim /etc/sysconfig/network-scripts/ifcfg-ens33
- 將ONBOOT改為yes殃恒,wq!保存退出
- 重新啟動(dòng)網(wǎng)絡(luò)
$ service network restart
安裝wget : yum -y install wget
下載redis安裝包
- 解壓壓縮包
tar -zxvf redis-4.0.6.tar.gz
- yum install gcc
- 跳轉(zhuǎn)到redis解壓目錄下 cd redis-4.0.6
- 編譯安裝
- make MALLOC=libc
- cd src && make install
- 測試是否安裝成功
cd src ./redis-server
redis三種啟動(dòng)方式以及其中的使用區(qū)別
- 直接啟動(dòng)
cd src ./redis-server
- 通過指定配置文件啟動(dòng)
- 首先修改redis.conf文件(在根目錄下)的daemonize no為yes
- 可以輸入/然后輸入dae按下enter這樣就可以搜索到然后保存
- 進(jìn)入redis的目錄下的src目錄植旧,然后執(zhí)行以下,就是守護(hù)進(jìn)程啟動(dòng)
./redis-server /usr/local/redis-4.0.6/redis.conf
可以通過下面方式測試是否啟動(dòng)成功 : ./redis-cli -p 6379
- 補(bǔ)充
- 針對守護(hù)進(jìn)程啟動(dòng)的方式關(guān)閉進(jìn)程:
- 查詢進(jìn)程信息 ps -ef|grep redis
- 關(guān)閉進(jìn)程: kill -9 8370
8370是進(jìn)程號(hào)离唐,而且會(huì)有倆進(jìn)程病附,找到server那個(gè)即可,一般第一個(gè)
- 使用redis啟動(dòng)腳本設(shè)置開機(jī)自啟動(dòng)
- linux配置開啟自啟動(dòng)腳本都在這個(gè)文件夾下面 /etc/init.d,系統(tǒng)啟動(dòng)的時(shí)候會(huì)自動(dòng)執(zhí)行該文件夾下面的腳本侯繁,所以把redis啟動(dòng)腳本移動(dòng)進(jìn)來即可
- 啟動(dòng)腳本 redis_init_script 位于Redis的 /utils/ 目錄下 (redis提供的)
- mkdir /etc/redis
- cp redis.conf /etc/redis/6379.conf
- 將啟動(dòng)腳本復(fù)制到/etc/init.d目錄下胖喳,本例將啟動(dòng)腳本命名為redisd(通常都以d結(jié)尾表示是后臺(tái)自啟動(dòng)服務(wù))
- cp redis_init_script /etc/init.d/redisd
- 設(shè)置為開機(jī)自啟動(dòng),直接配置開啟自啟動(dòng) chkconfig redisd on 發(fā)現(xiàn)錯(cuò)誤: service redisd does not support chkconfig
- 解決辦法贮竟,在啟動(dòng)腳本開頭添加如下注釋來修改運(yùn)行級(jí)別(修改腳本修改的是:/etc/init.d/redisd)
#!/bin/sh # chkconfig: 2345 90 10
- 設(shè)置開機(jī)自啟:chkconfig redisd on
- 驗(yàn)證是否啟動(dòng): service redisd start,如果提示已啟動(dòng)則可證明設(shè)置開機(jī)自啟成功了
打開服務(wù): service redisd start #關(guān)閉服務(wù) : service redisd stop
命令操作
- 選擇數(shù)據(jù)庫
redis默認(rèn)有16個(gè)數(shù)據(jù)庫丽焊,不選擇的話寫入默認(rèn)是0數(shù)據(jù)庫,但是可以手動(dòng)指定
select 0
- redis的數(shù)據(jù)結(jié)構(gòu):
- redis存儲(chǔ)的是:key,value格式的數(shù)據(jù)咕别,其中key都是字符串技健,value有5種不同的數(shù)據(jù)結(jié)構(gòu)
- value的數(shù)據(jù)結(jié)構(gòu):
- 字符串類型 string
- 哈希類型 hash : map格式
- 列表類型 list : linkedlist格式。支持重復(fù)元素
- 集合類型 set : 不允許重復(fù)元素
- 有序集合類型 sortedset:不允許重復(fù)元素惰拱,且元素有順序
- 字符串類型 string
- 存儲(chǔ): set key value
127.0.0.1:6379> set username zhangsan
OK - 獲却萍: get key
127.0.0.1:6379> get username
"zhangsan" - 刪除: del key
127.0.0.1:6379> del age
(integer) 1 - mget:批量獲取多個(gè)key的值,如果可以不存在則返回nil
- incr && incrby :incr對key對應(yīng)的值進(jìn)行加加操作偿短,并返回新的值;incrby加指定值
- decr && decrby:decr對key對應(yīng)的值進(jìn)行減減操作欣孤,并返回新的值;decrby減指定值
- setnx:設(shè)置key對應(yīng)的值為String類型的value澄耍,如果key已經(jīng)存在則返回0
- setex:設(shè)置key對應(yīng)的值為String類型的value颖医,并設(shè)定有效期
- 其他命令
- getrange: 獲取key對應(yīng)value的子字符串
- mset: 批量設(shè)置多個(gè)key的值,如果成功表示所有值都被設(shè)置钠署,否則返回0表示沒有任何值被設(shè)置
- msetnx: 同mset勾怒,不存在就設(shè)置婆排,不會(huì)覆蓋已有的key
- getset: 設(shè)置key的值,并返回key舊的值
- append: 給指定key的value追加字符串笔链,并返回新字符串的長度
- 存儲(chǔ): set key value
- 哈希類型 hash
- Hash是一個(gè)String類型的field和value之間的映射表段只,
- redis的Hash數(shù)據(jù)類型的key(hash表名稱)對應(yīng)的value實(shí)際的內(nèi)部存儲(chǔ)結(jié)構(gòu)為一個(gè)HashMap
- Hash特別適合存儲(chǔ)對象。
- 相對于把一個(gè)對象的每個(gè)屬性存儲(chǔ)為String類型鉴扫,將整個(gè)對象存儲(chǔ)在Hash類型中會(huì)占用更少內(nèi)存赞枕。
- 所存儲(chǔ)的成員較少時(shí)數(shù)據(jù)存儲(chǔ)為zipmap,當(dāng)成員數(shù)量增大時(shí)會(huì)自動(dòng)轉(zhuǎn)成真正的HashMap,此時(shí)encoding為ht。
- 運(yùn)用場景:如用一個(gè)對象來存儲(chǔ)用戶信息鹦赎,商品信息谍椅,訂單信息等等。
-
存儲(chǔ): hset key field value
- 127.0.0.1:6379> hset myhash username lisi
(integer) 1 - 127.0.0.1:6379> hset myhash password 123
(integer) 1
- 127.0.0.1:6379> hset myhash username lisi
-
獲裙呕啊:
- hget key field: 獲取指定的field對應(yīng)的值
127.0.0.1:6379> hget myhash username
"lisi" - hgetall key:獲取所有的field和value
127.0.0.1:6379> hgetall myhash- "username"
- "lisi"
- "password"
- "123"
- hget key field: 獲取指定的field對應(yīng)的值
刪除: hdel key field
127.0.0.1:6379> hdel myhash username
(integer) 1hlen--返回key對應(yīng)的HashMap中的field的數(shù)量
-
- 列表類型 list:可以添加一個(gè)元素到列表的頭部(左邊)或者尾部(右邊)
- 添加:
lpush key value: 將元素加入列表左表
-
rpush key value:將元素加入列表右邊
127.0.0.1:6379> lpush myList a (integer) 1 127.0.0.1:6379> lpush myList b (integer) 2 127.0.0.1:6379> rpush myList c (integer) 3
- 獲取:
- lrange key start end :范圍獲取
127.0.0.1:6379> lrange myList 0 -1- "b"
- "a"
- "c"
- lrange key start end :范圍獲取
- 刪除:
- lpop key: 刪除列表最左邊的元素锁施,并將元素返回
- rpop key: 刪除列表最右邊的元素陪踩,并將元素返回
- 添加:
-
集合類型 set : 不允許重復(fù)元素
- 存儲(chǔ):sadd key value
- 127.0.0.1:6379> sadd myset a
(integer) 1 - 127.0.0.1:6379> sadd myset a
(integer) 0
- 127.0.0.1:6379> sadd myset a
- 獲取:smembers key:獲取set集合中所有元素
- 127.0.0.1:6379> smembers myset
1) "a"
- 127.0.0.1:6379> smembers myset
- 刪除:srem key value:刪除set集合中的某個(gè)元素
- 127.0.0.1:6379> srem myset a
(integer) 1
- 127.0.0.1:6379> srem myset a
- spop——隨機(jī)返回并刪除key對應(yīng)的set中的一個(gè)元素
- suion——求給定key對應(yīng)的set并集
- sinter——求給定key對應(yīng)的set交集
- 存儲(chǔ):sadd key value
-
有序集合類型 sortedset:不允許重復(fù)元素悉抵,且元素有順序.每個(gè)元素都會(huì)關(guān)聯(lián)一個(gè)double類型的分?jǐn)?shù)肩狂。redis正是通過分?jǐn)?shù)來為集合中的成員進(jìn)行從小到大的排序。
- 存儲(chǔ):zadd key score value
- 127.0.0.1:6379> zadd mysort 60 zhangsan
(integer) 1 - 127.0.0.1:6379> zadd mysort 50 lisi
(integer) 1 - 127.0.0.1:6379> zadd mysort 80 wangwu
(integer) 1
- 127.0.0.1:6379> zadd mysort 60 zhangsan
- 獲壤咽巍:zrange key start end [withscores] , -1表示獲取所有元素
-
127.0.0.1:6379> zrange mysort 0 -1
- "lisi"
- "zhangsan"
- "wangwu"
-
127.0.0.1:6379> zrange mysort 0 -1 withscores
- "zhangsan"
- "60"
- "wangwu"
- "80"
- "lisi"
- "500"
-
- 刪除:zrem key value ,刪除key對應(yīng)的zset中的一個(gè)元素
- 127.0.0.1:6379> zrem mysort lisi
(integer) 1
- 127.0.0.1:6379> zrem mysort lisi
- zrangebyscore——返回有序集key中傻谁,指定分?jǐn)?shù)范圍的元素列表,排行榜中運(yùn)用
- zrank——返回key對應(yīng)的zset中指定member的排名。其中member按score值遞增(從小到大)列粪;排名以0為底审磁,也就是說,score值最小的成員排名為0,排行榜中運(yùn)用
- 存儲(chǔ):zadd key score value
set是通過hashmap存儲(chǔ)岂座,key對應(yīng)set的元素态蒂,value是空對象;sortset是怎么存儲(chǔ)并實(shí)現(xiàn)排序的呢,hashmap存儲(chǔ)费什,還加了一層跳躍表;跳躍表:相當(dāng)于雙向鏈表钾恢,在其基礎(chǔ)上添加前往比當(dāng)前元素大的跳轉(zhuǎn)鏈接
- 通用命令
- keys * : 查詢所有的鍵
- type key : 獲取鍵對應(yīng)的value的類型
- del key:刪除指定的key value
- 持久化
- redis是一個(gè)內(nèi)存數(shù)據(jù)庫,當(dāng)redis服務(wù)器重啟鸳址,獲取電腦重啟瘩蚪,數(shù)據(jù)會(huì)丟失,我們可以將redis內(nèi)存中的數(shù)據(jù)持久化保存到硬盤的文件中稿黍。
- redis持久化機(jī)制:
-
RDB:默認(rèn)方式疹瘦,不需要進(jìn)行配置,默認(rèn)就使用這種機(jī)制
- 在一定的間隔時(shí)間中闻察,檢測key的變化情況拱礁,然后持久化數(shù)據(jù)
-
編輯redis.windwos.conf文件
- after 900 sec (15 min) if at least 1 key changed
save 900 1 - after 300 sec (5 min) if at least 10 keys changed
save 300 10 - after 60 sec if at least 10000 keys changed
save 60 10000
- after 900 sec (15 min) if at least 1 key changed
重新啟動(dòng)redis服務(wù)器,并指定配置文件名稱
D:\JavaWeb2018\day23_redis\資料\redis\windows-64\redis-2.8.9>redis-server.exe redis.windows.conf
-
AOF:日志記錄的方式辕漂,可以記錄每一條命令的操作呢灶。可以每一次命令操作后钉嘹,持久化數(shù)據(jù)
- 編輯redis.windwos.conf文件
- appendonly no(關(guān)閉aof) --> appendonly yes (開啟aof)
- appendfsync always : 每一次操作都進(jìn)行持久化
- appendfsync everysec : 每隔一秒進(jìn)行一次持久化
- appendfsync no : 不進(jìn)行持久化
- 編輯redis.windwos.conf文件
-
事務(wù)
- Redis事務(wù)可以一次執(zhí)行多個(gè)命令鸯乃,按順序串行化執(zhí)行,且執(zhí)行過程中不許加塞;
- 批量操作在發(fā)送 EXEC 命令前被放入隊(duì)列緩存;
- 收到 EXEC 命令后,進(jìn)入事務(wù)執(zhí)行缨睡,事務(wù)中任何命令執(zhí)行失敗鸟悴,其余命令依然被執(zhí)行;
- 在事務(wù)執(zhí)行過程中,其他客戶端提交的命令請求不會(huì)插入到事務(wù)執(zhí)行序列中;
- 總的來說奖年,Redis會(huì)將一個(gè)事務(wù)中的所有命令序列化细诸,然后按順序執(zhí)行,且不允許出現(xiàn)加塞行為.
- 事務(wù)經(jīng)歷的三個(gè)階段:開啟事務(wù) --> 命令入列 --> 執(zhí)行事務(wù);
- A向B轉(zhuǎn)賬
multi #開啟事務(wù)陋守,以后的命令會(huì)依次進(jìn)入到序列中
get account:a
get account:b
decrby account:a 50 #A減50
incrby account:b 50 #B加50
exec #執(zhí)行事務(wù) - discard:取消事務(wù)震贵,放棄隊(duì)列中的所有命令;開啟了事務(wù)水评,但不想執(zhí)行 exec 命令時(shí)猩系,可執(zhí)行 discard 命令取消事務(wù);
- 錯(cuò)誤處理:
- 如果隊(duì)列中的某個(gè)命令出現(xiàn)錯(cuò)誤,比如操作的key不存在中燥,屬于邏輯業(yè)務(wù)的錯(cuò)誤寇甸,那么這條命令不再執(zhí)行,
而其他命令仍照常執(zhí)行疗涉,而且不會(huì)回滾; - 但如果某個(gè)命令出現(xiàn)報(bào)告錯(cuò)誤(語法錯(cuò)誤)拿霉,比如輸入的命令不存在,Redis會(huì)立即報(bào)錯(cuò)博敬,那么Redis會(huì)取消事務(wù)友浸,
所有命令都不會(huì)執(zhí)行;
- 如果隊(duì)列中的某個(gè)命令出現(xiàn)錯(cuò)誤,比如操作的key不存在中燥,屬于邏輯業(yè)務(wù)的錯(cuò)誤寇甸,那么這條命令不再執(zhí)行,
- watch/unwatch
- 當(dāng)兩個(gè)事務(wù)同時(shí)操作同一個(gè)key時(shí),可能會(huì)導(dǎo)致數(shù)據(jù)的不一致;
- watch key key ... : 監(jiān)視key偏窝,在開啟事務(wù)之后收恢、執(zhí)行事務(wù)之前,這個(gè)key被其他命令改動(dòng)了祭往,
那么當(dāng)前事務(wù)將會(huì)被打斷伦意,并回滾; - unwatch:取消對所有key的監(jiān)視;
- 如果在執(zhí)行 watch 命令之后,只要執(zhí)行了 exec 或 discard 命令硼补,watch會(huì)自動(dòng)取消驮肉,無需再執(zhí)行 unwatch 命令.
- 應(yīng)用場景:
- 一組命令必須同時(shí)執(zhí)行,或者都不執(zhí)行;
- 保證一組命令在執(zhí)行過程中不被其他命令插入;
- 商品秒殺活動(dòng)已骇、轉(zhuǎn)賬;
為什么Redis回滾幾乎不用
Redis命令在事務(wù)中可能會(huì)執(zhí)行失敗离钝,但是Redis事務(wù)不會(huì)回滾,而是繼續(xù)會(huì)執(zhí)行余下的命令褪储。如果您有一個(gè)關(guān)系型數(shù)據(jù)庫的知識(shí)卵渴,這對您來說可能會(huì)感到奇怪,因?yàn)殛P(guān)系型數(shù)據(jù)在這種情況下都是會(huì)回滾的鲤竹。
Redis這樣做浪读,主要是因?yàn)?
只有當(dāng)發(fā)生語法錯(cuò)誤(這個(gè)問題在命令隊(duì)列時(shí)無法檢測到)了,Redis命令才會(huì)執(zhí)行失敗, 或?qū)eys賦予了一個(gè)類型錯(cuò)誤的數(shù)據(jù):這意味著這些都是程序性錯(cuò)誤,這類錯(cuò)誤在開發(fā)的過程中就能夠發(fā)現(xiàn)并解決掉碘橘,幾乎不會(huì)出現(xiàn)在生產(chǎn)環(huán)境互订。
由于不需要回滾,這使得Redis內(nèi)部更加簡單痘拆,而且運(yùn)行速度更快仰禽。
緩存問題
- 緩存穿透
- 查詢一個(gè)不存在數(shù)據(jù)時(shí),緩存中沒有错负,就需要從數(shù)據(jù)庫中查詢坟瓢,查不到數(shù)據(jù)就不寫入緩存中,導(dǎo)致每次請求
這個(gè)不存在的數(shù)據(jù)時(shí)犹撒,都要到數(shù)據(jù)庫中去查詢,造成緩存穿透; - 解決方式:持久層查詢不到數(shù)據(jù)時(shí)粒褒,就緩存一個(gè)空結(jié)果(空字符串)识颊,每次查詢時(shí)先判斷緩存中是否存在key,
如果有奕坟,則直接返回空值祥款,表示此數(shù)據(jù)不存在,否則就去查詢數(shù)據(jù)庫; - 另外月杉,持久層 insert 此數(shù)據(jù)時(shí)刃跛,及時(shí)清除查詢的key,或者設(shè)置空結(jié)果的緩存時(shí)間;
- 查詢一個(gè)不存在數(shù)據(jù)時(shí),緩存中沒有错负,就需要從數(shù)據(jù)庫中查詢坟瓢,查不到數(shù)據(jù)就不寫入緩存中,導(dǎo)致每次請求
- 緩存雪崩
- 如果緩存集中在一段時(shí)間內(nèi)失效苛萎,發(fā)生大量的緩存穿透桨昙,所有的查詢都落在數(shù)據(jù)庫上,造成緩存雪崩;
- 緩存雪崩沒有完美的解決方案腌歉,應(yīng)分析用戶行為蛙酪,盡量將緩存失效時(shí)間均勻分布;
- 大多數(shù)系統(tǒng)設(shè)計(jì)者會(huì)考慮加鎖/分布式鎖,或者隊(duì)列的方式來保證單線程/進(jìn)程去寫緩存翘盖,從而避免失效時(shí)
大量的并發(fā)請求落在數(shù)據(jù)庫上;
- 熱點(diǎn)key
- 某個(gè)key訪問非常頻繁桂塞,當(dāng)key失效時(shí),將會(huì)有大量線程來構(gòu)建緩存馍驯,導(dǎo)致負(fù)載增加阁危,系統(tǒng)崩潰;
- 解決方案:
- 使用鎖,單機(jī)使用synchronized汰瘫、lock等狂打,分布式使用分布式鎖;
- 不設(shè)置緩存過期時(shí)間,而是在對應(yīng)的value里設(shè)置一個(gè)時(shí)間吟吝,如果檢測到超過了這個(gè)時(shí)間菱父,則異步更新緩存;
- 在value里設(shè)置一個(gè)比過期時(shí)間t0小的過期時(shí)間t1,當(dāng)t1過期時(shí),延長t1浙宜,并更新緩存;
- 設(shè)置標(biāo)簽緩存官辽,并設(shè)置過期時(shí)間,標(biāo)簽緩存過期后粟瞬,異步更新實(shí)際緩存;
- 緩存預(yù)熱:在項(xiàng)目即將發(fā)布上線之前同仆,清空Redis數(shù)據(jù)庫,然后由開發(fā)者把所有的功能調(diào)試一遍裙品,
這樣Redis中就有了一些緩存數(shù)據(jù)俗批,然后再發(fā)布項(xiàng)目,這樣做也是為了避免大量用戶同時(shí)去查詢MySQL數(shù)據(jù)庫了;
Java客戶端 Jedis
* Jedis: 一款java操作redis數(shù)據(jù)庫的工具.
* 使用步驟:
1. 下載jedis的jar包
2. 使用
//1. 獲取連接
Jedis jedis = new Jedis("localhost",6379);
//2. 操作
jedis.set("username","zhangsan");
//3. 關(guān)閉連接
jedis.close();
* Jedis操作各種redis中的數(shù)據(jù)結(jié)構(gòu)
1. 字符串類型 string set get
```java
//1. 獲取連接
Jedis jedis = new Jedis();//如果使用空參構(gòu)造市怎,默認(rèn)值 "localhost",6379端口
//2. 操作
//存儲(chǔ)
jedis.set("username","zhangsan");
//獲取
String username = jedis.get("username");
System.out.println(username);
//可以使用setex()方法存儲(chǔ)可以指定過期時(shí)間的 key value
jedis.setex("activecode",20,"hehe");//將activecode:hehe鍵值對存入redis岁忘,并且20秒后自動(dòng)刪除該鍵值對
//3. 關(guān)閉連接
jedis.close();
```
2. 哈希類型 hash : map格式 hset hget hgetAll
```java
//1. 獲取連接
Jedis jedis = new Jedis();//如果使用空參構(gòu)造,默認(rèn)值 "localhost",6379端口
//2. 操作
// 存儲(chǔ)hash
jedis.hset("user","name","lisi");
jedis.hset("user","age","23");
jedis.hset("user","gender","female");
// 獲取hash
String name = jedis.hget("user", "name");
System.out.println(name);
// 獲取hash的所有map中的數(shù)據(jù)
Map<String, String> user = jedis.hgetAll("user");
// keyset
Set<String> keySet = user.keySet();
for (String key : keySet) {
//獲取value
String value = user.get(key);
System.out.println(key + ":" + value);
}
//3. 關(guān)閉連接
jedis.close();
```
3. 列表類型 list : linkedlist格式区匠。支持重復(fù)元素 lpush / rpush lpop / rpop lrange start end : 范圍獲取
```java
//1. 獲取連接
Jedis jedis = new Jedis();//如果使用空參構(gòu)造干像,默認(rèn)值 "localhost",6379端口
//2. 操作
// list 存儲(chǔ)
jedis.lpush("mylist","a","b","c");//從左邊存
jedis.rpush("mylist","a","b","c");//從右邊存
// list 范圍獲取
List<String> mylist = jedis.lrange("mylist", 0, -1);
System.out.println(mylist);
// list 彈出
String element1 = jedis.lpop("mylist");//c
System.out.println(element1);
String element2 = jedis.rpop("mylist");//c
System.out.println(element2);
// list 范圍獲取
List<String> mylist2 = jedis.lrange("mylist", 0, -1);
System.out.println(mylist2);
//3. 關(guān)閉連接
jedis.close();
```
4. 集合類型 set : 不允許重復(fù)元素 sadd smembers:獲取所有元素
```java
//1. 獲取連接
Jedis jedis = new Jedis();//如果使用空參構(gòu)造,默認(rèn)值 "localhost",6379端口
//2. 操作
// set 存儲(chǔ)
jedis.sadd("myset","java","php","c++");
// set 獲取
Set<String> myset = jedis.smembers("myset");
System.out.println(myset);
//3. 關(guān)閉連接
jedis.close();
```
5. 有序集合類型 sortedset:不允許重復(fù)元素驰弄,且元素有順序 zadd zrange
```java
//1. 獲取連接
Jedis jedis = new Jedis();//如果使用空參構(gòu)造麻汰,默認(rèn)值 "localhost",6379端口
//2. 操作
// sortedset 存儲(chǔ)
jedis.zadd("mysortedset",3,"亞瑟");
jedis.zadd("mysortedset",30,"后裔");
jedis.zadd("mysortedset",55,"孫悟空");
// sortedset 獲取
Set<String> mysortedset = jedis.zrange("mysortedset", 0, -1);
System.out.println(mysortedset);
//3. 關(guān)閉連接
jedis.close();
```
jedis連接池: JedisPool
使用:
1. 創(chuàng)建JedisPool連接池對象
2. 調(diào)用方法 getResource()方法獲取Jedis連接
//0.創(chuàng)建一個(gè)配置對象
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(50);
config.setMaxIdle(10);
//1.創(chuàng)建Jedis連接池對象
JedisPool jedisPool = new JedisPool(config,"localhost",6379);
//2.獲取連接
Jedis jedis = jedisPool.getResource();
//3. 使用
jedis.set("hehe","heihei");
//4. 關(guān)閉 歸還到連接池中
jedis.close();
連接池工具類
public class JedisPoolUtils {
private static JedisPool jedisPool;
static{
//讀取配置文件
InputStream is = JedisPoolUtils.class.getClassLoader().getResourceAsStream ("jedis.properties");
//創(chuàng)建Properties對象
Properties pro = new Properties();
//關(guān)聯(lián)文件
try {
pro.load(is);
} catch (IOException e) {
e.printStackTrace();
}
//獲取數(shù)據(jù),設(shè)置到JedisPoolConfig中
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(Integer.parseInt(pro.getProperty("maxTotal")));
config.setMaxIdle(Integer.parseInt(pro.getProperty("maxIdle")));
//初始化JedisPool
jedisPool = new JedisPool(config,pro.getProperty("host"),Integer.parseInt(pro.getProperty("port")));
}
/**
* 獲取連接方法
*/
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
Linux(Centos7)中安裝配置使用 Redis
- 檢查是否有 redis yum 源
- yum search redis
- yum info redis
- 安裝 epel 倉庫
EPEL (Extra Packages for Enterprise Linux)是基于 Fedora 的一個(gè)項(xiàng)目戚篙,為“紅帽系”的操作系統(tǒng)提供額外的軟件包五鲫,適用于 RHEL、CentOS 和 Scientific Linux.
yum install epel-release -y
- 安裝 redis 數(shù)據(jù)庫
- yum info redis
- yum install redis -y
- 安裝完畢后岔擂,使用下面的命令啟動(dòng) redis 服務(wù)
- systemctl start redis
- systemctl restart redis
- systemctl enable redis
- linux 上面進(jìn)入 Redis 客戶端
redis-cli
Ubuntu使用編譯版本安裝
- step1:下載
- step2:解壓
tar -zxvf redis-3.2.8.tar.gz
- step3:復(fù)制位喂,放到usr/local/redis?錄下
sudo mv ./redis-3.2.8 /usr/local/redis/
- step4:進(jìn)?redis?錄
cd /usr/local/redis/
- step5:生成
- 安裝c語言編譯器gcc: sudo apt-get install gcc
- 安裝編譯命令make: sudo apt-get install make(這一步可能會(huì)出問題,根據(jù)提示執(zhí)行命令)
- 生成 : sudo make(比較慢)
- step6:測試,這段運(yùn)?時(shí)間會(huì)較?
sudo make test
會(huì)報(bào)錯(cuò):make test error2....
解決方案:
cd
wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz
sudo tar xzvf tcl8.6.1-src.tar.gz -C /usr/local/
cd /usr/local/tcl8.6.1/unix/
sudo ./configure
sudo make(時(shí)間比較長)
sudo make install
- step7:安裝,將redis的命令安裝到/usr/local/bin/?錄
sudo make install (時(shí)間比較長)
- step8:安裝完成后智亮,我們進(jìn)入目錄/usr/local/bin中查看,文件如下
a)redis-server redis服務(wù)器
b)redis-cli redis命令行客戶端
c)redis-benchmark redis性能測試工具
d)redis-check-aof AOF文件修復(fù)工具
e)redis-check-rdb RDB文件檢索工具
- step9:配置?件忆某,移動(dòng)到/etc/?錄下
配置?件?錄為/usr/local/redis/redis.conf
sudo cp /usr/local/redis/redis.conf 空格 /etc/redis/
配置
- Redis的配置信息在/etc/redis/redis.conf下。
- 查看
sudo vi /etc/redis/redis.conf
核心配置選項(xiàng)
- 綁定ip:如果需要遠(yuǎn)程訪問阔蛉,可將此?注釋弃舒,或綁定?個(gè)真實(shí)ip
bind 127.0.0.1
- 端?,默認(rèn)為6379
port 6379
- 是否以守護(hù)進(jìn)程運(yùn)?
- 如果以守護(hù)進(jìn)程運(yùn)?状原,則不會(huì)在命令?阻塞聋呢,類似于服務(wù)
- 如果以?守護(hù)進(jìn)程運(yùn)?,則當(dāng)前終端被阻塞
- 設(shè)置為yes表示守護(hù)進(jìn)程颠区,設(shè)置為no表示?守護(hù)進(jìn)程
- 推薦設(shè)置為yes
daemonize yes
- 數(shù)據(jù)?件
dbfilename dump.rdb
- 數(shù)據(jù)?件存儲(chǔ)路徑
dir /var/lib/redis
- ?志?件
logfile /var/log/redis/redis-server.log
- 數(shù)據(jù)庫削锰,默認(rèn)有16個(gè)
database 16
- 主從復(fù)制,類似于雙機(jī)備份毕莱。
slaveof
啟動(dòng)服務(wù)端
此時(shí)啟動(dòng)針對編譯安裝版本的啟動(dòng)
- cd /etc/redis/redis-server
- ./redis.conf
啟動(dòng)客戶端
redis-cli
測試是否是通的
ping
返回pong則證明通暢
關(guān)閉
查詢r(jià)edis是否已經(jīng)啟動(dòng)
ps aux | grep redis
ps aux代表顯示所有進(jìn)程器贩,|是代表?xiàng)l件颅夺,grep是過濾然后是和redis有關(guān)的進(jìn)程。
- 然后通過查詢回來的pid進(jìn)行關(guān)閉
sudo kill -9 23113/pid
默認(rèn)指令
不修改配置文件的情況下蛹稍,默認(rèn)使用如下指令即可
- 推薦使?服務(wù)的?式管理redis服務(wù)
- 啟動(dòng)
sudo service redis start
- 停?
sudo service redis stop
- 重啟
sudo service redis restart
但是修改配置文件之后就用不了了吧黄,一般推薦如下:
ps -aux|grep redis 查看redis服務(wù)器進(jìn)程
sudo kill -9 pid 殺死redis服務(wù)器
sudo redis-server /etc/redis/redis.conf 指定加載的配置文件
注意
如果以 redis start形式開啟redis,并且寫入數(shù)據(jù)唆姐,此時(shí)kill形式關(guān)閉拗慨,再已
找到配置文件形式啟動(dòng),則可能啟動(dòng)不成功奉芦,此時(shí)可以 rm dump.rdb刪除redis本地?cái)?shù)據(jù)庫文件之后在啟動(dòng)赵抢。原因是兩種啟動(dòng)方式,一種使用存儲(chǔ)了另外一種大部分情況下不能操作數(shù)據(jù)庫文件声功,但是不是絕對的烦却。
go中使用redis
安裝命令
go get github.com/gomodule/redigo/redis
安裝完成后,回到家目錄創(chuàng)建test.go,把下面代碼復(fù)制到test.go里面先巴,編譯執(zhí)行test.go短绸,之后在redis中查找到鍵c1值為hello,說明安裝成功
package main
import ( "github.com/gomodule/redigo/redis")
func main(){
conn,_ := redis.Dial("tcp", ":6379")
defer conn.Close()
conn.Do("set", "c1", "hello")
}
操作方法
- 連接數(shù)據(jù)庫
Dial(network, address string)(conn,err)
- 執(zhí)行數(shù)據(jù)庫操作命令
Send(commandName string, args ...interface{}) error
Flush() error
Receive() (reply interface{}, err error)
Send函數(shù)發(fā)出指令筹裕,flush將連接的輸出緩沖區(qū)刷新到服務(wù)器,Receive接收服務(wù)器返回的數(shù)據(jù)
例如:
c.Send("SET", "foo", "bar")
c.Send("GET", "foo")
c.Flush()//把緩沖區(qū)命令發(fā)到服務(wù)器
c.Receive() // 接收set請求返回的數(shù)據(jù)
v, err = c.Receive() // 接收get請求傳輸?shù)臄?shù)據(jù)
另外一種執(zhí)行數(shù)據(jù)庫操作命令
Do(commandName string, args ...interface{}) (reply interface{}, err error)
- reply helper functions(回復(fù)助手函數(shù))
Bool窄驹,Int朝卒,Bytes,map乐埠,String抗斤,Strings和Values函數(shù)將回復(fù)轉(zhuǎn)換為特定類型的值。為了方便地包含對連接Do和Receive方法的調(diào)用丈咐,這些函數(shù)采用了類型為error的第二個(gè)參數(shù)瑞眼。如果錯(cuò)誤是非nil,則輔助函數(shù)返回錯(cuò)誤棵逊。如果錯(cuò)誤為nil伤疙,則該函數(shù)將回復(fù)轉(zhuǎn)換為指定的類型:
exists, err := redis.Bool(c.Do("EXISTS", "foo"))
if err != nil {
//處理錯(cuò)誤代碼
}
reflect.TypeOf(exists)//打印exists類型
- Scan函數(shù)
func Scan(src [] interface {},dest ... interface {})([] interface {},error)
Scan函數(shù)從src復(fù)制到dest指向的值。
Dest參數(shù)的值必須是整數(shù)辆影,浮點(diǎn)數(shù)徒像,布爾值,字符串蛙讥,[]byte锯蛀,interface{}或這些類型的切片。Scan使用標(biāo)準(zhǔn)的strconv包將批量字符串轉(zhuǎn)換為數(shù)字和布爾類型次慢。
示例代碼
var value1 int
var value2 string
reply, err := redis.Values(c.Do("MGET", "key1", "key2"))
if err != nil {
//處理錯(cuò)誤代碼
}
if _, err := redis.Scan(reply, &value1, &value2); err != nil {
// 處理錯(cuò)誤代碼
}
序列化與反序列化
針對redis旁涤,如果存儲(chǔ)復(fù)雜數(shù)據(jù)類型可以序列化之后存儲(chǔ)翔曲,取出后,反序列化獲取劈愚。一般都是利用Bytes存儲(chǔ)序列化的數(shù)據(jù)瞳遍。
- 序列化(字節(jié)化)
var buffer bytes.Buffer//容器
enc :=gob.NewEncoder(buffer)//編碼器
err:=enc.Encode(dest)//編碼
反序列化(反字節(jié)化)
dec := gob.NewDecoder(bytes.NewReader(buffer.bytes()))//解碼器
dec.Decode(src)//解碼
Nodejs 中使用 Redis
- 在你的項(xiàng)目中安裝 Redis
npm install redis --save 或者 cnpm install redis --save
- 使用 Redis
字符串案例:
var redis = require('redis');
var client = redis.createClient(6379, 'localhost');
//設(shè)置數(shù)據(jù)
client.set('username', '李四');
client.set('username', '李四','EX','5'); //設(shè)置過期 5 秒
//獲取數(shù)據(jù)
client.get('username', function(err, val){
console.log(val);
});
列表案例:
var redis = require('redis');
var client = redis.createClient(6379, 'localhost');
client.rpush('testLists', 'a');
client.rpush('testLists', 'b');
client.rpush('testLists', 'c');
client.lpush('testLists', 2);
client.lpush('testLists', 1);
client.lrange('testLists',0, -1,(err,lists)=>{
if(err){
console.log(err);
return;
}
console.log(lists)
})
集合案例:
var redis = require('redis');
var client = redis.createClient(6379, 'localhost');
client.sadd('testSet', 1);
client.sadd('testSet', 'a');
client.sadd('testSet', 'bb');
client.smembers('testSet', function(err, v){
console.log(v);
});
哈希案例:
var redis = require('redis');
var client = redis.createClient(6379, 'localhost');
client.hset('userinfo',"username", "zhangsan");
client.hmset('userinfo',"username","張三","age", "20","sex","男");
client.hgetall('userinfo',function(err,val){
console.log(val);
})
Redis 訂閱發(fā)布
- Redis 發(fā)布訂閱(pub/sub)是一種消息通信模式:發(fā)送者(pub)發(fā)送消息,訂閱者(sub)接收消息造虎。
- redis發(fā)布訂閱功能比較薄弱但比較輕量級(jí)傅蹂,mq消息持久化,數(shù)據(jù)可靠性比較差算凿,無后臺(tái)功能可msgId份蝴、msgKey進(jìn)行查詢消息
- Redis 客戶端可以訂閱任意數(shù)量的頻道。
- 下圖展示了頻道 channel1 氓轰, 以及訂閱這個(gè)頻道的三個(gè)客戶端 —— client2 婚夫、 client5 和 client1之間的關(guān)系:
當(dāng)有新消息通過 PUBLISH 命令發(fā)送給頻道 channel1 時(shí), 這個(gè)消息就會(huì)被發(fā)送給訂閱它的三個(gè)客戶端
- 發(fā)布
client.publish('testPublish', 'message from publish.js');
- 訂閱
client.subscribe('testPublish');
client.on('message', function(channel, msg){
console.log('client.on message, channel:', channel, ' message:', msg);
});