Aerospike用例分析

简介:     Aerospike是一个以分布式为核心,T级别大数据高并发的……,参见《Aerospike入坑导读》https://yq.aliyun.com/articles/622455?spm=a2c4e.11155435.0.0.36e43312Nq4iTX,针对常用的一般性操作给出九个用例,代码采用GO语言实现,JAVA、C\C++以及其他语言的实现都差不多,同样具有参考意义。

       Aerospike是一个以分布式为核心,T级别大数据高并发的……,参见《Aerospike入坑导读》https://yq.aliyun.com/articles/622455?spm=a2c4e.11155435.0.0.36e43312Nq4iTX,针对常用的一般性操作给出九个用例,代码采用GO语言实现,JAVA、C\C++以及其他语言的实现都差不多,同样具有参考意义。

func asInformation() {
	url := fmt.Sprintf("%s:%d", AS_HOST, AS_PORT)

	if con, err := as.NewConnection(url, time.Second * 10); err == nil {
		defer con.Close()

		if ifs, err := as.RequestInfo(con, ""); nil == err {
			for k, v := range ifs {
				/**
				 * features: peers;cdt-list;cdt-map;cluster-stable;pipelining;geo ...
				 * build: 4.2.0.5
				 * version: Aerospike Community Edition build 4.2.0.5
				 * build_os: el7
				 * statistics: cluster_size=1;cluster_key=E50AB9AFD60C;cluster_in ...
				 * services-alumni:
				 * services:
				 * partition-generation: 0
				 * node: BB9822D9A270008
				 * edition: Aerospike Community Edition
				 * build_time: Mon Jul 16 19:02:48 UTC 2018
				 */
				fmt.Printf("%s: %s\n", k, v)
			}
		}
	} else {
		panic(err.Error())
	}
}

       用例一:asInformation获取aerospike的基础信息,第64行调用RequestInfo函数,函数的第一个参数为aerospike的连接句柄,第二个参数为信息名称,空则返回全部信息,结果保存在map容器中。

func asMapToRecord(cli *as.Client) {
	arr := []byte{0x11, 0x21, 0x31}
	lst := []interface{}{111, "STRING", arr}
	mmp := map[interface{}] interface{} {
		"key1": 1,
		"key2": "A",
		"key3": arr,
		"key4": lst,
	}

	mybin := "mybin1"
	bin := as.NewBin(mybin, mmp)
	cli.PutBins(AS_WPLC, AS_NKEY, bin)

	if rst, err := cli.Get(AS_PLCY, AS_NKEY, bin.Name); nil == err {
		val := rst.Bins[bin.Name].(map[interface{}] interface{})
		fmt.Printf("Intege: %d, String: %s, []Byte: %v, Map: %v\n", val["key1"], val["key2"], val["key3"], val["key4"])
	}
}

       用例二:asMapToRecord以map数据结构作为bin存储的数据类型,93、94、95行构造了一个map实例,且每个节点的数据类型都不一样,分别为整形、字符串、字符数组和链表(其中链表中包含三个元素,分别为整形、字符串和字符数组),可见GO语言的map对数据类型的支持是多么的肆意妄为。查询的结果以键值对的方式返回,指定key从而读取value。

func asListToRecord(cli *as.Client) {
	mybin := "mybin2"
	bin := as.NewBin(mybin, []interface{}{111, "STRING_111", []byte{0x11, 0x21, 0x31}})

	cli.PutBins(AS_WPLC, AS_NKEY, bin)

	if rst, err := cli.Get(AS_PLCY, AS_NKEY, bin.Name); nil == err {
		val := rst.Bins[bin.Name].([]interface{})
		fmt.Printf("Intege: %d, String: %s, []Byte: %v\n", val[0], val[1], val[2])
	}
}

       用例三:asListToRecord以链表数据结构作为bin存储的数据类型,第119行构造了一个链表实例,并附加bin名称定义了一个bin对象,链表结构共三个节点,分别存储整形、字符串和字符数组。查询的结果集以链表方式返回,可以直接通过下标得到数据项。

