1、基本使用
1. 设置一个键值对
set k1 v100
2. 设置一个键值对(当这个键不存在时)
setnx k1 100 失败
setnx k2 100 成功
3. 获取指定key的值
get k1
4. 将字符串xxx添加到key值的末尾
append k1 xxx
5. 获取key的长度
strlen k1
6. 将k2的值加1(前提是value中只有数字字符)
incr k2
7. 将k2的值减1(前提是value中只有数字字符)
decr k2
8. 将k2的值增加step(前提是value中只有数字字符)
incrby k2 step
9. 将k2的值减小step(前提是value中只有数字字符)
decrby k2 step
10. 同时设置多个值
mset k1 v1 k2 v2 k3 v3
11. 同时获取多个值
mget k1 k2 k3
12. 同时设置多个值(原子操作,所有的key都不存在才会生效)
msetnx k1 v1 k2 v2 k3 v3 k4 v4 失败(k1 k2 k3都已经存在)
msetnx k4 v4 k5 v5 k6 v6 成功(不存在k4 k5 k6)
13. 获取一个字符串指定位置的值, 字符从0开始存放。
getrange k1 start end 获取的是[start, end]区间
14. 对一个字符串从指定位置开始进行替换
setrange k1 index xxx 从index位置开始替换xxx
15. 设置一个k v键值对,同时设置过期时间(可用ttl k1查看过期时间)
setex k1 time v1 = set k1 v1 + expire k1 time
16. 获取当前的key的值,并且更新为value
getset k1 v100 控制台会先输出k1的值,然后将k1的值换成v100
2、数据结构
-
redis中最基础的数据结构之一,string的内部实现就是一个动态数组(Simple Dynamic String)
-
由于redis是用C编写的,基本上可以猜测到这个动态string是使用一个结构体进行维护。
-
维护的方式也很简单,既然是动态的那么肯定需要维护一个array数组、一个len长度记录、一个capacity容量记录。
-
扩容的阈值会根据长度和容量进行计算,当长度超过一定的阈值时就会扩容。
-
扩容方式:开辟一个新空间、更新capacity容量、更新len长度、将原来空间的数据拷贝过来,可能还要追加字符串。
2.1、基本数据结构定义
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct _str{
char *arr;
int capacity;
int len;
}
typedef _str string;
2.2、初始化创建
-
假设最开始先给10个字节的容量(不知道起始容量)
-
C语言中char类型是占1个字节大小,英文占1个字节,中文占连续的2个。
-
初始化分配肯定是redis操作收到一个set k v的操作,那么这时候肯定是能够计算出v的存储空间大小,然后按需分配空间(可能比v的实际存储空间大)
string init_string(char *s)
{
int len = strlen(s);
int init_size = len + 10; //比实际存储空间略大
string str;
str.arr = (char *)malloc(sizeof(char)*init_size);
str.len = len; //长度
str.capacity = init_size; //容量
strcpy(str.arr,s); //拷贝字符串
puts(str.arr);
return str;
}
2.3、扩容
-
扩容肯定是在更新数据的时候发现空间不够了,需要进行扩容。
-
扩容肯定是需要重新分配空间的,不然地址无法连续(数组);重新申请分配一个空间然后将原数据空间的数据拷贝到新空间,然后释放原空间。
-
扩容完毕然后在追加新设定的字符串。
string expand_capacity(int expand_size, string now)
{
string str;
str.arr = (char *)malloc(sizeof(char)*expand_size);
str.len = now.len;
str.capacity = expand_size;
strcpy(str.arr,now.arr); //将now中的字符串拷贝到新空间中
free(now.arr); //释放之间的空间
return str;
}
2.4、扩容细节
-
如果当前存储空间小于1M(1024byte)也就是capacity < 1024时;这时候扩容是将空间扩大到capacity = capacity + len。也就是新增一倍已经使用的空间。
-
如果当前存储空间大于等于1M(1024byte)也就是capacity >= 1024时;这时候扩容是将空间扩大到capacity = capacity + 1024。也就是每次只扩大1MB的空间。
-
redis中单个字符串最大存储空间是512MB,相当于可以存储char s[512*1024]个空间。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct _str{
char *arr;
int len;
int capacity;
};
typedef _str string;
string init_string(char *s)
{
int len = strlen(s);
int init_size = len + 5; //比实际存储空间略大
string str;
str.arr = (char *)malloc(sizeof(char)*init_size);
str.len = len; //长度
str.capacity = init_size; //容量
strcpy(str.arr,s); //拷贝字符串
return str;
}
string expand_capacity(int expand_size, string now)
{
string str;
str.arr = (char *)malloc(sizeof(char)*expand_size);
str.len = now.len;
str.capacity = expand_size;
strcpy(str.arr,now.arr); //将now中的字符串拷贝到新空间中
free(now.arr); //释放之间的空间
return str;
}
void info(string s)
{
puts(s.arr);
printf("当前长度len = %d\n", s.len);
printf("当前容量cap = %d\n", s.capacity);
}
int main()
{
// 1. 首次分配空间
string s = init_string("hello world");
info(s);
s = expand_capacity(20, s);
info(s);
return 0;
}