How to fill redis with redis-cli with dummy data of size weigh hundreds of MB? - performance

I am getting my hand dirty with redis monitoring. So far I came up with this metrics useful to monitor about redis:
memory_used
through put
latency
connections
replication
I am newbie on this. I am trying to fill the redis from redis-cli with dummy data as:
for i in `seq 10000000`; do redis-cli SET users:app "{id: '$i', name: 'name$i', address: 'address$i' }" ; done
but it doesn't scale my need to fillup the redis-db fast enough...
Also I need some help regarding the latency and throught put monitoring. I know what they mean, but I don't know how to measure them... My eyes don't see anything rellated to that on output for redis-cli info
Thanks, for support/guidence :D

Use the undocumented DEBUG POPULATE command.
DEBUG POPULATE count [prefix] [size]: Create count string keys named key:<num>. If a prefix is specified it's used instead of the key prefix.
The value starts with value:<num> and is filled with null chars if needed until it achieves the given size if specified.
> DEBUG POPULATE 5 test 1000000
OK
> KEYS *
1) "test:3"
2) "test:1"
3) "test:4"
4) "test:2"
5) "test:0"
> STRLEN test:0
(integer) 1000000
> STRLEN test:4
(integer) 1000000
> GETRANGE test:1 0 10
"value:1\x00\x00\x00\x00"

To "fill fast", follow the instructions in the documentation about Mass Insert - the gist is using the --pipe directive on a pre-prepared data file.

following #leomurillo
I got this to work without the last parameter, and I couldn't find the documentation for this undocumented command :)
127.0.0.1:6379> DEBUG POPULATE 10000000 PHPREDIS_SESSION
OK
(15.61s)
127.0.0.1:6379> dbsize
(integer) 10000334

Using Python
redis-dummy-data-generator.py, Creates 10000 key-value pairs
#!/usr/bin/python
for i in range(10000):
print 'set name'+str(i),'helloworld'
Run generator script and store the output in redis_commands.txt file
python redis-dummy-data-generator.py > redis_commands.txt
Load generated dummy data into redis-server
redis-cli -a mypassword -h localhost -p 6379 < redis_commands.txt

Related

On loading a file in redis, a new line is being inserted in value, how to avoid this

I am trying to upload a file in redis using command:
redis-cli -p <Port> -h <Host> -n <DB> -x set <key> < /tmp/file.json
The problem is : in redis value -
It is storing a \n at the end of line and I don't want this.
"{\"items\":{\"38749\":{\"buyone\":0,\"buytwo\":10},\"38712\":{\"buyone\":0,\"buytwo\":10},\"112775\":{\"buyone\":0,\"buytwo\":10},\"38721\":{\"buyone\":0,\"buytwo\":10},\"38720\":{\"buyone\":0,\"buytwo\":10},\"38714\":{\"buyone\":0,\"buytwo\":10},\"38726\":{\"buyone\":0,\"buytwo\":10},\"38733\":{\"buyone\":0,\"buytwo\":10},\"38729\":{\"buyone\":0,\"buytwo\":10},\"113708\":{\"buyone\":0,\"buytwo\":10},\"38731\":{\"buyone\":0,\"buytwo\":10},\"38745\":{\"buyone\":0,\"buytwo\":10},\"38732\":{\"buyone\":0,\"buytwo\":10},\"100074\":{\"buyone\":0,\"buytwo\":10},\"38730\":{\"buyone\":0,\"buytwo\":10},\"38719\":{\"buyone\":0,\"buytwo\":10},\"38723\":{\"buyone\":0,\"buytwo\":10},\"38755\":{\"buyone\":0,\"buytwo\":10},\"38760\":{\"buyone\":0,\"buytwo\":10}}}\n"
Since your file contains newlines, that's what gets stored in Redis.
You'll need to strip the newlines from your file before setting its contents to Redis. Depending on your OS, the method may vary. Here's a question about this: How do I remove newlines from a text file?
Finally got this working -
cat /tmp/up.json | redis-cli -n 20 --pipe
and up.json contents
set 'PACKAGES_CONFIG' '{"checkOfferFieldPrices":true,"showPrescInfoScreen":true,"showAddOnsScreen":true,"offerText":"1 + 1 with Lenskart Gold","bannerConfig":{"isVisible":true,"primaryText":"Hi %s, You are a GOLD Member!","secondaryText":"You are eligible for Buy 1 Get 1 offer on this order!"},"isExpandedByDefault":true,"isPreSelected":true,"displayBogoTabs": true, "defaultSelectedTabId": "buy2","tabConfig":[{"id":"buy1","title":"Buy 1","subtitle":"No Offer","enabled":true},{"id":"buy2","title":"Buy 2","subtitle":"Buy 1 Get 1 Free","enabled":true}]}'

