go-redis / cache

Cache library with Redis backend for Golang
https://redis.uptrace.dev/guide/go-redis-cache.html
BSD 2-Clause "Simplified" License
757 stars 95 forks source link

ring.go:320: ring shard state changed: Redis<:6379 db:10> is down #63

Closed nicolasassi closed 3 years ago

nicolasassi commented 3 years ago

I'm having problems regarding connecting to redis on docker as seems in the title.

My go code stands as follows:

func NewRedis() (*Redis, error) {
    db, err := strconv.Atoi(os.Getenv("REDIS_DB"))
    if err != nil {
        return nil, fmt.Errorf("error connecting to redis %s:%s:%s: %v",
            os.Getenv("REDIS_ADDR"), os.Getenv("REDIS_PORT"), os.Getenv("REDIS_DB"), err)
    }
    options := redis.RingOptions{
        Addrs: map[string]string{
            os.Getenv("REDIS_ADDR"): fmt.Sprintf(":%s", os.Getenv("REDIS_PORT")),
        },
        DB: db,
    }
    ring := redis.NewRing(&options)
    return &Redis{cache: cache.New(&cache.Options{
        Redis:      ring,
        LocalCache: cache.NewTinyLFU(1000, time.Minute),
    })}, nil
}

my docker-compose responsible for redis:

version: '3.7'

networks:
  calliope:
    name: calliope
    driver: bridge

services:
  redis:
    container_name: redis-calliope
    image: redis:latest
    command: [ "redis-server", "--bind", "redis", "--port", "6379" ]
    ports:
      - 6379:6379
    networks:
      calliope:
        aliases:
          - redis

My docker-compose for the go service:

version: '3.7'

networks:
  calliope:
    name: calliope
    driver: bridge

services:
  calliope_text_analysis:
    container_name: calliope_text_analysis_local
    build:
      context: . # Use an image built from the specified dockerfile in the current directory.
      dockerfile: Dockerfile
      args:
        - ENV_FILE=env-local
    environment:
      GOOGLE_APPLICATION_CREDENTIALS: /tmp/keys/keyfile.json
    volumes:
      - ${GOOGLE_APPLICATION_CREDENTIALS}:/tmp/keys/keyfile.json:ro
    ports:
      - 8888:8888
    networks:
      - calliope
nicolasassi commented 3 years ago

in addition to that, I'm able to connect normaly to redis when running my application out of docker connecting to redis inside the container. The problem only occurs when trying to connect when both sides are in containers

bamstars commented 3 years ago

any idea about that? i met the same problem...

nicolasassi commented 3 years ago

@bamstars ended up using redis instead of cache as I could not solve this problem...

bamstars commented 3 years ago

@nicolasassi thank you for you kindly reply, i found this problem when deployed server app in a docker whatever deployed redis instance in either docker or local host. My current solution is using UniversalClient instead of Ring, it seems work well so far, code like below

// ring := redis.NewRing(&redis.RingOptions{ // Addrs: conf.AddrPort, // Password: conf.Password, // DB: conf.DB, // })

rdb := redis.NewUniversalClient(&redis.UniversalOptions{
    Addrs:    conf.AddrPort,
    Password: conf.Password,
    DB:       conf.DB,
})

return cache.New(&cache.Options{
    Redis: rdb,
    LocalCache: cache.NewTinyLFU(
        conf.Size,
        time.Duration(conf.TtlInHours)*time.Hour),
})

Detail docs about UniversalClient and Cache can be found here https://redis.uptrace.dev/guide/universal.html https://redis.uptrace.dev/guide/caching.html