go/golang + redis too many open files error - redis

I'm using redis in Golang with the Redigo connector (https://github.com/garyburd/redigo) suggested by the Redis website.
I have:
After every Dial() I defer a Close()
Set fs.file-max = 100000
Set vm.overcommit_memory = 1
Disabled saving
Set maxclients = 100000
I run a high traffic website, and everything runs great for about 10 minutes, from which I get
error: dial tcp 127.0.0.1:6379: too many open files
Then I can't access redis at all from my application.
I see nothing in the redis logs to suggest any errors or problems. What do I do to fix this?

I don't know which driver you use but with redigo you can define a number of open connections in a pool, all you have to do then is in every query to redis, first get a client from the pool, then close it, so it goes back to the pool and gets re-used, just like this:
redisPool = &redis.Pool{
MaxIdle: 3,
MaxActive: 10, // max number of connections
Dial: func() (redis.Conn, error) {
c, err := redis.Dial("tcp", ":6379")
if err != nil {
panic(err.Error())
}
return c, err
},
}
r := redisPool.Get() // get a client from the pool
_, err = r.Do("GET one") // use the client
if err != nil {
panic(err.Error())
}
r.Close() // close the client so the connection gets reused

Your problem is that Redis cant open new connections and then becomes unresponsive, you need to increase the file descriptors limit of your operating system (ubuntu defaults to 1024 which can be a problem) which right now is dominating the redis maxclients setting.
The way you tweak this limit depends on the os redis is running, on linux you need something like this:
ulimit -n 99999

Related

ERR unknown command '--cluster' when rebalancing slots

I have created a RedisClient using go-redis
rdClient := rd.NewClusterClient(rdClusterOpts)
I can do other database operation using the client
out,err := rdClient.Ping(context.TODO()).Result()
PONG
I can also do get set operation using the client.
When I try to rebalance the slots, it shows an error.
out, err := rdClient.Do(context.TODO(), "--cluster", "rebalance", "10.244.0.98", "--cluster-use-empty-masters").Result()
It shows the Error
ERR unknown command '--cluster', with args beginning with: 'rebalance' '10.244.0.96:6379' '--cluster-use-empty-masters
Is there any way to perform the Redis Cluster Manager commands using go-redis or any other go redis client ?

Set minimum idle connections in SQL pool

Background: I want to reduce the response time when working with SQL databases in my Go applications.
Golang provides an SQL package with a connection pool.
It includes the following configuration options:
func (db *DB) SetConnMaxIdleTime(d time.Duration)
func (db *DB) SetConnMaxLifetime(d time.Duration)
func (db *DB) SetMaxIdleConns(n int)
func (db *DB) SetMaxOpenConns(n int)
However, there is nothing like SetMinIdleConns to ensure that there are always some open connections that can be used when a request comes in.
As a result, my application has good response times under load, but the first request after some idle time always has some delay because it needs to open a new connection to the database.
Question: Is there a way to fix this with the Go standard library or is there some alternative connection pooling library for Go with this feature?
Workarounds and already tried:
I tried setting ConnMaxIdleTime and ConnMaxLifetime to very high values, but then the SQL server closes them and I get even higher delays or even errors on the first call after a long idle time.
Obviously, I could create a background task that periodically uses the database. However, this does not seem like a clean solution.
I am considering porting a connection pool library from another language to Go.
The pgx/pgxpool library provides a connection pool for Postgres, which allows to configure the minimum number of connections:
connConf, err := pgxpool.ParseConfig(connStr)
// ... (error handling)
connConf.MaxConns = 50
// Set minimum number of connections:
connConf.MinConns = 10
pool, err := pgxpool.ConnectConfig(context.TODO(), connConf)

lua setting an expiration time using the redis command with 'setex' appears as a permanent key in openresty

setting an expiration time using the redis command appears as a permanent key when i do this in openresty with lua script.
the lua script is follow this:
local function ip_frequency(ip,red)
local limit_num=50
local key = "limit:frequency:"..ip
local resp, err = red:get(key)
if resp==nil then
local ok,err=red:setex(key,2,1)
if not ok then
return false;
end
end
if type(resp) == "string" then
if tonumber(resp) > limit_num then
return false
end
end
ok, err = red:incr(key)
if not ok then
return false
end
return true
end
When the openresty program has run for some time,some permanent keys appear in redis.From this function it can be seen that I did not set a key for the permanent time,but it just happens. Why is that,please help me answer this question. Thank you!
The software version is as follows:
openresty: 1.17.8.2
redis: 6.0+
centos: 8.0+
Openresty connects to redis database and uses it's functionality. Such usage of redis functions in lua or other language is not atomic. For redis server it means: [redis:get, pause, redis:setex] or [redis:get, pause, redis:incr]. During pause period can happen a lot of things, event if there is only 1ms, such as cleanup of 'dead' keys.
And this what could happen with your code:
local resp, err = red:get(key)
You get valid key value which is smaller than limit_num
ok, err = red:incr(key)
Redis checks if key is valid, and removes it if reaches ttl
Redis checks that there is no such key, so creates key with value=0 and increments key value
So at this point you have permanent key. If you want to avoid permanent keys, use something like: red:setex(key,2,tonumber(res)+1) istead of red:incr(key)

Aerospike - command execution timed out on client

Using the following code to load data in Aerospike. data is a list of maps of type BinMap
for _, binMap := range data {
id, ok := binMap["id"].(string)
key, _ := as.NewKey("test", "myset", id)
err := shared.Client.Put(nil, key, binMap)
if err !=nil {
fmt.Println(err)
}
After loading few records, the following error message is received.
command execution timed out on client: Exceeded number of retries.
See `Policy.MaxRetries`. (last error: Node not found for partition
test:711 in partition table.)
For each iteration, the partition test number changes.
The error continues even after waiting for 5 seconds after each Put command. I am not sure what timeout is reported in the error message.What client configuration is required for go client?
Using MacOs 10.15.3; go client; Aerospike running on docker 2.2.0.3
There's a good chance your cluster hasn't formed correctly, or that its networking isn't properly set up to give clients access to all the nodes. Since you're using Docker, take a look at Lucien's Medium post How do I get a 2 nodes Aerospike cluster running quickly in Docker without editing a single file?.

IBM VM Creation via Softlayer API takes longer time

I followed the example given in the below link to create a new IBM-cloud VM.
https://www.ibm.com/developerworks/cloud/library/cl-softlayer-go-overview/index.html
func main() {
sess := session.New()
service := services.GetVirtualGuestService(sess)
guestTpl := datatypes.Virtual_Guest{
Hostname: sl.String("sample"),
Domain: sl.String("example.com"),
MaxMemory: sl.Int(2048),
StartCpus: sl.Int(1),
Datacenter: &datatypes.Location{Name: sl.String("sjc01")},
OperatingSystemReferenceCode: sl.String("UBUNTU_LATEST"),
LocalDiskFlag: sl.Bool(true),
}
guest, err := service.Mask("id;domain").CreateObject(&guestTpl)
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
fmt.Printf("New Virtual Guest created with ID %d\n", *guest.Id)
fmt.Printf("Domain: %s\n", *guest.Domain)
}
The IBM approval mail comes after an hour , and the VM related updates are generated after that mail.
Is there a way to reduce the time ? Or is the IBM behavior takes longer time ?
Help is highly appreciated.
I use python for that task and one day I've faced that I need 1 hour per 1 server to create. So there is no technical solution. IBM somehow approves server creating manually.
I would recommend raise a support ticket to IBM. Now I have average 3 minutes to create a virtual server.
Just in case try to use servers like B1_1X2X100. To insure that you use standard fast setup.
Good luck