String Redis strings for Redis data types
The Redis string is not a native C-language string, but rather a simple dynamic string that is built by itself, called SDS, which is similar to the native C-language string, using '/' as the end.
In addition to printing the log, we operate the string basically using SDS
The main functions of SDS in Redis
1. 保存数据库的字符串值 2. 用作缓冲区buffer
The definition of SDS in Redis
Sds.h and SDS.C under the SRC directory under the source bundle
typedefchar *sds; /** * 保存字符串对象的结构 */ struct sdshdr { // buf 中已占用空间的长度 int len; // buf 中剩余可用空间的长度 intfree; // 数据空间 char buf[]; };
Why use SDS instead of the C language native string?
SDS has a little bit of a feature
- The time complexity to get the string length is O(1)
c The province does not carry its own length attribute, so to get the length must traverse once, this complexity is O ( n )
/** * 返回实际的长度 */ staticinline size_t sdslen(const sds s) { struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr))); return sh->len; }
- Prevent buffer Overflow
This is shown by some of the unsafe string manipulation functions in C, such as
strcat(char* dest,constchar* src)
Look at the Sdscat in SDS.C ()
//Function prototypesSDS Sdscat (SDS s,Const Char*T);//Concrete implementationSDS Sdscat (SDS s,Const Char*t) {returnSdscatlen (S, T,strlen(t)); }//sdscatlenSDS Sdscatlen (SDS s,Const void*t, size_t len) {structSDSHDR *sh;//original string lengthsize_t Curlen = Sdslen (s);//Extended SDS Space //T = O (N)s = sdsmakeroomfor (S,len);//Insufficient memory? Direct return if(s = = NULL)returnNULL;//Copy the contents of T to the back of the string //T = O (N)SH = (void*) (S (sizeof(struct(SDSHDR)));memcpy(S+curlen, T, Len);//Update PropertiesSh->len = Curlen+len; Sh-> Free= sh-> Free-len;//Add new end symbolS[curlen+len] =' + ';//Return to new SDS returnS }
As you can see, when the SDS is stitching, the length of the original string is first obtained and then extended.
3. Reduce memory redistribution when modifying strings
The C-language string is first or foremost dependent on a character array, and a string of length n corresponds to a character array of length n+1, so the memory reallocation of the character array occurs when the string is manipulated.
For memory redistribution, the general design of complex algorithms and system calls, relatively time-consuming, occasional redistribution is acceptable, but for redis, frequent operation, it is very inefficient.
Do you remember the structure of SDS? A space has been saved that has not been used. This is the SDS that blocks the association with the underlying array.
So how does SDS use this free to reduce memory redistribution?
Method One, memory pre-allocation. Optimize SDS growth Operations
To put it simply, the Redis API, when modifying SDS, extends the free space length of the SDS if it involves extending the SDS length. If free is sufficient, then use free space.
So how much does it extend? What is the size relationship between free and length?
-If the SDS after the extension is less than 1M, then after the expansion of the Free==length, the total memory size is F Ree+LeNg Th+1by Te
-If the SDS after expansion is greater than 1M, then the size of free is 1M and the total length is 1M +LeNg Th+1by Te
Method Two, the inert space release optimizes the SDS to shorten the operation
To put it simply, the Redis API truncates the SDS, and the program does not immediately reclaim the extra memory, but uses the free property to save the space.
Implementation code
SDS Sdstrim (SDS s,Const Char*cset) {structSdshdr *sh = (void*) (S (sizeof(struct(SDSHDR)));Char*start, *end, *SP, *ep; size_t Len;//Set and record pointersSP = start = s; EP = end = S+sdslen (s)-1;//trim, T = O (n^2) while(SP <= End &&STRCHR(Cset, *SP)) sp++; while(Ep > Start &&STRCHR(Cset, *EP)) ep--;//Calculate the remaining string length after trim finishesLen = (sp > EP)?0: ((EP-SP) +1);//If necessary, move string contents forward //T = O (N) if(sh->buf! = SP) memmove (sh->buf, SP, len);//Add TerminatorSh->buf[len] =' + ';//Update PropertiesSh-> Free= sh-> Free+ (Sh->len-len); Sh->len = Len;//Return to SDS after pruning returns;}
Binary security
A C-language string can only be used to hold ANSI characters because it cannot contain null characters.
All SDS APIs handle the data stored in the SDS byte array in a binary way, without any processing of the data.
Compatible with some C-language strings.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
A string of Redis data types