Optimizing Disk I/O when running Redis and PostgreSQL on a single machine - redis

Background:
I have a live Django app that utilizes 4 Redis instances.
The first two are big in size: back ups amount to ~2GB and ~4.4GB respectively. The other two are small: ~85M and ~15M.
redis-server --version yields Redis server v=4.0.2 sha=00000000:0 malloc=jemalloc-4.0.3 bits=64 build=401ce53d7b0383ca.
The problem:
It's a busy server running PostgreSQL 9.6.5 as well. PG data and Redis backups are both saved in the secondary drive xvdb.
I've noticed that whenever my big Redis instances start backing up, disk I/O naturally spikes and PostgreSQL commit statements start piling up in the slow log. Behold:
21:49:26.171 UTC [44861] ubuntu#myapp LOG: duration: 3063.262 ms statement: COMMIT
21:49:26.171 UTC [44890] ubuntu#myapp LOG: duration: 748.307 ms statement: COMMIT
21:49:26.171 UTC [44882] ubuntu#myapp LOG: duration: 1497.461 ms statement: COMMIT
21:49:26.171 UTC [44893] ubuntu#myapp LOG: duration: 655.063 ms statement: COMMIT
21:49:26.171 UTC [44894] ubuntu#myapp LOG: duration: 559.743 ms statement: COMMIT
21:49:26.172 UTC [44883] ubuntu#myapp LOG: duration: 1415.733 ms statement: COMMIT
As a consequence, this is how my PostgreSQL commits look like every day:
The question:
Is there anything I can do on the Redis side to help smoothe out this spikey situation? I'd like Redis and PostgreSQL to live in as much harmony as they possibly can on a single machine.
More information:
Ask for more information if you need it.
Machine specs:
AWS EC2 m4.4xlarge (16 cores, 64GB RAM)
Elastic Block Store gp2 volumes (105 IOPS, burst upto 3000 IOPS)
The following config exists in the Append Only Mode section of my Redis conf files:
appendonly no
appendfilename "appendonly.aof"
# appendfsync always
appendfsync everysec
# appendfsync no
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble no
Typical iostat -xmt 3 values are:
10/15/2017 08:28:35 PM
avg-cpu: %user %nice %system %iowait %steal %idle
10.44 0.00 0.93 0.15 0.06 88.43
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
xvda 0.00 0.00 0.00 2.00 0.00 0.04 38.67 0.00 0.00 0.00 0.00 0.00 0.00
xvdb 0.00 2.67 0.00 44.67 0.00 0.41 18.99 0.13 2.81 0.00 2.81 1.07 4.80
Compare that to the same around the time slow commits are logged:
10/15/2017 10:18:11 PM
avg-cpu: %user %nice %system %iowait %steal %idle
8.16 0.00 0.65 11.90 0.04 79.24
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
xvda 0.00 4.00 0.00 1.00 0.00 0.02 48.00 0.00 1.33 0.00 1.33 1.33 0.13
xvdb 0.00 0.00 1.67 1312.00 0.01 163.50 254.90 142.56 107.64 25.60 107.75 0.76 100.00
The first Redis instance has the following snapshotting config:
save 7200 1
#save 300 10
#save 60 10000
The second Redis instance has the following snapshotting config:
save 21600 10
#save 300 10
#save 60 10000

I can suggest one solution - docker. docker has the capability to limit the os resources that a particular container will use. In your case, the os resource seems to be the disk i/o.
The --device-read-bps flag limits the read rate (bytes per second)
from a device. For example, this command creates a container and
limits the read rate to 1mb per second from /dev/sda:
$ docker run -it --device-read-bps /dev/sda:1mb
docker also has a flag --device-read-iops=[] which limit read rate (IO per second) from a device.
Your image here will be redis, but it won't hurt to move postgres also to docker. This will help you limit the disk i/o rates on redis containers so that postgres has more of it.
This solution should work for you but the infrastructure changes might be a little painful to achieve.
You can refer this SO post for docker limit i/o speed

Related

WSL2 io speeds on Linux filesystem are slow