bash asynchronous variable setting (dns lookup)

Let's say we had a loop that we want to have run as quickly as possible. Let's say something was being done to a list of hosts inside that loop; just for the sake of argument, let's say it was a redis query. Let's say that the list of hosts may change occasionally due to hosts being added/removed from a pool (not load balanced); however, the list is predictable (e.g., they all start with “foo” and end with 2 digits. So we want to run this occasionally; say, once every 15 minutes:
listOfHosts=$(dig +noall +ans foo{00..99}.domain | while read -r n rest; do printf '%s\n' ${n%.}; done)
to get the list of hosts. Let's say our loop looked something like this:
while :; do
for i in $listOfHosts; do
redis-cli -h $i llen something
done
(( ( $(date +%s) % 60 * 15) == 0 )) && callFunctionThatSetslistOfHosts
done
(now obviously there's some things missing, like testing to see if we've already run callFunctionThatSetslistOfHosts in the current minute and only running it once, and doing something with the redis output, and maybe the list of hosts should be an array, but basically this is it.)
How can we run callFunctionThatSetslistOfHosts asynchronously so that it doesn't slow down the loop. I.e., have it running in the background setting listOfHosts occasionally (e.g. once every 15 minutes), so that the next time the inner loop is run it gets a potentially different set of hosts to run the redis query on?
My major problem seems to be that in order to set listOfHosts in a loop, that loop has to be a subshell, and listOfHosts is local to that subshell, and setting it doesn't affect the global listOfHosts.
I may resort to pipes, but will have to poll the reader before generating a new list — not that that's terribly bad if I poll slowly, but I thought I'd present this as a problem.
Thanks.

How to resume reading a file?

I'm trying to find the best and most efficient way to resume reading a file from a given point.
The given file is being written frequently (this is a log file).
This file is rotated on a daily basis.
In the log file I'm looking for a pattern 'slow transaction'. End of such lines have a number into parentheses. I want to have the sum of the numbers.
Example of log line:
Jun 24 2015 10:00:00 slow transaction (5)
Jun 24 2015 10:00:06 slow transaction (1)
This is easy part that I could do with awk command to get total of 6 with above example.
Now my challenge is that I want to get the values from this file on a regular basis. I've an external system that polls a custom OID using SNMP. When hitting this OID the Linux host runs a couple of basic commands.
I want this SNMP polling event to get the number of events since the last polling only. I don't want to have the total every time, just the total of the newly added lines.
Just to mention that only bash can be used, or basic commands such as awk sed tail etc. No perl or advanced programming language.
I hope my description will be clear enough. Apologizes if this is duplicate. I did some researches before posting but did not find something that precisely correspond to my need.
Thank you for any assistance
In addition to the methods in the comment link, you can also simply use dd and stat to read the logfile size, save it and sleep 300 then check the logfile size again. If the filesize has changed, then skip over the old information with dd and read the new information only.
Note: you can add a test to handle the case where the logfile is deleted and then restarted with 0 size (e.g. if $((newsize < size)) then read all.
Here is a short example with 5 minute intervals:
#!/bin/bash
lfn=${1:-/path/to/logfile}
size=$(stat -c "%s" "$lfn") ## save original log size
while :; do
newsize=$(stat -c "%s" "$lfn") ## get new log size
if ((size != newsize)); then ## if change, use new info
## use dd to skip over existing text to new text
newtext=$(dd if="$lfn" bs="$size" skip=1 2>/dev/null)
## process newtext however you need
printf "\nnewtext:\n\n%s\n" "$newtext"
size=$((newsize)); ## update size to newsize
fi
sleep 300
done

Is it possible to count the number of partitions?

I am working on a test in which I must find out the number of partitions of a table and check if it is right. If I use show partitions TableName I get all the partitions by name, but I wish to get the number of partitions, like something along the lines show count(partitions) TableName (which retuns OK btw.. so it's not good) and get 12 (for ex.).
Is there any way to achieve this??
Using Hive CLI
$ hive --silent -e "show partitions <dbName>.<tableName>;" | wc -l
--silent is to enable silent mode
-e tells hive to execute quoted query string
You could use:
select count(distinct <partition key>) from <TableName>;
By using the below command, you will get the all partitions and also at the end it shows the number of fetched rows. That number of rows means number of partitions
SHOW PARTITIONS [db_name.]table_name [PARTITION(partition_spec)];
< failed pictoral example >
You can use the WebHCat interface to get information like this. This has the benefit that you can run the command from anywhere that the server is accessible. The result is JSON - use a JSON parser of your choice to process the results.
In this example of piping the WebHCat results to Python, only the number 24 is returned representing the number of partitions for this table. (Server name is the name node).
curl -s 'http://*myservername*:50111/templeton/v1/ddl/database/*mydatabasename*/table/*mytablename*/partition?user.name=*myusername*' | python -c 'import sys, json; print len(json.load(sys.stdin)["partitions"])'
24
In scala you can do following:
sql("show partitions <table_name>").count()
I used following.
beeline -silent --showHeader=false --outputformat=csv2 -e 'show partitions <dbname>.<tablename>' | wc -l
Use the following syntax:
show create table <table name>;

fastest hashing in a unix environment?

I need to examine the output of a certain script 1000s of times on a unix platform and check if any of it has changed from before.
I've been doing this:
(script_stuff) | md5sum
and storing this value. I actually don't really need "md5", JUST a simple hash function which I can compare against a stored value to see if its changed. Its okay if there are an occassional false positive.
Is there anything better than md5sum that works faster and generates a fairly usable hash value? The script itself generates a few lines of text - maybe 10-20 on average to max 100 or so.
I had a look at fast md5sum on millions of strings in bash/ubuntu - that's wonderful, but I can't compile a new program. Need a system utility... :(
Additional "background" details:
I've been asked to monitor the DNS record of a set of 1000 or so domains and immediately call certain other scripts if there has been any change. I intend to do a dig xyz +short statement and hash its output and store that, and then check it against a previously stored value. Any change will trigger the other script, otherwise it just goes on. Right now, we're planning on using cron for a set of these 1000, but can think completely diffeerently for "seriously heavy" usage - ~20,000 or so.
I have no idea what the use of such a system would be, I'm just doing this as a job for someone else...
The cksum utility calculates a non-cryptographic CRC checksum.
How big is the output you're checking? A hundred lines max. I'd just save the entire original file then use cmp to see if it's changed. Given that a hash calculation will have to read every byte anyway, the only way you'll get an advantage from a checksum type calculation is if the cost of doing it is less than reading two files of that size.
And cmp won't give you any false positives or negatives :-)
pax> echo hello >qq1.txt
pax> echo goodbye >qq2.txt
pax> cp qq1.txt qq3.txt
pax> cmp qq1.txt qq2.txt >/dev/null
pax> echo $?
1
pax> cmp qq1.txt qq3.txt >/dev/null
pax> echo $?
0
Based on your question update:
I've been asked to monitor the DNS record of a set of 1000 or so domains and immediately call certain other scripts if there has been any change. I intend to do a dig xyz +short statement and hash its output and store that, and then check it against a previously stored value. Any change will trigger the other script, otherwise it just goes on. Right now, we're planning on using cron for a set of these 1000, but can think completely diffeerently for "seriously heavy" usage - ~20,000 or so.
I'm not sure you need to worry too much about the file I/O. The following script executed dig microsoft.com +short 5000 times first with file I/O then with output to /dev/null (by changing the comments).
#!/bin/bash
rm -rf qqtemp
mkdir qqtemp
((i = 0))
while [[ $i -ne 5000 ]] ; do
#dig microsoft.com +short >qqtemp/microsoft.com.$i
dig microsoft.com +short >/dev/null
((i = i + 1))
done
The elapsed times at 5 runs each are:
File I/O | /dev/null
----------+-----------
3:09 | 1:52
2:54 | 2:33
2:43 | 3:04
2:49 | 2:38
2:33 | 3:08
After removing the outliers and averaging, the results are 2:49 for the file I/O and 2:45 for the /dev/null. The time difference is four seconds for 5000 iterations, only 1/1250th of a second per item.
However, since an iteration over the 5000 takes up to three minutes, that's how long it will take maximum to detect a problem (a minute and a half on average). If that's not acceptable, you need to move away from bash to another tool.
Given that a single dig only takes about 0.012 seconds, you should theoretically do 5000 in sixty seconds assuming your checking tool takes no time at all. You may be better off doing something like this in Perl and using an associative array to store the output from dig.
Perl's semi-compiled nature means that it will probably run substantially faster than a bash script and Perl's fancy stuff will make the job a lot easier. However, you're unlikely to get that 60-second time much lower just because that's how long it takes to run the dig commands.

Resources