Aerospike Cient 基础
client配置与连接
初始Aerospike对象
Aerospike 对象代表一个单独的集群,如果我们想连接多个集群,必须得创建多个Aerospike对象。
只要我们的client连接上了一个Aerospike集群中的节点,那么它会自动发现该集群的其他client的。所以为了跟一个Aerospike集群通信,我们必须得初始化过Aerospike对象。
每一个Aerospike对象里内部都包含了一个Aerospike集群的状态和维持着一个相应的连接池。
初始化 配置
as_config config;
as_config_init(&config);
config.hosts[0] = { .addr = "127.0.0.1", .port = 3000 };
初始化Aerospike对象,初始化失败返回NULL指针
aerospike as;
aerospike_init(&as, &config);
client 连接管理
发起连接
如果我们初始化成功了,那么我们就可以向该集群去发起连接请求了,aerospike_connect函数可以帮我们发起连接,如果失败as_error会被填充。
as_error err;
if (aerospike_connect(&as, &err) != AEROSPIKE_OK) {
fprintf(stderr, "err(%d) %s at [%s:%d]\n", err.code,
err.message, err.file, err.line);
}
关闭连接
当client不在需要去连接集群,可以使用 aerospike_close 去关闭连接
as_error err;
if (aerospike_close(&as, &err) != AEROSPIKE_OK) {
fprintf(stderr, "err(%d) %s at [%s:%d]\n", err.code, err.message, err.file, err.line);
}
释放资源
跟Aerospike交互我们都是通过Aerospike对象来交互的,所以当我们不用它的时候,需要释放相应的资源,可以通过调用aerospike_destroy(&as)来释放
Kv 接口
Aerospike 基础知识
一个集群初始的时候,Aerospike就会给它配置一个相应的容器,我们把它称为namespace,这个namespace就是传统的db。namespaces 又被划分为 sets 和 records。set 就是传统的表 ,records 就是传统的行。每一行都有一个独一无二的key和多个存储着该行数据的bins(传统的列)。
通过上面的介绍,我们可以发现一个key,可以存储多个相关的值,这就很像一个倒排表。在Aerospike中的key是我们设置的key,value则像一个List,只不过这个List比较特殊,里面可以是不同类型的内容。支持的类型如下所示
integer
string
bytes
double
list
map
GeoJSON
native-language serialized (blobs)
另外Aerospike每一行都包含了相应的元信息。16位的基本信息,它在每次更新的时候会修改,这个是为了并发所设计的,我觉得这个设计很像CAS操作面对ABA问题所设的版本号一个原理
(https://cloud.tencent.com/developer/article/1021132 ).
如下是 Aerospike的基本框架图
Write API
init Record
前俩个接口用法一样,只不过个接口申请的record,后面我们设置它的bin时,它申请bin是在栈上申请的,第二个申请bin时候是在堆上申请的。
第三个接口无论record还是bin都是在堆上申请的。
as_record_inita(struct as_record *, int)
as_record_init(struct as_record*,int)
struct as_record* as_record_new(int num)
as_record rec;
as_record_inita(&rec, 2); // 2 代表初始化2个列
as_record_set_int64(&rec,0);//此时rec内部有了一个相应的bin,这个bin是在栈上
-------------------------------------------------------------------------
as_record rec2;
as_record_init(&rec2,2);//申请2列,
as_record_set_int64(&rec2,1);//此时rec内部有了一个相应的bin结构,这个结构是在堆上的。
---------------------------------------------------------------------------
as_record * rec3;
rec3 = as_record_new(3);
as_record_set_int64(&rec3,3);//此时record和bin都在堆上
后即使as_record_inita 申请的record的bin结构在栈上开辟的内存,但是bin相应的value也可能是在堆上申请的内存,所以总是使用 as_record_destroy()去释放是没问题的。(如果是内置类型就不用调用这个函数了)
init key
as_key_init_str(as_key* key, const as_namespace ns, const as_set set, const char* value);
as_key key;
as_key_init_str(&key, "test", "test-set", "test-key");
1
2
3
init bin
下面的接口用于初始化bin,strp 与 rawp跟str与raw主要区别在于当该bin对应的record在代码中被destroy的时候,该bin一定被释放。
在代码中我们可以通过as_val_reserve来增加 bin 的引用计数,这样即使该record被detroy,该bin也不会被释放。
as_record_get_int64 接口中 fallback 参数,代表默认值,如果bin 不存在 或者 该bin(列)类型不是int的时候返回fallback默认值。使用起来 int64_t value = as_record_get_int64(rec, “bin”, INT64_MAX) 即可。其余返回指针的get API,如果bin不存在 或者 该 bin类型不是你调用接口对应类型的时候会返回NULL。
bool as_record_set_int64(as_record* rec, const as_bin_name name, int64_t value);
bool as_record_set_str(as_record* rec, const as_bin_name name, const char* value);
bool as_record_set_double(as_record* rec, const as_bin_name name, double value);
bool as_record_set_strp(as_record* rec, const as_bin_name name, const char* value, bool free);
as_record_set_raw(as_record* rec, const as_bin_name name, const uint8_t* value, uint32_t size);
bool as_record_set_rawp(as_record* rec, const as_bin_name name, const uint8_t* value, uint32_t size, bool free);
example:
as_record_set_int64(rec, "ibin", 123);
as_record_set_str(rec, "sbin", "abc");
as_record_set_strp(rec, "spbin", strdup("ijk"), true);
as_record_set_raw(rec, "rbin", (uint8_t*)"xyz", 3);
-----------------------------------------------------------------
bool as_record_set_bytes(as_record* rec, const as_bin_name name, as_bytes * value);
bool as_record_set_list(as_record* rec, const as_bin_name name, as_list * value);
bool as_record_set_map(as_record* rec, const as_bin_name name, as_map * value);
bool as_record_set_string(as_record* rec, const as_bin_name name, as_string * value);
-----------------------------------------------------------------
int64_t as_record_get_int64(const as_record* rec, const as_bin_name name, int64_t fallback);
double as_record_get_double(const as_record* rec, const as_bin_name name, double fallback);
char* as_record_get_str(const as_record* rec, const as_bin_name name);
as_integer* as_record_get_integer(const as_record* rec, const as_bin_name name);
as_double* as_record_get_as_double(const as_record* rec, const as_bin_name name);
as_string* as_record_get_string(const as_record* rec, const as_bin_name name);
as_val_reserve 用法
调用as_val_reserve 后,即使该record被destroy了,其bin也不会被释放。但是bin是否destroy 不影响我们在Aerospike中进行操作,所以还是不要用这么骚的操作。
as_arraylist list;
as_arraylist_init(&list, 3);
as_arraylist_append_str(&list,"1");
as_arraylist_append_int64(&list,"2");
as_arraylist_append_int64(&list, "3");
as_record rec;
as_record_inita(&rec, 1);
as_record_set_list(&rec, "lbin", (as_list*)as_val_reserve(&list));
as_record_destroy(&rec);
char * p = as_arraylist_get_str(&list, 1);
char * p2 = as_arraylist_get_str(&list, 2);
char * p3 = as_arraylist_get_str(&list, 3);
as_arraylist_destroy(&list);
17
设置数据的超时值
当我们设置了一个record的超时值的时候,这个record超时后,Aerospike会删除它。
rec->ttl = 128;代表确切的128s删除
rec->ttl = 0;代表使用db的TTL时间
rec->ttl = -1;代表不设置TTL时间
遍历record
Aerospike主要通过以下俩个接口去遍历bin。as_record_foreach 迭代遍历record的所有bin,并为每一个bin都调用用户自己设置的回调函数。as_record_iterator接口,这个接口会返回一个 record的迭代器,然后配用相关迭代器接口完成调用。
as_record_foreach
@param name bin名
@param value bin的值
@param udata 我们调as_record_foreach传的值
@return true 继续遍历
@return false 中止遍历
bool callback(const char *name, const as_val *value, void *udata);
@param:record 待遍历的record
@param:callback 每个bin都要调用的回调函数
@param:data 我们设置的data,可以为NULL,它会被传入回调中
@return true 全部元素都遍历了
@return false 遍历中止了
as_record_foreach(record*,callback*,data*);
data 为回调函数中的data
example :
bool print_bin(const char* name, const as_val * value, void* udata) {
char * sval = as_val_tostring(value);
printf("bin: name=%s, value=%s\n", name, sval);
free(sval);
return true;
}
as_record_foreach(rec, print_bin, NULL);
bool callback(const char *name, const as_val *value, void *udata)
{
as_integer *ivalue = as_integer_fromval(value);
if (ivalue) {
printf("%s = %d\n", name, as_integer_get(ivalue));
}
else {
printf("%s is not an integer?!\n", name);
}
return true;
}
as_record rec;
as_record_inita(&rec, 3);
as_record_set_int64(&rec, "a", 1);
as_record_set_int64(&rec, "b", 2);
as_record_set_int64(&rec, "c", 3);
as_record_foreach(&rec, callback, NULL);
as_record_iterator
as_record_iterator it;
as_record_iterator_init(&it, &rec);
while (as_record_iterator_has_next(&it)) {
as_bin *bin = as_record_iterator_next(&it);
char *name = as_bin_get_name(bin);
as_val *value = (as_val*)as_bin_get_value(bin);
as_integer *ivalue = as_integer_fromval(value);
if (ivalue) {
printf("%s = %d\n", name, as_integer_get(ivalue));
}
else {
printf("%s is not an integer?!\n", name);
}
}
Aerospike Select 坑
今天使用了 aerospike_key_select 指定bin查找,但是发现如果这个key 不为空,但是没有我们要查找的bin,aerospike_key_select 并不会报错,它的返回码等于AEROSPIKE_OK。这就造成当我们可能读取返回值的时候发生错误
————————————————
版权声明:本文为CSDN博主「sdoyuxuan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sdoyuxuan/article/details/84325903
相关文章