Trying out WSL2 for the first time. Running Ubuntu 18.04 on a Dell Latitude 9510 with an SSD. Noticed build speeds of a React project were brutally slow. Per all the articles on the web I'm running the project out of ~ and not the windows mount. Ran a benchmark using sysbench --test=fileio --file-test-mode=seqwr run in ~ and got:
File operations:
reads/s: 0.00
writes/s: 3009.34
fsyncs/s: 3841.15
Throughput:
read, MiB/s: 0.00
written, MiB/s: 47.02
General statistics:
total time: 10.0002s
total number of events: 68520
Latency (ms):
min: 0.01
avg: 0.14
max: 22.55
95th percentile: 0.31
sum: 9927.40
Threads fairness:
events (avg/stddev): 68520.0000/0.00
execution time (avg/stddev): 9.9274/0.00
If I'm reading this correctly, that wrote 47 mb/s. Ran the same test on my mac mini and got 942 mb/s. Is this normal? This seems like the Linux i/o speeds on WSL are unusably slow. Any thoughts on ways to speed this up?
---edit---
Not sure if this is a fair comparison, but the output of winsat disk -drive c on the same machine from the Windows side. Smoking fast:
> Dshow Video Encode Time 0.00000 s
> Dshow Video Decode Time 0.00000 s
> Media Foundation Decode Time 0.00000 s
> Disk Random 16.0 Read 719.55 MB/s 8.5
> Disk Sequential 64.0 Read 1940.39 MB/s 9.0
> Disk Sequential 64.0 Write 1239.84 MB/s 8.6
> Average Read Time with Sequential Writes 0.077 ms 8.8
> Latency: 95th Percentile 0.219 ms 8.9
> Latency: Maximum 2.561 ms 8.7
> Average Read Time with Random Writes 0.080 ms 8.9
> Total Run Time 00:00:07.55
---edit 2---
Windows version: Windows 10 Pro, Version 20H2 Build 19042
Late answer, but I had the same issue and wanted to post my solution for anyone who has the problem:
Windows Defender seems to destroy the read speeds in WSL. I added the entire rootfs folder as an exclusion. If you're comfortable turning off Windows Defender, I recommend that as well. Any antivirus probably has similar issues, so adding the WSL directories as an exclusion is probably you best bet.

iperf2 latency is a two way or one way latency

