1. 程式人生 > >Redis常用技術----超時命令

Redis常用技術----超時命令

Java中有GC,可以自動回收不再使用的Java物件。同樣,Redis也是基於記憶體而執行的資料集合,也存在著對記憶體垃圾的回收和管理的問題。

對於Redis,del命令可以刪除一些鍵值對,所以Redis比JVM更靈活。於此同時,當記憶體執行空間滿了之後,它還會按照回收機制去自動回收一些鍵值對,這和JVM有一定相似之處。但是當進行垃圾回收的時候,又有可能引發系統停頓,因此選擇恰當的回收機制和回收時間將有利於系統性能的提高。

首先看看鍵值對的超時命令,因為大部分情況下,我們都想回收那些超時的鍵值對。

命令 說明 備註
persist key 持久化key,取消超時時間 移除key的超時時間
ttl key 檢視key的超時時間 以秒計算,-1代表沒有超時時間,如果不存在key或者key已經超時則為-2
expire key seconds 設定超時時間戳 以秒為單位
expireat key timestamp 設定超時時間點 用uninx時間戳確定
pptl key milliseconds 檢視key的超時時間戳 以毫秒計算
pexpire key 設定鍵值超時的時間 以毫秒為單位
pexpireat key stamptimes 設定超時時間點 以毫秒為單位的uninx時間戳

下面使用spring來執行這個過程

/**
 * 測試Redis的超時命令
 * @author liu
 */
public class TestExpire {
    @SuppressWarnings({ "unchecked", "resource"
, "rawtypes", "unused" }) @Test public void testExpire() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); RedisTemplate rt = applicationContext.getBean(RedisTemplate.class); rt.execute((RedisOperations ops)->{ ops.boundValueOps("key1").set("value1"); String keyValue = (String)ops.boundValueOps("key1").get(); long expSecond = ops.getExpire("key1"); System.out.println(expSecond); boolean b = false; b = ops.expire("key1", 120L, TimeUnit.SECONDS); b = ops.persist("key1"); long l = 0L; l = ops.getExpire("key1"); long now = System.currentTimeMillis(); Date date = new Date(); date.setTime(now + 120000); ops.expireAt("key1", date); return null; } ); } }

這裡討論一個問題:如果key超時了,Redis會回收key的儲存空間嗎?

答案是不會。Redis的Key超時不會被其自動回收,它只會標識哪些鍵值對超時了。這樣做的好處是如果一個很大的鍵值對超時,比如一個列表或hash結構,存著百萬個元素,要對其回收需要很長時間。如果採用超時回收,則可能會產生停頓。壞處也很明顯,這些超時的鍵值對會浪費比較多的空間。

Redis提供兩種方式回收這些超時鍵值對,分別是定時回收惰性回收

  • 定時回收:在確定的某個時間觸發一次程式碼,回收超時的鍵值對。

  • 惰性回收:當一個超時的鍵,被再次使用get命令訪問到時,將觸發Redis將其從記憶體中清空。

定時回收可以完全回收掉那些超時的鍵,但是缺點也很明顯,如果這件鍵值對比較多,那麼就會耗費較多的時間,從而導致卡頓。

對於惰性回收,它的優勢是可以指定回收的鍵值對,它的缺點是要執行一個get操作進行觸發,或者在某些時候,我們難以判斷哪些鍵值對已經超時。

無論使用那一種回收策略,都需要根據情況而定。如果一個鍵值對儲存著數億千萬的資料,使用expire命令使其到達一個時間超時,然後用get命令訪問觸發其回收,顯然會付出卡頓代價,這是現實中需要考慮的。