redis中list長度
阿新 • • 發佈:2019-01-24
我們使用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中
從上面的程式碼可以看出,在list結構體中有個len欄位,得到長度的時候,直接返回這個欄位。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)