SET key value // 爲一個鍵賦值
GET key // 獲取一個鍵值
複製代碼
INCR key
複製代碼
當要操做的鍵不存在時默認鍵值爲0,第一次遞增後結果是1 當鍵值不是整數時,redis會提示錯誤javascript
首先要解決的一個問題是如何給鍵命名,通常狀況下,命名最佳實踐爲:java
對象類型:對象ID:對象屬性 備註:對於多個單次推薦使用"."分隔 例如使用user:1:friends來存儲ID爲1的用戶的好友列表redis
其次,咱們須要對文章生成一個自增的id,那麼此時咱們可使用INCR指令,對一個鍵進行自增,每次發佈新文章時,都從該鍵內取一個新增的值。 咱們可使用對象類型的命名方法,將鍵值命名爲posts:count,每次新增文章咱們都使用INCR命令,從該鍵值內取值。json
咱們使用JavaScript內的JSON方法來對文章內的諸多元素進行序列化,將其變爲字符串形式的數據,存儲在redis中。 此時,咱們寫一個發佈文章的僞JavaScript代碼bash
// 得到文章的新ID
const postId = INCR posts:count
// 將博客文章的數據序列化爲JSON
const jsonPost = JSON.stringify({ title, content, author, time })
// 將序列化後的字符串存入一個字符串類型的鍵中
SET post:postId:data, jsonPost
複製代碼
HSET key field value
HGET key field
// 設置多個字段使用下面指令,如:HMSET key field1 value1 field2 value2
HMSET key filed value [field value ...]
// 獲取多個字段使用下面命令,如:HMGET key field1 field2
HMGET key field [field ...]
// 若是想獲取全部字段和字段值,可是不知道鍵中有哪些字段時,使用以下指令
HGETALL key
複製代碼
HSET不區分插入和更新操做,無需事先判斷字段是否存在來決定要執行的是插入操做仍是插入操做post
HEXISTS key field
複製代碼
使用該命令判斷字段是否存在,若是存在返回1,不存在返回0,若是鍵不存在也會返回0性能
HSETNX key field value
複製代碼
HSETNX 中的NX標識if Not eXists 若是不存在ui
與HSET的區別是:若是字段已存在,該命令不執行任何操做編碼
// 增長自定義的數字,如:HINCRBY student score 60
HINCRBY key field increment
複製代碼
若是student鍵不存在,自動建立該鍵,score字段默認爲0,並增長60spa
HDEL key field [field ...]
複製代碼
該命令能夠刪除一個或多個字段,返回值是被刪除的字段個數
前文提到的存儲文章沒法對文章內單個字段進行原子讀寫操做,而且若是隻想獲取標題也須要獲取所有數據後使用JSON解析,消耗資源。 若是還使用字符串類型存儲數據,那麼能夠設計以下結構:
鍵 | 鍵值 |
---|---|
post:1:title | 第一篇博文 |
post:1:author | 趙玉成 |
post:1:time | 2019年4月5日 |
post:1:content | 這是個人第一篇博文 |
若是使用散列類型存儲文章內容,那麼能夠設計以下結構:
鍵 | 字段 | 字段值 |
---|---|---|
post:1 | title | 第一篇博文 |
post:1 | author | 趙玉成 |
post:1 | time | 2019年4月5日 |
post:1 | content | 這是個人第一篇博文 |
咱們發現,散列類型存儲方式優勢以下:
咱們爲文章增長一個惟一的別名,而且經過該縮略名查找到對應文章id 此時,咱們能夠增長一個散列類型鍵:slug.to.id 來存儲文章的別名對應的id,此時咱們發佈文章的僞代碼以下:
// 得到文章的新ID
const postId = INCR posts:count
// 判斷別名是否存在,若是不存在該別名,則直接使用
const isSlugAvailable = HSETNX slug.to.id, slug, postId
if (isSlugAvailable === 0) return
HMSET post:postId, title, title, content, content, slug, slug, author, author, time, time
複製代碼
下面的僞代碼實現了經過別名來獲取文章內容
const postId = HGET slug.to.id, slug
if (!postid) {
console.log('文章不存在')
return
}
const post = HGETALL post:postId
console.log(`文章標題:${post.title}`)
複製代碼
下面的僞代碼模擬了修改id爲1的文章別名
// 若是新的slug已經存在了,那麼將不會設置,而且返回0
const isSlugAvailable = HSETNX slug.to.id, newSlug, 1
if (isSlugAvailable === 0) return
// 獲取舊的別名
const oldSlug = HGET post:42, slug
// 設置新的別名
HSET post:1, slug, newSlug
// 刪除舊的別名
HDEL slug.to.id, oldSlug
複製代碼
// 向列表左邊增長元素,返回值表示增長元素後列表長度
LPUSH key value [value ...]
// 向列表右邊增長元素,返回值表示增長元素後列表長度
RPUSH key value [value ...]
複製代碼
// 從列表左邊彈出一個元素,返回值爲被移除的元素值
LPOP key
// 從列表右邊彈出一個元素,返回值爲被移除的元素值
RPOP key
複製代碼
以上操做能夠模擬棧和隊列操做: 若是把列表當作棧:搭配使用LPUSH、LPOP或RPUSH、RPOP 若是把列表當作隊列:搭配使用LPUSH、RPOP或RPUSH、LPOP
LLEN key
複製代碼
鍵不存在時返回0 複雜度O(1),由於redis會讀取現成的值
LRANGE key start top
複製代碼
得到索引從start
到stop
之間全部元素,包含兩端元素 同時支持負索引,表示從右邊開始計數,「-1」表示從右邊第一個元素
若是start索引位置比stop索引位置靠後,返回空列表 若是stop大於實際的索引範圍,返回列表最右邊的元素
LREM key count value
複製代碼
該指令刪除列表中前 count 個值爲 value 的元素,返回的是實際刪除的元素數量。
實現一個文章分頁功能,咱們將使用列表類型鍵posts:list記錄文章列表 發佈新文章時,用LPUSH把新文章id加入列表中,刪除文章時使用LREM post:list 1 要刪除文章的id
使用LRANGE命令來實現文章分頁,僞代碼以下:
const postsPerPage = 10
const start = (currentPage - 1) * postsPerPage
const end = currentPage * postsPerPage - 1
const postsId = LRANGE posts:list, start, end
// 使用獲取到的id列表循環讀取文章
postsId.map(id => {
let post = HGETALL post:id
console.log(`文章標題:${post.title}`)
})
複製代碼
此時該文章列表是順序倒序的,新發布的文章在前面
此方法有如下問題:
當不容許修改本身發表的評論,且讀取評論時須要得到評論的所有數據(評論者姓名、評論時間、評論內容),所以適合將一條評論的各個元素序列化爲字符串後做爲列表類型鍵中的元素來存儲。 假設咱們存儲文章id
爲1
的評論,僞代碼以下:
const serializedComment = JSON.stringify({ author, time, contnet })
LPUSH post:1:comments, serializedComment
複製代碼
獲取時使用LRANGE
便可
SADD key number [number ...]
SREM key number [number ...]
複製代碼
使用SADD時,若是鍵不存在則會自動建立,一個集合中不能有相同的元素,返回值是成功加入的元素數量 使用SREM時,返回值是刪除成功個數
SMEMBERS key
複製代碼
SISMEMBER key number
複製代碼
時間複雜度爲O(1),不管集合中有多少元素均可以極快返回結果
當值存在時返回1,不存在返回0
// 多個集合差集運算,即全部屬於A但不屬於B的元素構成的集合,多個鍵時,先計算A與B的差集,結果再去與C求差集
SDIFF key [key ...]
// 對多個集合執行交集運算
SINTER key [key ...]
// 對多個集合執行並集
SUNION key [key ...]
複製代碼
因爲文章的每一個標籤都是不一樣的,而且對其沒有排列要求,所以咱們可使用集合類型來存儲文章標籤,對每篇文章使用的鍵名爲post:文章ID:tags
僞代碼以下
SADD post:1:tages, JavaScript, Frontend, Node
SREM post:1:tage, JavaScript
const tags = SMEMBERS post:1:tages
console.log(tages)
複製代碼
若是但願列出某個標籤下的文章,在存儲時爲每一個標籤使用名爲tag:標籤名稱:posts
的集合類鍵存儲有該標籤的文章id列表
若是但願獲取JavaScript
標籤的文章時,只要使用SMEMBERS tag:JavaScript:posts
便可,若是但願同時找到JavaScript
、Node
這兩個標籤的文章,只須要使用SMEMBERS tag:JavaScript:posts
、SMEMBERS tag:Node:posts
取交集,藉助SINTER
便可。
與集合類型的類似點
ZADD key score member [score member ...]
複製代碼
若是該元素已經存在,會使用新的分數替換原有的元素。 分數能夠是整數,也能夠是雙精度浮點數。
inf:表示無窮,該指令支持無窮大 如:ZADD test +inf a
返回值是新加入到集合中的元素個數(不包含以前已經存在的元素)
ZSCORE key member
複製代碼
ZRANGE key start stop [WITHSCORES]
ZREVRANGE key start stop [WITHSCORES]
複製代碼
ZRANGE
會按照分數從小到大的順序返回start到stop之間的全部元素(包含兩端的元素),若是索引爲負數則表明從後向前查找(-1表示最後一個元素) 若是須要得到元素的分數,則須要再命令尾部加上WITHSCORES參數 該命令的時間複雜度爲O(log m+n),n爲有序集合的基數,m爲返回元素個數, 若是分數相同按照字典順序進行排列,中文如按照UTF-8的編碼,則是按照該編碼進行排序。 ZREVRANGE
則是與ZRANGE
排序相反。
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
複製代碼
按照元素分數從小到大的順序返回分數在min到max之間的元素,包含min和max。若是不包含端點值,能夠在分數前加上「(」符號
WITHSCORES與ZRANGE
一致
LIMIT offset count
表示在得到的元素列表基礎上向後偏移offset
個元素,而且只取前count
個元素
例如:獲取分數高於60分的從第二我的開始的3我的,而且帶上分數 ZRANGEBYSCORE scoreboard (60 +inf WITHSCORES LIMIT 1 3
ZINCRBY key increment member
複製代碼
正數爲增長,負數爲減分 若是指定元素不存在,則會自動建立分數爲0的元素,再執行操做 返回值是更改後的分數
建立一個有序集合鍵,該鍵中以文章id爲元素,文章的點擊量爲分數。該鍵的命名爲posts:page.view
,每次用戶訪問一篇文章時,經過ZINCRBY posts:page.view 1 文章ID
更新訪問量
下面的僞代碼實現了按照點擊量的順序顯示文章列表:
const postsPerPage = 10
const start = (currentPage - 1) * postsPerPage
const end = currentPage * postsPerPage - 1
const postId = ZREVRANGE posts:page.view, start, end
postId.map(id => {
let postData = HGETALL post:id
console.log(`文章標題:${postData}`)
})
複製代碼
將元素設置爲文章的id,元素的分數設置爲Unix時間,當文章有更新時,更新分數便可。 藉助ZREVRANGEBYSCORE
命令能夠輕鬆得到指定時間的文章列表