All Projects → kvz → Cronlock

kvz / Cronlock

Licence: mit
cronlock lets you deploy cronjobs cluster-wide without worrying about overlaps. It uses Redis to keep track of locks.

Programming Languages

shell
77523 projects

Projects that are alternatives of or similar to Cronlock

Nodock
Docker Compose for Node projects with Node, MySQL, Redis, MongoDB, NGINX, Apache2, Memcached, Certbot and RabbitMQ images
Stars: ✭ 734 (+190.12%)
Mutual labels:  cron-jobs, redis
Redis Rogue Server
Redis 4.x/5.x RCE
Stars: ✭ 243 (-3.95%)
Mutual labels:  redis
Video Chat
Video chat app using Vue, Vuex, WebRTC, SocketIO, Node, Redis & Docker with horizontal scaling. Multiparty and 1 to 1 video functionality, several public rooms and user status
Stars: ✭ 240 (-5.14%)
Mutual labels:  redis
Awesome crawl
腾讯新闻、知乎话题、微博粉丝,Tumblr爬虫、斗鱼弹幕、妹子图爬虫、分布式设计等
Stars: ✭ 246 (-2.77%)
Mutual labels:  redis
Kue Scheduler
A job scheduler utility for kue, backed by redis and built for node.js
Stars: ✭ 240 (-5.14%)
Mutual labels:  redis
Cqrs Clean Eventual Consistency
CQRS, using Clean Architecture, multiple databases and Eventual Consistency
Stars: ✭ 247 (-2.37%)
Mutual labels:  redis
Webrtc im
webrtc 直播连麦
Stars: ✭ 237 (-6.32%)
Mutual labels:  redis
Type Graphql Series
Typescript GraphQL Server built with TypeGraphQL
Stars: ✭ 249 (-1.58%)
Mutual labels:  redis
Redis rate
Rate limiting for go-redis
Stars: ✭ 248 (-1.98%)
Mutual labels:  redis
Zapi
基于swoole的异步轻量级api框架,内部封装全套mysql、redis、mongo、memcached异步客户端,可以轻松start、reload、stop,加入数据库的查询模块,框架已经封装好近乎同步写法,底层异步调用。现已支持异步mysql、异步redis、异步http请求.
Stars: ✭ 245 (-3.16%)
Mutual labels:  redis
Redis Manager
Integrates your Laravel application with a redis manager
Stars: ✭ 245 (-3.16%)
Mutual labels:  redis
Blog
煎鱼的博客,有点忙,传送门:https://eddycjy.com
Stars: ✭ 2,772 (+995.65%)
Mutual labels:  redis
Spring Cloud Shop
spring cloud 版分布式电商项目,全力打造顶级多模块,高可用,高扩展电商项目
Stars: ✭ 248 (-1.98%)
Mutual labels:  redis
Golang Url Shortener
URL Shortener written in Golang using Bolt DB or Redis. Provides features such as Deletion, Expiration, OAuth and is of course Dockerizable.
Stars: ✭ 240 (-5.14%)
Mutual labels:  redis
Redis
Native port of Redis for Windows. Redis is an in-memory database that persists on disk. The data model is key-value, but many different kind of values are supported: Strings, Lists, Sets, Sorted Sets, Hashes, Streams, HyperLogLogs. This repository contains unofficial port of Redis to Windows.
Stars: ✭ 4,186 (+1554.55%)
Mutual labels:  redis
Chain
链喵 CMDB 本项目已停止开发!因长时间未对代码进行维护,可能会造成项目在不同环境上无法部署、运行BUG等问题,请知晓!项目仅供参考!
Stars: ✭ 240 (-5.14%)
Mutual labels:  redis
Docker Lnmp
🐋Docker-compose(Linux,Nginx,MySQL,PHP7,Redis)
Stars: ✭ 244 (-3.56%)
Mutual labels:  redis
Spring Boot Start Current
Spring Boot 脚手架 Mybatis Spring Security JWT 权限 Spring Cache + Redis
Stars: ✭ 246 (-2.77%)
Mutual labels:  redis
Atlas Of Thrones
An interactive "Game of Thrones" map powered by Leaflet, PostGIS, and Redis.
Stars: ✭ 253 (+0%)
Mutual labels:  redis
Rollout
Feature flippers.
Stars: ✭ 2,774 (+996.44%)
Mutual labels:  redis

cronlock