func asBatchToRecord(cli *as.Client) {
	bn := "mybin3"
	bk := []string{"b_key1", "b_key2", "b_key3", "b_key4"}
	bv := []string{"b_val1", "b_val2", "b_val3", "b_val4"}

	// 写入操作
	for i, k := range bk {
		bin := as.NewBin(bn, bv[i])
		key, _ := as.NewKey(AS_NMSP, AS_MYST, k)
		cli.PutBins(AS_WPLC, key, bin)
	}

	// 存在判断
	ks := make([]*as.Key, len(bk) * 2)
	for i, k := range bk {
		ks[i], _ = as.NewKey(AS_NMSP, AS_MYST, k)
	}
	ks[4], _ = as.NewKey(AS_NMSP, AS_MYST, "b_key5")
	ks[5], _ = as.NewKey(AS_NMSP, AS_MYST, "b_key6")
	ks[6], _ = as.NewKey(AS_NMSP, AS_MYST, "b_key7")
	ks[7], _ = as.NewKey(AS_NMSP, AS_MYST, "b_key8")
	if ext, err := cli.BatchExists(nil, ks); nil == err {
		for i, e := range ext {
			fmt.Printf("ns = %s, set = %s, key = %s, exists = %t\n", ks[i].Namespace(), ks[i].SetName(), ks[i].Value(), e)
		}
	} else {
		panic(err.Error())
	}

	// 批量获取
	if rst, err := cli.BatchGet(nil, ks, bn); nil == err {
		for i, r := range rst {
			if nil != r {
				fmt.Printf("ns = %s, set = %s, key = %s, bin = %s, val = %s\n", ks[i].Namespace(), ks[i].SetName(), ks[i].Value(), bn, r.Bins[bn])
			} else {
				fmt.Printf("ns = %s, set = %s, key = %s, bin = %s, val = %s\n", ks[i].Namespace(), ks[i].SetName(), ks[i].Value(), bn, "nil")
			}
		}
	}
}

       用例四:asBatchToRecord批量操作,140 - 144行写入四条记录,147行故意定义其两倍查询主键数组,其中前四个为刚才写入记录的主键,151 - 154行构造了四个不存在的主键,155行提请批量判断记录是否存在,156 - 158行打印结果至标准输出。164 - 172行采用两倍主键数组批量获取结果集,存在的结果打印,不存在的显示nil。

func asAppendToRecord(cli *as.Client) {
	mybin := "mybin4"

	bin := as.NewBin(mybin, "aero")
	cli.AppendBins(AS_WPLC, AS_NKEY, bin)
	asGetBinsAndPrint("AppendBins第一次调用", cli, AS_NKEY, bin)

	bin = as.NewBin(mybin, "spike")
	cli.AppendBins(AS_WPLC, AS_NKEY, bin)
	asGetBinsAndPrint("AppendBins第二次调用", cli, AS_NKEY, bin)
}

       用例五:asAppendToRecord从右侧向bin中追加数据,183 - 185行写入aero,187 - 189行写入spike,分两次写入完整aerospike数据。

