RedisParam 1.0.0
This vignette is for the developer who wants to understand the secret
behind RedisParam
. The regular user does not need to read this
document for using the package.
The image below shows the framework of RedisParam
. Unlike the
traditional one-to-many structure where the worker only serves one
manager. RedisParam
allows for multiple managers and workers to
connect with the same job queue. The job is done in a first-come,
first-serve basis.
For making the package robust, RedisParam
is developed with a few
principles in mind.
resisting worker loss: A worker might be died at any time for any reason, the manager must be able to find the missing task due to the died worker and resubmit the task.
Job queue robustness: Since any one can destroy the entire data on the server at any time. The job queue, the bridge between the manager and worker, must be resilient. After a data loss, the current job can fail but the queue should be still able to process new jobs.
For implementing the package while satisfying the design principles, we require that maintaining the job queue on the server should not need any data on the server. Therefore, even if all data in Redis has been lost, the connection between the manager and workers should still be maintained.
The data used in Redis can be divided into three components: queue, manager data. Just as the image shows
Public data is the data that can be viewed by all managers and workers with the same job queue name. It includes
The manager data has
constant queue: This is not a queue, but an object which is used to store the data that does not vary across all tasks. We call it a queue as it is implemented using the list structure in Redis
manager result queue: The queue which stores the results from the worker
manager task(s): The serialized task data. The task ID contains information about whether it is a public task and whether it requires constant data, so the worker can use it to quickly determine if it needs to download the constant data from Redis.
manager task set: A set of task ID which the manager has sent to the public queue and haven’t finished by the worker
The manager has two functions to send the task to the worker, namely
.send_to
and .manager_send
. The former one is used to send the
task to a specific worker(private queue) while the later one can send
the task to any worker(public queue). Below is the workflow of the
task submission.
The receiving operation is a blocking operation, it will block the r
session for a few seconds if there is no result available, then check
for if there is any missing tasks, then blocks R again. The manager
will use the BLPOP
operation to pop the result from
managerResultQueue
in Redis
Receiving the task from the job queue in the worker requires a little more work. The worker will try to pop the task ID from both public and private queues. This is a blocking operation so the worker only continues when there is at least one task available. Once the worker received the task, it decompose the task ID to determine the manager ID and whether the task needs the constant data. Then get the task data and its constant data(if required). The worker also needs to cache the constant data for the future tasks. Below is the workflow for receiving a task in the worker
When sending back the result to Redis, the worker is responsible to
check whether the manager still has the task ID in
managerTaskSet
. By doing this, we make sure there will not be any
unnecessary data transmission and the manager would not receive an
incorrect result. This can happens if the user interrupt the manager
process before the job is finished or the Redis server loses all its
data(either on purpose or by accident).
If the manager still has the task ID, the worker will then push the
result to managerResultQueue
, then removes the task ID from
managerTaskSet
, the worker ID from workerTaskMap
and deletes the
task itself from Redis.
This version of the vignette was built on 2022-11-01 with the following software package versions:
#> R version 4.2.1 (2022-06-23)
#> Platform: x86_64-pc-linux-gnu (64-bit)
#> Running under: Ubuntu 20.04.5 LTS
#>
#> Matrix products: default
#> BLAS: /home/biocbuild/bbs-3.16-bioc/R/lib/libRblas.so
#> LAPACK: /home/biocbuild/bbs-3.16-bioc/R/lib/libRlapack.so
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_GB LC_COLLATE=C
#> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] BiocStyle_2.26.0
#>
#> loaded via a namespace (and not attached):
#> [1] bookdown_0.29 digest_0.6.30 R6_2.5.1
#> [4] jsonlite_1.8.3 magrittr_2.0.3 evaluate_0.17
#> [7] stringi_1.7.8 cachem_1.0.6 rlang_1.0.6
#> [10] cli_3.4.1 jquerylib_0.1.4 bslib_0.4.0
#> [13] rmarkdown_2.17 tools_4.2.1 stringr_1.4.1
#> [16] xfun_0.34 yaml_2.3.6 fastmap_1.1.0
#> [19] compiler_4.2.1 BiocManager_1.30.19 htmltools_0.5.3
#> [22] knitr_1.40 sass_0.4.2