閱讀375 返回首頁    go 技術社區[雲棲]


Redis開發運維實踐開發者設計規範之典型使用場景參考

4.6 典型使用場景參考

下麵是Redis適用的一些場景:

1. 取最新 N 個數據的操作

比如典型的取你網站的最新文章,通過下麵方式,我們可以將最新的 5000條評論的ID放在Redis的List集合中,並將超出集合部分從數據庫獲取。

使用LPUSH latest.comments命令,向 list集合中插入數據 插入完成後再用 LTRIM latest.comments 0 5000 命令使其永遠隻保存最近5000個 ID 然後我們在客戶端獲取某一頁評論時可以用下麵的邏輯

FUNCTION get_latest_comments(start,num_items):
 id_list = redis.lrange("latest.comments",start,start+num_items-1) 
 IF id_list.length < num_items 
 id_list = SQL_DB("SELECT ... ORDER BY time LIMIT ...") 
 END 
 RETURN id_list 
END 

如果你還有不同的篩選維度,比如某個分類的最新 N 條,那麼你可以再建一個按此分類的List,隻存ID的話,Redis是非常高效的。

2. 排行榜應用,取 TOP N 操作

這個需求與上麵需求的不同之處在於,前麵操作以時間為權重,這個是以某個條件為權重,比如按頂的次數排序,這時候就需要我們的 sorted set出馬了,將你要排序的值設置成 sorted set的score,將具體的數據設置成相應的 value,每次隻需要執行一條ZADD命令即可。

127.0.0.1:6379> zdd topapp 1 weixin
(error) ERR unknown command 'zdd'
127.0.0.1:6379> zadd topapp 1 weixin
(integer) 1
127.0.0.1:6379> zadd topapp 1 QQ
(integer) 1
127.0.0.1:6379> zadd topapp 2 meituan
(integer) 1
127.0.0.1:6379> zincrby topapp 1 meituan
"3"
127.0.0.1:6379> zincrby topapp 1 QQ
"2"
127.0.0.1:6379> zrank topapp QQ
(integer) 1
3) "meituan"
127.0.0.1:6379> zrank topapp weixin
(integer) 0
127.0.0.1:6379> zrange topapp 0 -1
1) "weixin"
2) "QQ"

3.需要精準設定過期時間的應用

比如你可以把上麵說到的 sorted set 的 score 值設置成過期時間的時間戳,那麼就可以簡單地通過過期時間排序,定時清除過期數據了,不僅是清除 Redis中的過期數據,你完全可以把 Redis 裏這個過期時間當成是對數據庫中數據的索引,用 Redis 來找出哪些數據需要過期刪除,然後再精準地從數據庫中刪除相應的記錄。

4.計數器應用

Redis的命令都是原子性的,你可以輕鬆地利用 INCR,DECR 命令來構建計數器係統。

5.Uniq 操作,獲取某段時間所有數據排重值

這個使用Redis的 set數據結構最合適了,隻需要不斷地將數據往 set中扔就行了,set意為集合,所以會自動排重。

6.實時係統,反垃圾係統

通過上麵說到的 set功能,你可以知道一個終端用戶是否進行了某個操作,可以找到其操作的集合並進行分析統計對比等。

7.Pub/Sub 構建實時消息係統

Redis 的 Pub/Sub 係統可以構建實時的消息係統,比如很多用 Pub/Sub 構建的實時聊天係統的例子。

8.構建隊列係統

使用list可以構建隊列係統,使用 sorted set甚至可以構建有優先級的隊列係統。

9.緩存

性能優於Memcached,數據結構更多樣化。作為RDBMS的前端擋箭牌,redis可以對一些使用頻率極高的sql操作進行cache,比如,我們可以根據sql的hash進行SQL結果的緩存:

def get_results(sql):
    hash = md5.new(sql).digest()
    result = redis.get(hash)
    if result is None:
        result = db.execute(sql)
        redis.set(hash, result)
        # or use redis.setex to set a TTL for the key
    return result

10.使用setbit進行統計計數

下邊的例子是記錄UV

#!/usr/bin/python
import redis
from bitarray import bitarray
from datetime import date

r=redis.Redis(host='localhost', port=6379, db=0)
today=date.today().strftime('%Y-%m-%d')

def bitcount(n):
len(bin(n)-2)

def setup():
r.delete('user:'+today)
r.setbit('user:'+today,100,0)

def setuniquser(uid):
r.setbit('user:'+today,uid,1)

def countuniquser():
a = bitarray()
a.frombytes(r.get('user:'+today),)
print a
print a.count()


if __name__=='__main__':
setup()
setuniquser(uid=0)
countuniquser()

11.維護好友關係

使用set進行是否為好友關係,共同好友等操作

12.使用 Redis 實現自動補全功能

使用有序集合保存輸入結果:

ZADD word:a 0 apple 0 application 0 acfun 0 adobe
ZADD word:ap 0 apple 0 application
ZADD word:app 0 apple 0 application
ZADD word:appl 0 apple 0 application
ZADD word:apple 0 apple
ZADD word:appli 0 application

再使用一個有序集合保存熱度:

ZADD word_scores 100 apple 80 adobe 70 application 60 acfun

取結果時采用交集操作:

ZINTERSTORE word_result 2 word_scores word:a WEIGHTS 1 1
ZRANGE word_result 0 -1 withscores

13. 可靠隊列設計

• UUIDs as Surrogate Keys Our strategy spreads information about the state of an item in the queue across a number of Redis data structures, requiring the use of a per-item surrogate key to tie them together. The UUID is a good choice here because 1) they are quick to generate, and 2) can be generated by the clients in a decentralized manner. • Pending List The Pending List holds the generated UUIDs for the items that have been enqueued(), and are ready to be processed. It is a RedisList, presenting the generated UUIDs in FIFO order. • Values Hash The Values Hash holds the actual items that have been enqueued. It is a Redis Hash, mapping the generated UUID to the binary form of the the item. This is the only representation of the original item that will appear in any of the data structures. • Stats Hash The Stats Hash records some timestamps and counts for each of the items. Specifically: • enqueue time • last dequeue time • dequeue count • last requeue time • last requeue count. It is a Redis Hash, mapping the generated UUID to a custom data structure that holds this data in a packed, binary form. Why keep stats on a per-item basis? We find it really useful for debugging (e.g. do we have a bad apple item that is being continuously requeued?), and for understanding how far behind we are if queues start to back up. Furthermore, the cost is only ~40 bytes per item, much smaller than our typical queued items. • Working Set The Working Set holds the set of UUIDs that have been dequeued(), and are currently being processed. It is a Redis Sorted Set, and scores each of the UUIDs by a pre-calculated, millisecond timestamp. Any object that has exceeded its assigned timeout is considered abandoned, and is available to be reclaimed. • Delay Set The Delay Set holds the set of UUIDs that have been requeued() with a per-item deferment. It is a Redis Sorted Set, and scores each of the UUIDs by a pre-calculated, millisecond timestamp. Once the deferment timestamp has expired, the item will be returned to the Pending List. Why support per-item deferment? We have a number of use cases where we might want to backoff specific pieces of work — maybe an underlying resource is too busy — without backing off the entire queue. Per-item deferment lets us say, “requeue this item, but don’t make it available for dequeue for another n seconds.”


Redis開發運維實踐指南

本文為《Redis開發運維實踐指南》內容,該書作者為黃鵬程,已授權雲棲社區轉載。



最後更新:2017-05-08 10:31:37

  上一篇:go Redis開發運維實踐上線部署規劃之網卡rps設置
  下一篇:go Redis開發運維實踐開發者設計規範之延遲考慮