Redis是一個偉大的工具,用來在內存中存儲列表是很合適的。
不過,如果你想要快速搜索列表,同時需要讓列表中每項都在一定時間后過期,應該怎么做呢?
首先,當然不能使用不同的類似的key存儲數據,然后使用keys命令來獲取所有類似key的數據。這樣的開銷是不可接受的。
Redis並沒有直接提供方法做這件事,但是這是可以做到的!雖然最后用的未必是Redis的List數據結構。
我接下來會展示給你看。
問題
最近,我遇到一個問題,我有一個數據列表,需要用它來制作折線圖,我准備使用API返回這個數據列表,然后在前端繪圖。
這個數據列表本身是挺大的,然后它還會一直更新,所以放在數據庫是不合適的,我計算過從數據庫取回需要10s。所以我決定使用redis。
碰到一個問題,就是數據列表中的數據,如果超過一定時間的話我是不需要了,否則這個列表會變得無比巨大。所以我需要redis對列表中的每個項都設置過期時間。
然后我在網上找到這篇文章,它描述了兩種辦法。
在講解這兩種辦法之前,你需要明白redis的兩個數據結構:
- Redis的集合:“無序的字符串集合”,它的項有下面的特點
- 唯一的(如果加入重復的數據,redis會默默的拒絕)
- 無序,並且不可以用任何方法(在redis中)排序
- Redis有序集合:“有序的字符串集合“,它的項有下面的特點:
- 和集合一樣,每個項都是唯一的
- 擁有積分(項的積分並不必須是唯一的)
- 根據積分排序(有索引)
這兩個集合,都不可以對其中的項設置過期時間。當然,你可以對整個集合設置過期時間。
兩種解決方法
有序集合
查詢有序集合是非常快的,因為redis將一個列表轉換成了集合,所以當我們訪問它的時候,它已經是排好序的了。
根據Redis文檔的描述:
“Sorted sets are implemented via a dual-ported data structure containing both a skip list and a hash table, so every time we add an element Redis performs an O(log(N)) operation. That’s good, but when we ask for sorted elements Redis does not have to do any work at all, it’s already all sorted”
當然,你不可以對有序集合中每個項設置TTL。
你可以通過score對有序集合進行查詢,我們可以利用這個地方來形成一個解決方案:
對於加入到有序集合的每個項,我們都將它的score設置為Unix Timestamp,這個timestamp代表它的過期時間。然后,我們加入一個定時任務,定時移除那些過期的數據。
多個集合以及TTL
這個方案使用普通的集合。
因為不能對集合中每項都設置TTL,但是可以對整個集合設置TTL。所以,我們可以將每個時間段的數據放在一個集合中。然后對這個集合設置過期時間。
