From e6b412f646d63f5cc2177f0f103c7fa2f0fcedd4 Mon Sep 17 00:00:00 2001 From: Sunny Gleason Date: Fri, 22 Feb 2019 14:03:49 -0500 Subject: [PATCH] feat: add redis Unix Domain Socket support for high performance (#26) * feat: add redis Unix Domain Socket support for high performance * feat: add redis unix domain socket support for api.js * wording enhancements --- README.md | 91 +++++++++++++++++++++++++++++++++++++++++++ api/api.js | 6 ++- api/config.js | 1 + api/inbound-stream.js | 9 +++-- 4 files changed, 102 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index cb1f28e9..d7544bfd 100644 --- a/README.md +++ b/README.md @@ -67,3 +67,94 @@ and if desired for UI testing: ```bash $ ./multinode-demo/client.sh --tx_count 40 --threads 2 -z 400 ``` + +## High Performance Use Cases + +### Redis via Unix Domain Socket + +Redis is known as a very fast in-memory data structure server. To keep up with Solana +speeds, it may be useful to enable Unix Domain Socket communication for added performance +(potentially 10-40% or more depending on the operations). + +Add configuration similar to the following to your `/etc/redis/redis.conf` (or equivalent): +``` +unixsocket /var/run/redis/redis-server.sock +unixsocketperm 770 +``` + +Increasing max socket connections on Linux may also prove useful: +```bash +sudo sysctl net.core.somaxconn=16384 +``` + +Remember to restart `redis-server` to pick up the new configuration: +```bash +sudo service redis-server restart +``` + +Ensure that your API unix user is in the same group as your `redis` user so it can read +the file. For example, you may need to do something like this: +```bash +sudo chgrp -R ubuntu /var/run/redis +``` + +Finally, update the redis section of `api/config.js` to enable the `path` configuration +which takes precedence over the host/port options: +```js + ... + redis: { + ... + path: '/var/run/redis/redis-server.sock', + }, + ... +``` + +If you would like to test Redis performance, the `redis-benchmark` tool is very handy +for quick sanity checks while tuning configuration. + +Results using localhost TCP socket: +```bash +$ redis-benchmark -q -n 2000000 -c 1000 -P 40 +PING_INLINE: 567215.00 requests per second +PING_BULK: 1021450.50 requests per second +SET: 587026.69 requests per second +GET: 741839.75 requests per second +INCR: 619195.06 requests per second +LPUSH: 671366.19 requests per second +RPUSH: 810701.25 requests per second +LPOP: 473372.78 requests per second +RPOP: 769230.81 requests per second +SADD: 925925.88 requests per second +HSET: 693721.81 requests per second +SPOP: 914494.75 requests per second +LPUSH (needed to benchmark LRANGE): 547495.19 requests per second +LRANGE_100 (first 100 elements): 34660.24 requests per second +LRANGE_300 (first 300 elements): 9543.71 requests per second +LRANGE_500 (first 450 elements): 6180.72 requests per second +LRANGE_600 (first 600 elements): 4716.88 requests per second +MSET (10 keys): 123137.54 requests per second +``` + +Results using Unix Domain Socket: +```bash +$ redis-benchmark -q -n 2000000 -c 1000 -P 40 -s /var/run/redis/redis-server.sock +PING_INLINE: 1038421.62 requests per second +PING_BULK: 1673640.12 requests per second +SET: 896459.00 requests per second +GET: 1175779.00 requests per second +INCR: 1107419.75 requests per second +LPUSH: 814995.94 requests per second +RPUSH: 768049.12 requests per second +LPOP: 775494.38 requests per second +RPOP: 884564.38 requests per second +SADD: 1047120.44 requests per second +HSET: 758437.62 requests per second +SPOP: 1275510.25 requests per second +LPUSH (needed to benchmark LRANGE): 810372.81 requests per second +LRANGE_100 (first 100 elements): 58491.50 requests per second +LRANGE_300 (first 300 elements): 12462.15 requests per second +LRANGE_500 (first 450 elements): 7449.32 requests per second +LRANGE_600 (first 600 elements): 4019.78 requests per second +MSET (10 keys): 120279.05 requests per second +``` + diff --git a/api/api.js b/api/api.js index 7f7a1d27..c3c06136 100644 --- a/api/api.js +++ b/api/api.js @@ -20,7 +20,11 @@ const port = 3001; const MINUTE_MS = 60 * 1000; function getClient() { - return redis.createClient(config.redis); + let props = config.redis.path + ? {path: config.redis.path} + : {host: config.redis.host, port: config.redis.port}; + + return redis.createClient(props); } expressWs(app); diff --git a/api/config.js b/api/config.js index fe451536..cf05b1f2 100644 --- a/api/config.js +++ b/api/config.js @@ -10,5 +10,6 @@ export default { redis: { host: '127.0.0.1', port: 6379, + // path: '/var/run/redis/redis-server.sock', }, }; diff --git a/api/inbound-stream.js b/api/inbound-stream.js index d100a91f..9d769e21 100644 --- a/api/inbound-stream.js +++ b/api/inbound-stream.js @@ -78,10 +78,11 @@ class BridgeFn { class RedisHandler { constructor(props) { - this.innerClient = redis.createClient({ - host: props.host, - port: props.port, - }); + const config = props.path + ? {path: props.path} + : {host: props.host, port: props.port}; + + this.innerClient = redis.createClient(config); this.process = this.process.bind(this); }