Build Status Gittip donate button Flattr donate button PayPayl donate button BitCoin donate button

Install

On most Linux & BSD machines, cronlock will install just by downloading it & making it executable. Here's the one-liner:

sudo curl -q -L https://raw.github.com/kvz/cronlock/master/cronlock -o /usr/bin/cronlock && sudo chmod +x $_

With Redis present on localhost, cronlock should now already work in basic form. Let's test by letting it execute a simple pwd:

CRONLOCK_HOST=localhost cronlock pwd

If this returns the current directory we're good to go. More examples below.

Introduction

Uses a central Redis server to globally lock cronjobs across a distributed system. This can be usefull if you have 30 webservers that you deploy crontabs to (such as mailing your customers), but you don't want 30 cronjobs spawned.

Of course you could also deploy your cronjobs to 1 box, but in volatile environments such as EC2 it can be helpful not to rely on 1 'throw away machine' for your scheduled tasks, and have 1 deploy-script for all your workers.

Another common problem that cronlock will solve is overlap by a single server/cronjob. It happens a lot that developers underestimate how long a job will run. This can happen because the job waits on something, acts different under high load/volume, or enters an endless loop.

In these cases you don't want the job to be fired again at the next cron-interval, making your problem twice as bad, some intervals later, there's a huge ps auxf with overlapping cronjobs, high server load, and eventually a crash.

By settings locks, cronlock can also prevent the overlap in longer-than-expected-running cronjobs.

Design goals

  • Lightweight
  • As little dependencies as possible / No setup
  • Follows locking logic from this Redis documentation
  • Well tested & documented

Requirements

  • Bash (version 3.0 and above) with /dev/tcp enabled. Older Debian/Ubuntu systems disable /dev/tcp
  • md5 or md5sum
  • A Redis server, or cluster of servers that is accessible by all cronlock machines

Options

  • CRONLOCK_CONFIG location of config file. this is optional since all config can also be passed as environment variables. default: <DIR>/cronlock.conf, /etc/cronlock.conf

Using the CRONLOCK_CONFIG file or by exporting in your environment, you can set these variables to change the behavior of cronlock:

  • CRONLOCK_HOST the Redis hostname. default: localhost
  • CRONLOCK_PORT the Redis port. default: 6379
  • CRONLOCK_AUTH the Redis auth password. default: Not present
  • CRONLOCK_DB the Redis database. default: 0
  • CRONLOCK_REDIS_TIMEOUT the length of time we wait for a response from redis before we consider it in an errored state. This ensures that if the redis connection goes away that we don't wait forever waiting for a response. default: 30
  • CRONLOCK_GRACE determines how many seconds a lock should at least persist. This is to make sure that if you have a very small job, and clocks aren't in sync, the same job on server2/3/4/5/6/etc (maybe even slightly behind in time) will just fire right after server1 releases the lock. default: 40 (I recommend using a grace of at least 30s)
  • CRONLOCK_RELEASE determines how long a lock can persist at most. Acts as a failsafe so there can be no locks that persist forever in case of failure. default is a day: 86400
  • CRONLOCK_RECONNECT_ATTEMPTS the number of times we try to reconnect before erroring. If the redis connection is closed, we will attempt to reconnect to redis upto this amount of times. default: 5
  • CRONLOCK_RECONNECT_BACKOFF the lenght of time to increase the wait between reconnects. Acts as a failsafe to allow redis to be started before we try to reconnect. Set to 0 to retry the connection immediately. default: 5
  • CRONLOCK_KEY a unique key for this command in the global Redis server. default: a hash of cronlock's arguments
  • CRONLOCK_PREFIX Redis key prefix used by all keys. default: cronlock
  • CRONLOCK_VERBOSE set to yes to print debug messages. default: no
  • CRONLOCK_NTPDATE set to yes update the server's clock againt pool.ntp.org before execution. default: no
  • CRONLOCK_TIMEOUT how long the command can run before it gets issues a kill -9. default: 0; no timeout

Redis Cluster Support