func asAddBinsToRecord(cli *as.Client) {
	val := 8
	mybin := "mybin5"

	bm := make(as.BinMap)
	bm[mybin] = val
	cli.Add(AS_WPLC, AS_NKEY, bm)
	asGetBinsAndPrint("BinMap 传入调用", cli, AS_NKEY, as.NewBin(mybin, val))

	// NewBin 调用累加
	bin := as.NewBin(mybin, val << 1)
	cli.AddBins(AS_WPLC, AS_NKEY, bin)
	asGetBinsAndPrint("NewBin 调用累加", cli, AS_NKEY, bin)

	// Operate调用累加
	bin = as.NewBin(mybin, val << 2)
	cli.Operate(AS_WPLC, AS_NKEY, as.AddOp(bin), as.GetOp())
	asGetBinsAndPrint("Operate调用累加", cli, AS_NKEY, bin)
	//上面一行与下面几行等价,Operate调用累加的同时返回结果。
	//if rst, err := cli.Operate(AS_WPLC, AS_NKEY, as.AddOp(bin), as.GetOp()); nil == err {
	//	fmt.Printf(
	//		"Operate调用累加 ---> ns = %s, set = %s, AS_NKEY = %s, bin = %s, val = %d\n",
	//		AS_NKEY.Namespace(), AS_NKEY.SetName(), AS_NKEY.Value(), bin.Name, rst.Bins[bin.Name])
	//}
}

       用例六:asAddBinsToRecord对bin值进行累加,201 - 204行构造一个map,调用as的Add函数累加,207 - 209行调用as的AddBins函数累加,212 - 214行调用as的Operate函数累加,三种方式导致的结果一致,不同的只是入口参数不同。

func asPrependToRecord(cli *as.Client) {
	mybin := "mybin6"
	wds := []string{"工程师", "研发", "软件", "是", "我"}

	for i, w := range wds {
		bin := as.NewBin(mybin, w)
		cli.PrependBins(AS_WPLC, AS_NKEY, bin)
		asGetBinsAndPrint(strconv.Itoa(i + 1), cli, AS_NKEY, bin)
	}
}

       用例七:asPrependToRecord从左侧向bin中追加数据,为了演示效果特将一句中文分词后从右向左逐一写入bin,每写一次打印输出一次。

func asReplaceToRecord(cli *as.Client) {
	bn := []string{"b_name_1", "b_name_2", "b_name_3"}
	bv := []string{"b_value_1", "b_value_2", "b_value_3"}

	for i, b := range bv {
		bin := as.NewBin(bn[i], b)
		cli.PutBins(AS_WPLC, AS_NKEY, bin)
	}

	fmt.Printf("覆盖前 --- > ")
	if rst, err := cli.Get(AS_PLCY, AS_NKEY, bn[0], bn[1], bn[2]); nil == err {
		for k, v := range rst.Bins {
			fmt.Printf("{bin = %s, val = %s}, ", k, v)
		}
		fmt.Println()
	}

	wp := as.NewWritePolicy(0, 0)
	wp.RecordExistsAction = as.REPLACE
	nb := as.NewBin("b_name_replace", "b_value_replace")

	cli.PutBins(wp, AS_NKEY, nb)
	asGetBinsAndPrint("覆盖后", cli, AS_NKEY, nb)
}

       用例八:asReplaceToRecord对原有记录进行覆盖操作,需要特别注意的一点是PutBins时务必指定所有的bin,已存在的但未传入的bin系统将不会自动保存。248 - 259行写入三个bin并打印至标准输出,261 - 266行采用一个新的bin执行覆盖操作成功后,之前写入的三个bin被删除。

func asGetHeaderFromKey(cli *as.Client) {
	if rst, _ := cli.GetHeader(AS_PLCY, AS_NKEY); nil != rst {
		fmt.Printf("Key.generation = %d, Key.expiration = %d (%s)\n", rst.Generation, rst.Expiration, time.Duration(rst.Expiration) * time.Second)
	} else {
		fmt.Printf("Failed to GetHeader: namespace = %s, set = %s, key = %s\n", AS_NKEY.Namespace(), AS_NKEY.SetName(), AS_NKEY.Value())
	}
}

       用例九:asGetHeaderFromKey查询一个已存在主键的被修改次数和生存期,一个key在没有被修改的情况下,系统默认生存期为720个小时(30天)

       Redis和Aerospike经常被拿来比较,至于用哪里好更多的时候还是要看需求,从总体上看,Aerospike比Redis对结构化数据支持的更好些,数据有效期、集群化管理、容灾容错方面也是各有所长,一定要找一个彼此不可替代的场景还真不好找。现在做个项目工程哪个不需要存点临时的中间数据给各个子系统读读写写的,多个备选方案总不是坏事。