iperf2 (version 2.0.9) reports latency in its output as shown below.
Is it a two-way latency or one-way latency measurement ?
Server listening on UDP port 5001 with pid 5167
Receiving 1470 byte datagrams
UDP buffer size: 208 KByte (default)
[ 3] local 192.168.1.102 port 5001 connected with 192.168.1.101 port 59592
[ ID] Interval Transfer Bandwidth Jitter Lost/Total Latency avg/min/max/stdev PPS
[ 3] 0.00-1.00 sec 122 KBytes 1.00 Mbits/sec 0.063 ms 0/ 6254 (0%) 659.932/659.882/660.502/ 8.345 ms 6252 pps
[ 3] 1.00-2.00 sec 122 KBytes 1.00 Mbits/sec 0.020 ms 0/ 6250 (0%) 660.080/659.919/666.878/ 0.110 ms 6250 pps
[ 3] 2.00-3.00 sec 122 KBytes 1.00 Mbits/sec 0.020 ms 0/ 6250 (0%) 660.113/659.955/660.672/ 0.047 ms 6250 pps
[ 3] 3.00-4.00 sec 122 KBytes 1.00 Mbits/sec 0.022 ms 0/ 6250 (0%) 660.153/659.994/660.693/ 0.047 ms 6250 pps
[ 3] 4.00-5.00 sec 122 KBytes 1.00 Mbits/sec 0.021 ms 0/ 6250 (0%) 660.192/660.034/660.617/ 0.049 ms 6250 pps
It's one-way which requires the clocks to be synchronized to a common reference. You may want to check in to Precision Time Protocol. Also, tell your hosting provider that you want better clocks in their data centers. The GPS atomic clock is quite accurate and the signal is free.
There is a lot more work going on with iperf 2.0.14 related to TCP write to read latencies. Version 2.0.14 will enforce the use of --trip-times on the client before any end/end or one way latency measurements are presented. This way the user tells iperf that the systems have their clocks synchronized to the accuracy which the user deems as sufficient. We also produce a Little's law inP metric along with network power. See the man pages for more. The hope is to have iperf 2.0.14 released by early 2021.
[rjmcmahon#localhost iperf2-code]$ src/iperf -s -i 1
[ 4] local 192.168.1.10%enp2s0 port 5001 connected with 192.168.1.80 port 47420 (trip-times) (MSS=1448) (peer 2.0.14-alpha)
[ ID] Interval Transfer Bandwidth Reads Dist(bin=16.0K) Burst Latency avg/min/max/stdev (cnt/size) inP NetPwr
[ 4] 0.00-1.00 sec 1.09 GBytes 9.34 Gbits/sec 18733 2469:2552:2753:2456:2230:2272:1859:2142 2.988/ 0.971/ 3.668/ 0.370 ms (8908/131072) 3.34 MByte 390759.84
Note: For my testing during iperf 2 development, I have GPS disciplined oven controlled oscillators from spectracom in my systems. These cost about $2.5K each and require a GPS signal.

thinking sphinx partially rebuilding index?

After running a script to populate my database i ran a rake ts:rebuild but sphinx is partially rebuilding the indexes.
Stopped searchd daemon (pid: 23309).
Generating configuration to /home/guest_dp/config/development.sphinx.conf
Sphinx 2.1.4-id64-release (rel21-r4421)
Copyright (c) 2001-2013, Andrew Aksyonoff
Copyright (c) 2008-2013, Sphinx Technologies Inc (http://sphinxsearch.com)
using config file '/home/guest_dp/config/development.sphinx.conf'...
indexing index 'episode_core'...
collected 4469 docs, 0.0 MB
sorted 0.0 Mhits, 100.0% done
total 4469 docs, 8938 bytes
total 0.071 sec, 124488 bytes/sec, 62244.07 docs/sec
indexing index 'episode_delta'...
collected 0 docs, 0.0 MB
total 0 docs, 0 bytes
total 0.013 sec, 0 bytes/sec, 0.00 docs/sec
indexing index 'organization_core'...
.
.
.
skipping non-plain index 'episode'...
skipping non-plain index 'organization'...
skipping non-plain index 'person'...
skipping non-plain index 'position'...
skipping non-plain index 'profession'...
skipping non-plain index 'segment'...
skipping non-plain index 'tv_show'...
total 12816 reads, 0.005 sec, 0.2 kb/call avg, 0.0 msec/call avg
total 116 writes, 0.020 sec, 52.3 kb/call avg, 0.1 msec/call avg
Started searchd successfully (pid: 23571).
What does it mean skipping non-plain index ?
Each of those are distributed indices, which contain the _core and _delta plain indices (e.g. episode contains both episode_core and episode_delta). There's nothing to do to index them directly, because distributed indices don't contain data, they just point to other indices.
In other words: what you're seeing is completely normal. All of your indices are being processed appropriately.
Sphinx used to have a slightly different message: Distributed index 'episode' can not be directly indexed; skipping - same deal.

What is the performance overhead of XADisk for read and write operations?

What does XADisk do in addition to reading/writing from the underlying file? How does that translate into a percentage of the read/write throughput (approximately)?
depends on the size, if large set the flag "heavyWrite" as true while opening the xaFileOutputStream.
test with 500 files of size 1MB each. Below is the amount of time taken, averaged over 10 executions...
Java IO - 37.5 seconds
Java NIO - 24.8 seconds
XADisk - 30.3 seconds

ThinkingSphinx returns no results when in test mode in Cucumber

I'm on a project upgrading from Rails 2 -> 3. We are removing Ultrasphinx (which is not supported in Rails 3) and replacing it with ThinkingSphinx. One problem - the Cucumber tests for searching, which used to work, are failing as ThinkingSphinx is not indexing the files in test mode.
This is the relevant part of env.rb:
require 'cucumber/thinking_sphinx/external_world'
Cucumber::ThinkingSphinx::ExternalWorld.new
Cucumber::Rails::World.use_transactional_fixtures = false
And here is the step (declared in my common_steps.rb file) that indexes my objects:
Given /^ThinkingSphinx is indexed$/ do
puts "Indexing the new database objects"
# Update all indexes
ThinkingSphinx::Test.index
sleep(0.25) # Wait for Sphinx to catch up
end
And this is what I have in my .feature file (after the model objects are created)
And ThinkingSphinx is indexed
This is the output of ThinkingSphinx when its run in test mode (this is WRONG, it should be finding documents but it is not)
Sphinx 0.9.9-release (r2117)
Copyright (c) 2001-2009, Andrew Aksyonoff
using config file 'C:/Users/PaulG/Programming/Projects/TechTV/config/test.sphinx.conf'...
indexing index 'collection_core'...
collected 0 docs, 0.0 MB
total 0 docs, 0 bytes
total 0.027 sec, 0 bytes/sec, 0.00 docs/sec
distributed index 'collection' can not be directly indexed; skipping.
indexing index 'video_core'...
collected 0 docs, 0.0 MB
total 0 docs, 0 bytes
total 0.018 sec, 0 bytes/sec, 0.00 docs/sec
distributed index 'video' can not be directly indexed; skipping.
total 0 reads, 0.000 sec, 0.0 kb/call avg, 0.0 msec/call avg
total 8 writes, 0.000 sec, 0.1 kb/call avg, 0.0 msec/call avg
rotating indices: succesfully sent SIGHUP to searchd (pid=4332).
In comparison, this is the output I get when I run
rake ts:index
To index the development environment:
Sphinx 0.9.9-release (r2117)
Copyright (c) 2001-2009, Andrew Aksyonoff
using config file 'C:/Users/PaulG/Programming/Projects/TechTV/config/development.sphinx.conf'...
indexing index 'collection_core'...
collected 4 docs, 0.0 MB
sorted 0.0 Mhits, 100.0% done
total 4 docs, 39 bytes
total 0.031 sec, 1238 bytes/sec, 127.04 docs/sec
distributed index 'collection' can not be directly indexed; skipping.
indexing index 'video_core'...
collected 4 docs, 0.0 MB
sorted 0.0 Mhits, 100.0% done
total 4 docs, 62 bytes
total 0.023 sec, 2614 bytes/sec, 168.66 docs/sec
distributed index 'video' can not be directly indexed; skipping.
total 10 reads, 0.000 sec, 0.0 kb/call avg, 0.0 msec/call avg
total 20 writes, 0.001 sec, 0.1 kb/call avg, 0.0 msec/call avg
rotating indices: succesfully sent SIGHUP to searchd (pid=5476).
Notice how its actually finding documents in my development database, but not my test database. The indexer is working in dev, but not test? I've spent 2 days on this, and am no closer to a solution. Any help would be overwhelmingly appreciated.
I figured it out this morning, hopefully I can save someone else the troubles I experienced. Looks like it wasn't a fault of Cucumber, but of DatabaseCleaner.
I fixed this issue by changing this line in env.rb:
DatabaseCleaner.strategy = :transaction
to
DatabaseCleaner.strategy = :truncation