容器型數(shù)據(jù)結(jié)構(gòu)的通用規(guī)則
list/set/hash/zset 這四種數(shù)據(jù)結(jié)構(gòu)是容器型數(shù)據(jù)結(jié)構(gòu),它們共享下面兩條通用規(guī)則:?
1、create if not exists?
如果容器不存在,那就創(chuàng)建一個(gè),再進(jìn)行操作。比如 rpush 操作剛開始是沒有列表的,
Redis 就會(huì)自動(dòng)創(chuàng)建一個(gè),然后再 rpush 進(jìn)去新元素。?
2、drop if no elements?
如果容器里元素沒有了,那么立即刪除元素,釋放內(nèi)存。這意味著 lpop 操作到最后一
個(gè)元素,列表就消失了
還有一個(gè)需要特別注意的地方是如果一個(gè)字符串已經(jīng)設(shè)置了過期時(shí)間,然后你調(diào)用了
set 方法修改了它,它的過期時(shí)間會(huì)消失。
redis緩存穿透處理
譬如
新聞表的 id? 范圍 是 100~~~~~2000
這時(shí)如果查詢2004 或者3000 等ID是沒有的,但不代表未來沒有。因此這里有其中一個(gè)做法如下:
1、譬如key=news200,如果數(shù)據(jù)庫查詢返回空
2、那么我們依然往redis存儲(chǔ)一個(gè)我們約定好的數(shù)據(jù)結(jié)構(gòu) 并且設(shè)置過期時(shí)間,譬如設(shè)置為200秒(到底多少秒
要根據(jù)實(shí)際情況來調(diào)整)
3、下次如果繼續(xù)查到這個(gè)key,那么我們?cè)黾舆@個(gè)key的過期時(shí)間(譬如5秒)
偽代碼如下:
??StringnewsID=getParameter("id");
? NewsgetNews= getFromRedis("news"+newsID);
??if(getNews==null)
? {
? ? ? getNews=getFromDB("news"+newsID);
???????if(getNews==null)
???????{
? ? ? ? ? ? getNews=defaultCache();//設(shè)置一個(gè)固定緩存-1
?????? }
???? setToRedis(getNews,200); //塞入redis,初始過期時(shí)間為200秒
? }
?else if(getNews.equal(defaultCache))? //如果取出的緩存是?默認(rèn)緩存,則增加5秒的過期時(shí)間
??{
?????expireCache("news"+newsID,50);
?}
? response.write(getNews);
redis 應(yīng)用之HyporLogLog
? ? ? 當(dāng)統(tǒng)計(jì)一個(gè)網(wǎng)站的pv時(shí),我們可以用redis 的計(jì)數(shù)器功能實(shí)現(xiàn),給每個(gè)網(wǎng)頁一個(gè)獨(dú)立的計(jì)數(shù)器,技術(shù)器的key 后綴加上當(dāng)天的日期,這樣來一個(gè)請(qǐng)求,incrby 一次,最后算出所有的pv數(shù)據(jù)。
? ? ?但是UV 的話,一天一個(gè)用戶訪問多次的話只統(tǒng)計(jì)一次,就要去重,這要每個(gè)網(wǎng)頁求都要帶上唯一的用戶ID來標(biāo)識(shí)(無論是登陸還是未登錄)。你也許已經(jīng)想到了一個(gè)簡(jiǎn)單的方案,那就是為一個(gè)頁面一個(gè)獨(dú)立的 set 集合來存儲(chǔ)所有當(dāng)天訪問過此頁面的用戶 ID。當(dāng)一個(gè)請(qǐng)求過來時(shí),我們使用 sadd 將用戶 ID 塞進(jìn)去就可以了。通過 scard 可以取出這個(gè)集合的大小,這個(gè)數(shù)字就是這個(gè)頁面的 UV 數(shù)據(jù)。但是,當(dāng)訪問量非常多,就需要一個(gè)很大的set集合來統(tǒng)計(jì),這就非常浪費(fèi)空間。
HyporLogLog很好地解決了這個(gè)問題,。HyperLogLog 提供不精確的去重計(jì)數(shù)方案,雖然不精確但是也不是非常不精確。HyperLogLog 提供了兩個(gè)指令 pfadd 和 pfcount,根據(jù)字面意義很好理解,一個(gè)是增加計(jì)數(shù),一個(gè)是獲取計(jì)數(shù)。pfadd 用法和 set 集合的 sadd 是一樣的,來一個(gè)用戶 ID,就將用戶 ID 塞進(jìn)去就是。pfcount 和 scard 用法是一樣的,直接獲取計(jì)數(shù)值。
? ? ? ?HyperLogLog 除了上面的 pfadd 和 pfcount 之外,還提供了第三個(gè)指令 pfmerge,用于將多個(gè) pf 計(jì)數(shù)值累加在一起形成一個(gè)新的 pf 值。比如在網(wǎng)站中我們有兩個(gè)內(nèi)容差不多的頁面,運(yùn)營(yíng)說需要這兩個(gè)頁面的數(shù)據(jù)進(jìn)行合并。其中頁面的 UV 訪問量也需要合并,那這個(gè)時(shí)候 pfmerge 就可以派上用場(chǎng)了。
除此之外,HyporLogLog還可以統(tǒng)計(jì)一段時(shí)間用戶注冊(cè)量,比如pfmerge 把8月的每一天的數(shù)據(jù)合并為8月,pfcount 統(tǒng)計(jì)數(shù)量。