相关文章
|
Java 数据库连接 mybatis
springboot访问jsp页面变成直接下载?
springboot访问jsp页面变成直接下载?
|
安全 数据安全/隐私保护 iOS开发
flutter 代码混淆
flutter 代码混淆
677 0
|
缓存 监控 负载均衡
电商API性能优化全方位策略剖析
电商API性能优化对提升用户体验与业务效率至关重要。本文从八个方面探讨优化策略:1) 数据库优化,如索引设计、查询语句精简及冷热数据分离;2) 缓存策略,利用本地与分布式缓存减少数据库压力;3) 异步处理,通过任务队列提高响应速度;4) 负载均衡,分散高并发请求;5) 代码优化,改进算法与重构低效代码;6) 接口设计优化,标准化与模块化设计;7) 安全措施,强化数据加密与身份验证;8) 持续监控与优化,确保长期稳定运行。综合应用这些策略可显著提升电商API性能与用户体验。
|
编解码 人工智能 文件存储
卷积神经网络架构:EfficientNet结构的特点
EfficientNet是一种高效的卷积神经网络架构,它通过系统化的方法来提升模型的性能和效率。
909 1
ly~
|
监控 Linux API
如何评估 SDL 图形库优化的效果
SDL(Simple DirectMedia Layer)是一个免费开源的多媒体开发库,广泛用于游戏和多媒体应用。优化后的SDL在性能、图像质量、加载速度、兼容性、跨平台性和开发效率等方面均有显著提升。性能方面,优化后的SDL提高了渲染效率和播放路数;图像质量上,通过先进的渲染技术提升了图像的清晰度和色彩准确性;加载速度方面,通过减少格式转换时间加快了图像加载速度;兼容性和跨平台性得到增强,支持多种操作系统和硬件设备;开发效率方面,简洁的API设计和丰富的文档帮助开发者快速上手,减少了开发时间和成本。这些优化使SDL成为游戏开发和多媒体应用的理想选择。
ly~
803 4
|
NoSQL IDE 开发工具
OPENJTAG调试学习(一):嵌入式软件的交叉开发系统
OPENJTAG调试学习(一):嵌入式软件的交叉开发系统
1040 0
|
监控 前端开发 jenkins
Jenkins 在前端项目持续部署中的应用,包括其原理、流程以及具体的实现方法
本文深入探讨了Jenkins在前端项目持续部署中的应用,涵盖其基本原理、流程及具体实现方法。首先介绍了Jenkins的基本概念及其在自动化任务中的作用,随后详细解析了从前端代码提交到生产环境部署的全过程,包括构建、测试、部署等关键步骤。最后,强调了持续部署中的代码质量控制、环境一致性、监控预警及安全管理等注意事项,旨在帮助开发者高效、安全地实施持续部署。
490 5
|
JSON 前端开发 Java
【Java笔记+踩坑】SpringMVC基础
springmvc简介、入门案例、bean加载控制、PostMan工具的使用、普通和JSON和日期格式请求参数传递、响应JSON或jsp或文本、Rest风格
【Java笔记+踩坑】SpringMVC基础
|
存储 编解码 缓存
电脑关键组件
电脑关键组件
578 1
|
数据可视化
8个常见的数据可视化错误以及如何避免它们
本文揭示了8个数据可视化常见错误:误导色彩对比、过多的数据图表、省略基线、误导性标签、错误的可视化方法、不实的因果关系、放大有利数据和滥用3D图形。强调清晰、准确和洞察力的重要性,提醒制作者避免使用过多颜色、一次性展示大量数据、错误图表类型以及展示无关相关性等。正确可视化能有力支持决策,不应牺牲真实性以追求视觉效果。
1653 6

热门文章

最新文章