前提:Aerospike必须要在5.0版本以后,有些操作甚至只在6.0有
1.查询所有的namespace|set|key
(1) 查询Aerospike集群下的所有的namespace
public class Test {
public static void main(String[] args) {
// 创建 ClientPolicy 对象
ClientPolicy policy = new ClientPolicy();
// 设置主机地址和端口号
String host = "10.204.196.243";
int port = 3000;
// 创建 Aerospike 客户端
AerospikeClient client = new AerospikeClient(policy, host, port);
try {
// 获取所有节点的信息
InfoPolicy infoPolicy = new InfoPolicy();
Node[] nodes = client.getNodes();//获取集群的节点信息
for (Node node : nodes) {
String response = Info.request(infoPolicy, node, "namespaces");
if (response != null && !response.isEmpty()) {
System.out.println("Node: " + node);
System.out.println("Namespaces: " + response);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭客户端
client.close();
}
}
}
(2) 查询当前namespace对应的set表下的所有key
需要补充参数:ScanPolicy策略、namespace、setName、ScanCallback回调函数、bin可变形参
ClientPolicy clientPolicy = new ClientPolicy();
AerospikeClient client = new AerospikeClient(clientPolicy,"10.204.196.243",3000);
ScanPolicy scanPolicy = new ScanPolicy();
client.scanAll(scanPolicy, "mediav", "test_batch", new ScanCallback() {
@Override
public void scanCallback(Key key, Record record) throws AerospikeException {
System.out.println("key:"+key);
System.out.println("Record:"+record);
}
});
补充-1 ScanCallback函数
将每次scan扫完的record都调用这个方法;scan如果中断了会报以下异常
com.aerospike.client.AerospikeException.ScanTerminated AerospikeException.ScanTerminated
如果引发任何异常,则到其他节点的并行扫描线程也将被终止,并且异常将通过启动的扫描调用传播回去。
如果ScanPolicy.concurrentNodes设置为true且ScanPolicy.maxConcurrentNodes设置不为1,那么你的scanCallback函数必须是线程安全的
3.异步操作API—底层解决了线程不安全问题,需要服务器的as版本>4.9
小案例
public class Test2 {
public static void main(String[] args) throws InterruptedException {
//不能直接使用同步的client,初始化一个异步的client
//创建EventLoops
EventPolicy eventPolicy = new EventPolicy();
EventLoops eventLoops = new NioEventLoops(eventPolicy,4);
//初始化异步as客户端需要指定EventLoops
ClientPolicy clientPolicy = new ClientPolicy();
clientPolicy.eventLoops=eventLoops;
AerospikeClient aerospikeClient = new AerospikeClient(clientPolicy,"10.204.196.243",3000);
WritePolicy wp = new WritePolicy();
wp.generationPolicy= GenerationPolicy.EXPECT_GEN_GT;
//开始准备异步写入
EventLoop eventLoop = eventLoops.next();
WriteListener writeListener = new WriteListener() {
@Override
public void onSuccess(Key key) {
System.out.println("写入成功");
System.out.println(key.toString());
System.out.println(aerospikeClient.get(null,key));
}
@Override
public void onFailure(AerospikeException exception) {
System.out.println("写入异常");
System.out.println(exception.toString());
}
};
Key key = new Key("mediav","test_async",1);
aerospikeClient.delete(null,key);
String[] arr=new String[20];
for (int i = 0; i < arr.length; i++) {
arr[i]="test-"+i;
}
for(int i=0;i<20;i++){
Bin bin1 = new Bin("name",arr[i]);
Bin bin2 = new Bin("age",18+i);
aerospikeClient.put(eventLoop, writeListener,null,key,bin1,bin2);
Record record = aerospikeClient.get(null, key);
System.out.println(i+1+"record:"+record);
}
TimeUnit.SECONDS.sleep(5);
System.out.println("最终的record:"+aerospikeClient.get(null,key));
//关闭顺序不能变
aerospikeClient.close();
eventLoops.close();
}
}
(1) EventPolicy和EventLoops底层解析
<1> EventPolicy
EventPolicy是异步策略,用于控制异步事件处理方式的配置类,它定义了如何处理异步操作的回调和事件调度。
EventPolicy ep = new EventPolicy();
ep.maxCommandsInProcess=10;//用于限制事件循环中最大允许的并发命令数量。默认是0,表示立即执行所有异步操作。
ep.maxCommandsInQueue=8;//每个事件循环的延迟队列中可存储的最大异步命令数量(就是等待线程的最大数量)。默认是0,表示无限制。
ep.queueInitialCapacity=256;//初始化延迟队列的容量。默认是256。
ep.minTimeout=100;//最小超时时间。默认是100ms。
<2> EventLoops
EventLoops 是一组线程,专门用于处理网络 I/O 事件。每个 EventLoop 线程负责监听和处理网络连接上的读写事件。API通过ClientPolicy可以配置 EventLoops的数量以及每个EventLoop中的线程数量,可以确保异步操作的高效处理。
每个 EventLoops 实例都可以在多个 AerospikeClient 实例之间共享。EventLoops 实例的事件循环数应近似于计算机上为 AerospikeClient 处理保留的 CPU 内核数。支持 Netty 和直接 NIO 事件循环。
//NIO声明
EventPolicy eventPolicy = new EventPolicy();//创建事件循环策略
EventLoops eventLoops = new NioEventLoops(eventPolicy, 4);//使用eventPolicy策略并设置NIO循环数为4
底层调用如下
参数解析
@param policy 事件循环策略
@param size NIO事件循环数
@param daemon 如果相关线程应作为守护进程运行,则参数 daemon 为 true
@param poolName 事件循环线程池名称
//Netty声明
EventPolicy eventPolicy = new EventPolicy();
EventLoopGroup group = new NioEventLoopGroup(4);//指定事件循环的类型是NIO类型,并设置实例的线程数
EventLoops eventLoops = new NettyEventLoops(eventPolicy, group);
<3> 异步写入操作
需要传的参数是EventLoop、WriteListener监听者、写入策略、Key、Bin可变形参
public static void main(String[] args) throws InterruptedException {
//不能直接使用同步的client,初始化一个异步的client
//创建EventLoops
EventPolicy eventPolicy = new EventPolicy();
EventLoops eventLoops = new NioEventLoops(eventPolicy,4);
//初始化异步as客户端需要指定EventLoops
ClientPolicy clientPolicy = new ClientPolicy();
clientPolicy.eventLoops=eventLoops;
AerospikeClient aerospikeClient = new AerospikeClient(clientPolicy,"10.204.196.243",3000);
WritePolicy wp = new WritePolicy();
wp.generationPolicy= GenerationPolicy.EXPECT_GEN_GT;
//开始准备异步写入,eventLoops.next()是以轮询方式返回下一个eventloop对象
EventLoop eventLoop = eventLoops.next();
//声明写操作监听者(是一个匿名内部类,需要重写两个方法,分别是写入成功和写入失败的情况)
WriteListener writeListener = new WriteListener() {
@Override
public void onSuccess(Key key) {
System.out.println("写入成功");
System.out.println(key.toString());
System.out.println(aerospikeClient.get(null,key));
}
@Override
public void onFailure(AerospikeException exception) {
System.out.println("写入异常");
System.out.println(exception.toString());
}
};
Key key = new Key("ns1","test_async");
Bin bin = new Bin("test","test_async");
aerospikeClient.put(eventLoop, writeListener,null,key,bin);
TimeUnit.SECONDS.sleep(5);
client.close();
eventLoops.close();
}
}
3.批量操作—Maven的as版本要6.0.0以上并且服务器上的asClient版本要在6.0.0以上
(1) operate操作以及Operation类—put/get的底层
<1> client.operate()操作
(1)多个Operation的执行顺序
在单条记录上的操作将按照在 operate() 调用中指定的顺序应用。Aerospike 保证这些操作是原子性的,即所有操作要么全部成功,要么全部失败,且在第一个操作和最后一个操作之间不会有其他线程影响该记录。
操作顺序有时很重要。例如,假设希望 Aerospike 在插入新商品前返回购物车中商品的总价,并在插入商品后再次返回总价。可以修改程序如下:
Record record = client.operate(null, key,
Operation.get("cost"),
Operation.append(new Bin("items", itemDescr + ",")),
Operation.add(new Bin("totalItems", 1)),
Operation.add(new Bin("cost", cost)),
Operation.get("cost")
);
//下面是代码解析
在此示例中,首先获取 cost bin 的值,更新后再次获取。这样做在 Aerospike 中是有效的,但返回的结果会是什么呢?幸运的是,Record 对象有一个有用的 toString() 方法,因此可以在返回 Record 后立即添加以下代码来查看返回值:
System.out.println(record);
结果如下:
(gen:1),(exp:0),(bins:(cost:59.25))
(gen:2),(exp:0),(bins:(cost:[59.25, 89.2]))
(gen:3),(exp:0),(bins:(cost:[89.2, 109.15]))
<2> Operation类
| 方法 | 描述 |
|---|---|
add(Bin) | 将 bin 增加传入的 Bin 值。如果 bin 不存在,将用传入的值创建该 bin。如果传入的值或数据库中现有的值非数值类型,将抛出 AerospikeException,并返回 ResultCode.BIN_TYPE_ERROR 代码。 |
append(Bin) | 将传入的字符串值添加到 bin 字符串的末尾。如果 bin 不存在,将用传入的值创建 bin。如果传入的值或数据库中现有的值非字符串类型,将抛出 AerospikeException,返回 ResultCode.BIN_TYPE_ERROR。 |
get() | 返回记录中所有 bin 的内容。 |
get(String) | 返回指定 bin 的内容。如果该 bin 不存在,则不返回任何内容。 |
put(Bin) | 将 bin 的内容设置为传入的值。 |
声明Operation=对象,需要传Type、binName、Value
Operation.Type:是个枚举,有WRITE、ADD等
binName:对那个bin进行操作
Value:操作的类型内容是什么
//案例如下
Operation operation1 = new Operation(Operation.Type.APPEND,"name",new Value.StringValue("_test"));//在name字段后拼接_test
Operation operation2 = new Operation(Operation.Type.WRITE,"age",new Value.IntegerValue(1));//插入一个age字段值为1
Operation operation3 = new Operation(Operation.Type.ADD,"age",new Value.IntegerValue(7));//将age字段的值+7
<3> ListOperation和MapOperation
(1)ListOperation
先来理解列表
现有一列表:[1, 4, 7, 3, 9, 26, 11],把他插入到set中
| 列表 | 1 | 4 | 7 | 3 | 9 | 26 | 11 |
|---|---|---|---|---|---|---|---|
| 索引 | 0或-7 | 1或-6 | 2或-5 | 3或-4 | 4或-3 | 5或-2 | 6或-1 |
| 排名 | 0或-7 | 2或-5 | 3或-4 | 1或-6 | 4或-3 | 6或-1 | 5或-2 |
注意:
ListOperation是支持负索引的,index-1表示倒数第一位
下面表格是简单的CRUD操作;
| 方法 | 描述 |
|---|---|
| ListOperation.size(String binName) | 返回list的大小 |
| ListOperation.get(String binName,int index) | 获取指定索引位置的元素 |
| ListOperation.getByIndex(String binName,int index,int returnType) | 返回指定索引元素的returnType数据 |
| ListOperation.getByRank(String binName,int rank,int returnType) | 返回按照元素大小排序后排行第rank个元素的returnType数据 |
| ListOperation.insert(String binName,int index,Value value) | 在对应bin的指定位置插入元素,并返回长度 |
| ListOperation.set(String binName,int index,Value value) | 将对应bin下的指定索引的元素设置为指定值 |
| ListOperation.append(String binName,Value value) | 对指定的List类型bin末尾追加一个元素,并返回长度 |
| ListOperation.appendItems(String binName,List list) | 对指定的List类型bin末尾追加多个元素,并返回长度 |
| ListOperation.remove(String binName,int index) | 删除指定索引位置的元素,并返回删除的个数 |
| ListOperation.pop(String binName,int index) | 将指定位置的元素出列,在bin中删除该元素并返回该元素 |
| ListOperation.trim(String binName,int index,int count) | 保留指定索引之后count个元素,其余全部删除,返回删除的个数 |
| ListOperation.clear(String binName) | 清空对应bin,默认不返回结果 |
| ListOperation.setOrder(String binName,ListOrder order) | 对指定的list类型bin进行排序,返回null。order可选参数:ListOrder.ORDERED(排序)、ListOrder.UNORDERED(未排序,默认) |
| ListOperation.sort(String binName,int sortFlags) | 对指定的list类型bin进行排序,默认不返回结果。sortFlags可选参数:ListSortFlags.DEFAULT(保留重复值)、ListSortFlags.DROP_DUPLICATES(去除重复值) |
(2)MapOperation
比如:{a:1, b:2, c:30, y:30, z:26}
| 键 | a | b | c | y | z |
|---|---|---|---|---|---|
| 值 | 1 | 2 | 30 | 30 | 26 |
| 索引 | 0 或 -5 | 1 或 -4 | 2 或 -3 | 3 或 -2 | 4 或 -1 |
| 排名 | 0 或 -5 | 1 或 -4 | 3 或 -2 | 4 或 -1 | 2 或 -3 |
下面表格是简单的CRUD操作
| 方法 | 描述 |
|---|---|
| MapOperation.size(String binName) | 返回map的大小 |
| MapOperation.getByKey(String binName,Value key,int returnType) | 根据key返回元素的returnType数据 |
| MapOperation.getByValue(String binName,Value value,int returnType) | 根据value返回元素的returnType数据 |
| MapOperation.getByIndex(String binName,int index,int returnType) | 根据索引位置返回对应元素的returnType数据 |
| MapOperation.getByRank(String binName,int rank,int returnType) | 返回排序后第rank位置元素的returnType数据 |
| MapOperation.put(MapPolicy policy,String binName,Value key,Value value) | 在map中放入新键值对,并且返回map的大小,policy不可为null |
| MapOperation.putItems(MapPolicy policy,String binName,Map<Value,Value> map) | 批量放入键值对,并且返回map的大小,policy不可为null |
| MapOperation.clear(String binName) | 清空map |
| MapOperation.removeByKey(String binName,Value key,int returnType) | 删除指定key的元素,并根据returnType返回被删除元素 |
| MapOperation.removeByValue(String binName,Value value,int returnType) | 删除指定值的元素,并根据returnType返回被删除元素 |
| MapOperation.removeByIndex(String binName,int index,int returnType) | 删除指定索引位置的元素,并根据returnType返回删除元素 |
| MapOperation.removeByRank(String binName,int rank,int returnType) | 删除排序后第rank位置元素的returnType数据 |