Aerospike 设计 |请求流程内部 |资源
Aerospike Design | Request Flow Internals | Resources
从客户端 API 触发时,我在哪里可以找到有关 read/write 请求在集群中如何流动的信息?
在 Aerospike 配置文档 ( http://www.aerospike.com/docs/reference/configuration ) 中,提到了事务队列、服务线程、事务线程等,但在体系结构文档中没有讨论它们。我想了解它是如何工作的,以便我可以相应地配置它。
服务线程 == 事务队列 == CPU 中的核心数或使用 CPU 固定 - 自动固定配置参数(如果在您的版本中可用并且在您的 [=16= 中可能) ]环境
每个队列的事务线程数-> 3(默认为 4,对于 objsize <1KB,非内存数据命名空间,3 是最优的)
从客户端到集群节点
在您的应用程序中,一条记录的 key is the 3-tuple (namespace, set, identifier). The key is passed to the client for all key-value methods (such as get and put).
客户端然后通过 RIPEMD-160, resulting in a 20B digest. This digest is the actual unique identifier of the record within the specified namespace of your Aerospike cluster. Each namespace has 4096 partitions 散列密钥的 (set, identifier) 部分,分布在集群的节点。
客户端uses 12 bits of the digest确定这个特定键的分区ID。使用分区映射,客户端查找拥有与分区 ID 对应的主分区的节点。随着集群的增长,找到正确节点的成本保持不变 (O(1)),因为它不依赖于记录数或节点数。
客户端将操作及其数据转换为 Aerospike wire protocol 消息,然后使用其池中的现有 TCP 连接(或创建新连接)将消息发送到正确的节点(即持有此分区 ID 的主副本)。
服务线程和事务队列
当操作消息作为 NIC transmit/receive queue 中断传入时,
a service thread picks up the message from the NIC. What happens next depends on the namespace this operation is supposed to execute against. If it is an in-memory namespace, the service thread will perform all of the following steps. If it's a namespace whose data is stored on SSD, the service thread will place the operation on a transaction queue. One of the queue's transaction threads 将执行以下步骤。
主索引查找
每条记录在内存中都有一个 64B 的元数据条目 primary index. The primary-index is expressed as a collection of sprigs per-partition, with each sprig being implemented as a red-black tree。
线程(事务线程或服务线程,如上所述)从记录的摘要中找到分区 ID,并跳到分区的正确分支。
存在、读取、更新、替换
如果操作是 exists、read、update 或 replace,线程获取记录锁,期间其他操作等待访问具体sprig。这是一个非常短暂的锁。线程遍历红黑树以找到具有此摘要的条目。如果操作是 exists, and the metadata entry does exist, the thread will package the appropriate message and respond. For a read, the thread will use the pointer metadata to read the record from the namespace storage.
一个update需要按照上面的方法读取record,然后merge in bin数据。替换类似于更新,但它会跳过首先读取当前记录。如果命名空间在内存中,服务线程会将修改后的记录写入内存。如果命名空间存储在 SSD 上,则合并的记录将放置在存储设备的 streaming write buffer, pending a flush 中。调整主索引中的元数据条目,将其指针更新为记录的新位置。 Aerospike 为 create/update/replace.
执行写时复制
如果replication factor of the namespace is greater than 1. After the record locking process, the operation will also be parked in the RW Hash (Serializer), while the replica write completes. This is where other transactions on the same record will queue up until they hit the transaction pending limit (AKA a hot key). The replica write(s) is handled by a different thread (rw-receive),更新和替换也需要传达给副本,释放事务或服务线程以继续下一个操作。当replica写入完成后RW Hash锁被释放,rw-receive线程将回复消息打包发送回客户端。
创建和删除
如果操作是写入新记录,或者删除记录,则需要修改partition sprig。
和update/replace一样,这些操作获取记录级锁,将通过RW散列。因为他们从代表树枝的红黑树中添加或删除元数据条目,所以他们还必须获取索引树归约锁。当名称空间主管线程找到 expired records 并将它们从主索引中删除时,也会发生此过程。创建操作将向分区分支添加一个元素。
如果命名空间存储在 SSD 上,则创建会将记录加载到流式写入缓冲区,等待刷新到 SSD,并在副本写入之前。它将更新主索引中的元数据条目,调整其指向新块的指针。
删除会从主索引的分区分支中删除元数据条目。
总结
- exists/read 抢记录级锁,持有时间最短。当复制因子为 1 时,update/replace 也是如此。
- update/replace 当复制因子大于 1 时,也获取 RW 哈希锁。
- create/delete也抢索引树缩减锁
- 对于内存中的命名空间,服务线程会完成所有工作,直至可能达到副本写入点。
- 对于 SSD 名称空间上的数据,服务线程将操作抛出到事务队列中,之后其事务线程之一处理诸如将记录加载到流式写入缓冲区以进行写入的操作,直到潜在的副本写入。
- rw-receive 线程处理副本写入并在 update/replace/create/delete 写入操作后返回消息。
进一步阅读
- 我已经解决了键值操作,但没有解决批处理、扫描或查询问题。一旦了解了单读的工作原理,batch-reads and single-key reads 之间的区别就更容易理解了。
- Durable deletes 不从主索引中删除此记录的元数据条目。相反,这些是墓碑的新写入操作。主索引中将有一个新的64B条目,SSD中将有一个128B条目用于记录。
- Performance optimizations with CPU pinning. See:
auto-pin
, service-threads
, transaction-queues
.
服务器版本 4.7+ 的更改,事务现在由服务线程本身处理。默认情况下,服务线程数现在设置为 5 x no。 cpu 个核心。一旦服务线程从套接字缓冲区中选择了一个事务,它就会完成它,除非它在 rwHash 中结束(例如为复制而写)。事务队列仍然存在(内部),但仅与在 rwHash 中排队时事务重新启动相关。 (同一摘要的多个未决交易)。
从客户端 API 触发时,我在哪里可以找到有关 read/write 请求在集群中如何流动的信息?
在 Aerospike 配置文档 ( http://www.aerospike.com/docs/reference/configuration ) 中,提到了事务队列、服务线程、事务线程等,但在体系结构文档中没有讨论它们。我想了解它是如何工作的,以便我可以相应地配置它。
服务线程 == 事务队列 == CPU 中的核心数或使用 CPU 固定 - 自动固定配置参数(如果在您的版本中可用并且在您的 [=16= 中可能) ]环境
每个队列的事务线程数-> 3(默认为 4,对于 objsize <1KB,非内存数据命名空间,3 是最优的)
从客户端到集群节点
在您的应用程序中,一条记录的 key is the 3-tuple (namespace, set, identifier). The key is passed to the client for all key-value methods (such as get and put).
客户端然后通过 RIPEMD-160, resulting in a 20B digest. This digest is the actual unique identifier of the record within the specified namespace of your Aerospike cluster. Each namespace has 4096 partitions 散列密钥的 (set, identifier) 部分,分布在集群的节点。
客户端uses 12 bits of the digest确定这个特定键的分区ID。使用分区映射,客户端查找拥有与分区 ID 对应的主分区的节点。随着集群的增长,找到正确节点的成本保持不变 (O(1)),因为它不依赖于记录数或节点数。
客户端将操作及其数据转换为 Aerospike wire protocol 消息,然后使用其池中的现有 TCP 连接(或创建新连接)将消息发送到正确的节点(即持有此分区 ID 的主副本)。
服务线程和事务队列
当操作消息作为 NIC transmit/receive queue 中断传入时, a service thread picks up the message from the NIC. What happens next depends on the namespace this operation is supposed to execute against. If it is an in-memory namespace, the service thread will perform all of the following steps. If it's a namespace whose data is stored on SSD, the service thread will place the operation on a transaction queue. One of the queue's transaction threads 将执行以下步骤。
主索引查找
每条记录在内存中都有一个 64B 的元数据条目 primary index. The primary-index is expressed as a collection of sprigs per-partition, with each sprig being implemented as a red-black tree。
线程(事务线程或服务线程,如上所述)从记录的摘要中找到分区 ID,并跳到分区的正确分支。
存在、读取、更新、替换
如果操作是 exists、read、update 或 replace,线程获取记录锁,期间其他操作等待访问具体sprig。这是一个非常短暂的锁。线程遍历红黑树以找到具有此摘要的条目。如果操作是 exists, and the metadata entry does exist, the thread will package the appropriate message and respond. For a read, the thread will use the pointer metadata to read the record from the namespace storage.
一个update需要按照上面的方法读取record,然后merge in bin数据。替换类似于更新,但它会跳过首先读取当前记录。如果命名空间在内存中,服务线程会将修改后的记录写入内存。如果命名空间存储在 SSD 上,则合并的记录将放置在存储设备的 streaming write buffer, pending a flush 中。调整主索引中的元数据条目,将其指针更新为记录的新位置。 Aerospike 为 create/update/replace.
执行写时复制如果replication factor of the namespace is greater than 1. After the record locking process, the operation will also be parked in the RW Hash (Serializer), while the replica write completes. This is where other transactions on the same record will queue up until they hit the transaction pending limit (AKA a hot key). The replica write(s) is handled by a different thread (rw-receive),更新和替换也需要传达给副本,释放事务或服务线程以继续下一个操作。当replica写入完成后RW Hash锁被释放,rw-receive线程将回复消息打包发送回客户端。
创建和删除
如果操作是写入新记录,或者删除记录,则需要修改partition sprig。
和update/replace一样,这些操作获取记录级锁,将通过RW散列。因为他们从代表树枝的红黑树中添加或删除元数据条目,所以他们还必须获取索引树归约锁。当名称空间主管线程找到 expired records 并将它们从主索引中删除时,也会发生此过程。创建操作将向分区分支添加一个元素。
如果命名空间存储在 SSD 上,则创建会将记录加载到流式写入缓冲区,等待刷新到 SSD,并在副本写入之前。它将更新主索引中的元数据条目,调整其指向新块的指针。
删除会从主索引的分区分支中删除元数据条目。
总结
- exists/read 抢记录级锁,持有时间最短。当复制因子为 1 时,update/replace 也是如此。
- update/replace 当复制因子大于 1 时,也获取 RW 哈希锁。
- create/delete也抢索引树缩减锁
- 对于内存中的命名空间,服务线程会完成所有工作,直至可能达到副本写入点。
- 对于 SSD 名称空间上的数据,服务线程将操作抛出到事务队列中,之后其事务线程之一处理诸如将记录加载到流式写入缓冲区以进行写入的操作,直到潜在的副本写入。
- rw-receive 线程处理副本写入并在 update/replace/create/delete 写入操作后返回消息。
进一步阅读
- 我已经解决了键值操作,但没有解决批处理、扫描或查询问题。一旦了解了单读的工作原理,batch-reads and single-key reads 之间的区别就更容易理解了。
- Durable deletes 不从主索引中删除此记录的元数据条目。相反,这些是墓碑的新写入操作。主索引中将有一个新的64B条目,SSD中将有一个128B条目用于记录。
- Performance optimizations with CPU pinning. See:
auto-pin
,service-threads
,transaction-queues
.
服务器版本 4.7+ 的更改,事务现在由服务线程本身处理。默认情况下,服务线程数现在设置为 5 x no。 cpu 个核心。一旦服务线程从套接字缓冲区中选择了一个事务,它就会完成它,除非它在 rwHash 中结束(例如为复制而写)。事务队列仍然存在(内部),但仅与在 rwHash 中排队时事务重新启动相关。 (同一摘要的多个未决交易)。