1. 程式人生 > >redis中list長度

redis中list長度

          我們使用redis , 其中經常需要得到一個list長度,那麼這個list長度是否儲存了還是每次都需要遍歷整個list呢? 

          看了下原始碼

  78 unsigned long listTypeLength(robj *subject) {
  79     if (subject->encoding == REDIS_ENCODING_ZIPLIST) {
  80         return ziplistLen(subject->ptr);
  81     } else if (subject->encoding == REDIS_ENCODING_LINKEDLIST) {
  82         return listLength((list*)subject->ptr);
  83     } else {
  84         redisPanic("Unknown list encoding");
  85     }
  86 }

          list 採用兩種實現方式,一個ziplist,另外一個linkedlist 

          我們先來看看這個ziplist           

 732 /* Return length of ziplist. */
 733 unsigned int ziplistLen(unsigned char *zl) {
 734     unsigned int len = 0;
 735     if (ZIPLIST_LENGTH(zl) < UINT16_MAX) {
 736         len = ZIPLIST_LENGTH(zl);
 737     } else {
 738         unsigned char *p = zl+ZIPLIST_HEADER_SIZE;
 739         while (*p != ZIP_END) {
 740             p += zipRawEntryLength(p);
 741             len++;
 742         }
 743         
 744         /* Re-store length if small enough */
 745         if (len < UINT16_MAX) ZIPLIST_LENGTH(zl) = len;
 746     }
 747     return len;
 748 }

          使用固定地方存放list長度,但是如果超過了最大值,那麼就需要遍歷

          所以使用ziplist,最好長度不要超過  2^16 -2  = 65534 ,否則嚴重影響效率

        我們再來看看linkedlist,實現在 adlist.c中

 47 typedef struct list {
 48     listNode *head;
 49     listNode *tail;
 50     void *(*dup)(void *ptr);
 51     void (*free)(void *ptr);
 52     int (*match)(void *ptr, void *key);
 53     unsigned int len;
 54 } list;
 55 
 56 /* Functions implemented as macros */
 57 #define listLength(l) ((l)->len)
從上面的程式碼可以看出,在list結構體中有個len欄位,得到長度的時候,直接返回這個欄位。