diff --git a/README.md b/README.md index 90635780..68f2fc95 100644 --- a/README.md +++ b/README.md @@ -208,7 +208,7 @@ This section does not describe permanent API contracts; it just describes limita ## Backend Configuration -Prebid Cache requires a backend data store which enforces TTL expiration. The following storage options are supported: Aerospike, Cassandra, Memcache, and Redis. You're welcomed to contribute a new backend adapter if needed. +Prebid Cache requires a backend data store which enforces TTL expiration. The following storage options are supported: Aerospike, Cassandra, Memcache, and Redis/Redis sentinel. You're welcomed to contribute a new backend adapter if needed. There is also an option (enabled by default) for a basic in-memory data store intended only for development. This backend does not support TTL expiration and is not built for production use. @@ -383,4 +383,4 @@ docker run -p 8000:8000 -t prebid-cache ### Profiling -[pprof stats](http://artem.krylysov.com/blog/2017/03/13/profiling-and-optimizing-go-web-applications/) can be accessed from a running app on the admin port `localhost:2525`. \ No newline at end of file +[pprof stats](http://artem.krylysov.com/blog/2017/03/13/profiling-and-optimizing-go-web-applications/) can be accessed from a running app on the admin port `localhost:2525`. diff --git a/backends/config/config_test.go b/backends/config/config_test.go index ea72d46a..48a2de75 100644 --- a/backends/config/config_test.go +++ b/backends/config/config_test.go @@ -149,6 +149,8 @@ func TestNewBaseBackend(t *testing.T) { desc: "Redis", inConfig: config.Backend{Type: config.BackendRedis}, expectedLogEntries: []logEntry{ + {msg: "Error creating Redis backend: At least one Host[s] is required.", lvl: logrus.FatalLevel}, + {msg: "Creating Redis backend", lvl: logrus.InfoLevel}, {msg: "Error creating Redis backend: ", lvl: logrus.FatalLevel}, }, }, diff --git a/backends/redis.go b/backends/redis.go index 21fa50ce..569d03a7 100644 --- a/backends/redis.go +++ b/backends/redis.go @@ -49,14 +49,17 @@ type RedisBackend struct { func NewRedisBackend(cfg config.Redis, ctx context.Context) *RedisBackend { if len(cfg.Hosts) < 1 || cfg.Host == "" { - log.Fatalf("At least one Host[s] is required.") + log.Fatalf("Error creating Redis backend: At least one Host[s] is required.") } var redisClient RedisDBClient + sentinel := false + if cfg.MasterName != "" { - log.Info("Creating Redis sentinel backend") + sentinel = true // Mode failover (sentinel) + log.Info("Creating Redis sentinel backend") options := &redis.FailoverOptions{ MasterName: cfg.MasterName, SentinelAddrs: cfg.Hosts, @@ -70,10 +73,9 @@ func NewRedisBackend(cfg config.Redis, ctx context.Context) *RedisBackend { } redisClient = RedisDBClient{client: redis.NewFailoverClient(options)} - } else { - log.Info("Creating Redis backend") // Mode single + log.Info("Creating Redis backend") constr := cfg.Host + ":" + strconv.Itoa(cfg.Port) options := &redis.Options{ Addr: constr, @@ -96,7 +98,11 @@ func NewRedisBackend(cfg config.Redis, ctx context.Context) *RedisBackend { panic("RedisBackend failure. This shouldn't happen.") } - log.Infof("Connected to Redis at %s:%d", cfg.Host, cfg.Port) + if sentinel { + log.Infof("Connected to Redis: %v", cfg.Hosts) + } else { + log.Infof("Connected to Redis: %s:%v", cfg.Host, cfg.Port) + } return &RedisBackend{ cfg: cfg, diff --git a/config/backends.go b/config/backends.go index d8f46609..1783b9c7 100644 --- a/config/backends.go +++ b/config/backends.go @@ -152,13 +152,13 @@ func (cfg *Memcache) validateAndLog() error { type Redis struct { Host string `mapstructure:"host"` - Hosts []string `mapstructure:"hosts"` - MasterName string `mapstructure:"mastername"` Port int `mapstructure:"port"` Password string `mapstructure:"password"` Db int `mapstructure:"db"` ExpirationMinutes int `mapstructure:"expiration"` TLS RedisTLS `mapstructure:"tls"` + Hosts []string `mapstructure:"hosts"` + MasterName string `mapstructure:"mastername"` } type RedisTLS struct { @@ -167,8 +167,13 @@ type RedisTLS struct { } func (cfg *Redis) validateAndLog() error { - log.Infof("config.backend.redis.host: %s", cfg.Host) - log.Infof("config.backend.redis.port: %d", cfg.Port) + if cfg.Host != "" && len(cfg.Hosts) > 0 { + log.Infof("config.backend.redis.hosts: %s. Note that redis host will be ignore if 'hosts' is define", cfg.Hosts) + log.Infof("config.backend.redis.mastername: %s.", cfg.MasterName) + } else { + log.Infof("config.backend.redis.host: %s", cfg.Host) + log.Infof("config.backend.redis.port: %d", cfg.Port) + } log.Infof("config.backend.redis.db: %d", cfg.Db) if cfg.ExpirationMinutes > 0 { log.Infof("config.backend.redis.expiration: %d. Note that this configuration option is being deprecated in favor of config.request_limits.max_ttl_seconds", cfg.ExpirationMinutes) diff --git a/config/config_test.go b/config/config_test.go index 8ab6da94..b3878f38 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -1202,6 +1202,7 @@ func getExpectedDefaultConfig() Configuration { DefaultTTL: utils.CASSANDRA_DEFAULT_TTL_SECONDS, }, Redis: Redis{ + Hosts: []string{}, ExpirationMinutes: utils.REDIS_DEFAULT_EXPIRATION_MINUTES, }, Ignite: Ignite{ @@ -1267,8 +1268,12 @@ func getExpectedFullConfigForTestFile() Configuration { Hosts: []string{"10.0.0.1:11211", "127.0.0.1"}, }, Redis: Redis{ - Host: "127.0.0.1", - Port: 6379, + Host: "127.0.0.1", + Port: 6379, + Hosts: []string{ + "10.0.0.1:26379", "127.0.0.1", + }, + MasterName: "mymaster", Password: "redis-password", Db: 1, ExpirationMinutes: 1, diff --git a/config/configtest/sample_full_config.yaml b/config/configtest/sample_full_config.yaml index 3c40fbb7..5d814cae 100644 --- a/config/configtest/sample_full_config.yaml +++ b/config/configtest/sample_full_config.yaml @@ -27,8 +27,12 @@ backend: keyspace: "prebid" default_ttl_seconds: 60 memcache: - hosts: ["10.0.0.1:11211","127.0.0.1"] + hosts: ["10.0.0.1:11211", "127.0.0.1"] redis: + hosts: + - "10.0.0.1:26379" + - "127.0.0.1" + mastername: "mymaster" host: "127.0.0.1" port: 6379 password: "redis-password" diff --git a/config/configtest/sample_full_redis_sentinel_config.yaml b/config/configtest/sample_full_redis_sentinel_config.yaml deleted file mode 100644 index f98d98e6..00000000 --- a/config/configtest/sample_full_redis_sentinel_config.yaml +++ /dev/null @@ -1,67 +0,0 @@ -port: 9000 -admin_port: 2525 -index_response: "Any index response" -log: - level: "info" -rate_limiter: - enabled: false - num_requests: 150 -request_limits: - max_size_bytes: 10240 - max_num_values: 10 - max_ttl_seconds: 5000 - allow_setting_keys: true -backend: - type: "memory" - aerospike: - default_ttl_seconds: 3600 - host: "aerospike.prebid.com" - hosts: ["aerospike2.prebid.com", "aerospike3.prebid.com"] - port: 3000 - namespace: "whatever" - user: "foo" - password: "bar" - connection_idle_timeout_seconds: 2 - cassandra: - hosts: "127.0.0.1" - keyspace: "prebid" - default_ttl_seconds: 60 - memcache: - hosts: ["10.0.0.1:11211", "127.0.0.1"] - redis: - hosts: ["127.0.0.1:26379", "127.0.0.2:26379"] - mastername: "mastername" - password: "redis-password" - db: 1 - expiration: 1 - tls: - enabled: false - insecure_skip_verify: false - ignite: - scheme: "http" - host: "127.0.0.1" - port: 8080 - secure: false - headers: !!omap - - Content-Length: 0 - cache: - name: "whatever" - create_on_start: false -compression: - type: "snappy" -metrics: - type: "none" - influx: - host: "metrics-host" - database: "metrics-database" - username: "metrics-username" - password: "metrics-password" - enabled: true - prometheus: - port: 8080 - namespace: "prebid" - subsystem: "cache" - timeout_ms: 100 - enabled: true -routes: - allow_public_write: true