Cronlock has support for Redis Cluster (http://redis.io/topics/cluster-spec) introduced in Redis 3.0.

Cronlock acts as a relatively "dumb" cluster client - it will react to MOVED and ASK commands and retry the request to the node given back in the response but it does not attempt to record the slot to node relationship for future use.

Cronlock supports the configuration of only one CRONLOCK_HOST and CRONLOCK_PORT. Cronlock will always connect to the configured host and port and issue the initial REDIS command with the calculated MD5 key. If the Redis node returns ASK or MOVED, Cronlock will disconnect and connect to the given host and port in the ASK or MOVED respoonse. The new Redis host is used for the remaining duration of the execution of Cronlock (or until another ASK or MOVED command is returned) - Cronlock will connect to the originally configured CRONLOCK_HOST and CRONLOCK_PORT for the next execution.

Given the support of only one CRONLOCK_HOST and CRONLOCK_PORT it is recommended that each server running cronlock is configured to initially connect a different master in the Redis Cluster. Thus if one Redis server goes down the instances of Cronlock configured to connect to the other master nodes will continue to operate.

This is easily done if the Redis Cluster is on the same servers as Cronlock - as CRONLOCK_HOST can be set to 127.0.0.1 - each copy of Cronlock will therefore initially connect to its local master node - before reconnecting to other alive Redis nodes.

Aside from configuring appropriate values for CRONLOCK_HOST and CRONLOCK_PORT for the systems running Cronlock - no additional configuration is required for Redis Cluster support.

Examples

Single box

crontab -e
* * * * * cronlock ls -al

In this configuration, ls -al will be launched every minute. If the previous ls -al has not finished yet, another one is not started. This works on 1 server, as the default CRONLOCK_HOST of localhost is used.

In this setup, cronlock works much like Tim Kay's solo, except cronlock requires Redis, so I recommend using Tim Kay's solution here.

Distributed

echo '0 8 * * * CRONLOCK_HOST=redis.mydomain.com cronlock /var/www/mail_customers.sh' | crontab

In this configuration, a central Redis server is used to track the locking for /var/www/mail_customers.sh. So you see that throughout a cluster of 100 servers, just one instance of /var/www/mail_customers.sh is ran every morning. No less, no more.

As long as your Redis server and at least 1 volatile worker is alive, this happens.

Distributed using a config file

To avoid messy crontabs, you can use a config file for shared config instead. Unless CRONLOCK_CONFIG is set, cronlock will look in ./cronlock.conf, then in /etc/cronlock.conf.

Example:

cat << EOF > /etc/cronlock.conf
CRONLOCK_HOST="redis.mydomain.com"
CRONLOCK_GRACE=50
CRONLOCK_PREFIX="mycompany.cronlocks."
CRONLOCK_NTPDATE="yes"
EOF

crontab -e
* * * * * cronlock /var/www/mail_customers.sh # will use config from /etc/cronlock.conf

Lock commands even though they have different arguments

By default cronlock uses your command and its arguments to make a unique identifier by which the global lock is acquired. However if you want to run: ls -al or ls -a, but just 1 instance of either, you'll want to provide your own key:

crontab -e
# One of two will be executed because they share the same KEY
* * * * * CRONLOCK_KEY="ls" cronlock ls -al
* * * * * CRONLOCK_KEY="ls" cronlock ls -a

Per application

If you use the same script and Redis server for multiple applications, an unwanted lock could deny app2 its script. You could make up your own unique CRONLOCK_KEY to circumvent, but it's probably better to use the CRONLOCK_PREFIX for that:

crontab -e
* * * * * CRONLOCK_PREFIX="mylocks.app1." cronlock /var/www/mail_customers.sh
crontab -e
* * * * * CRONLOCK_PREFIX="mylocks.app2." cronlock /var/www/mail_customers.sh

Now both /var/www/mail_customers.sh will run, because they have a different application in their prefixes.

Exit codes

  • = 200 Success (delete succeeded or lock not acquired, but normal execution)
  • = 201 Failure (cronlock error)
  • = 202 Failure (cronlock timeout)
  • < 200 Success (acquired lock, executed your command), passes the exit code of your command

Versioning

This project implements the Semantic Versioning guidelines.

Releases will be numbered with the following format:

<major>.<minor>.<patch>

And constructed with the following guidelines:

  • Breaking backward compatibility bumps the major (and resets the minor and patch)
  • New additions without breaking backward compatibility bumps the minor (and resets the patch)
  • Bug fixes and misc changes bumps the patch

For more information on SemVer, please visit http://semver.org.

License

Copyright (c) 2013 Kevin van Zonneveld, http://kvz.io
Licensed under MIT: http://kvz.io/licenses/LICENSE-MIT

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].