Repository: celery/celery

Issue:
Extend config of Redis backend
<!--
Please fill this template entirely and do not erase parts of it.
We reserve the right to close without a response
feature requests which are incomplete.
-->
# Checklist
<!--
To check an item on the list replace [ ] with [x].
-->

- [x] I have checked the [issues list](https://github.com/celery/celery/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22Issue+Type%3A+Feature+Request%22+)
  for similar or identical feature requests.
- [x] I have checked the [pull requests list](https://github.com/celery/celery/pulls?utf8=%E2%9C%93&q=is%3Apr+label%3A%22PR+Type%3A+Feature%22+)
  for existing proposed implementations of this feature.
- [x] I have checked the [commit log](https://github.com/celery/celery/commits/master)
  to find out if the if the same feature was already implemented in the
  master branch.
- [x] I have included all related issues and possible duplicate issues
  in this issue (If there are none, check this box anyway).

## Related Issues and Possible Duplicates
<!--
Please make sure to search and mention any related issues
or possible duplicates to this issue as requested by the checklist above.

This may or may not include issues in other repositories that the Celery project
maintains or other repositories that are dependencies of Celery.

If you don't know how to mention issues, please refer to Github's documentation
on the subject: https://help.github.com/en/articles/autolinked-references-and-urls#issues-and-pull-requests
-->

#### Related Issues

- None

#### Possible Duplicates

- None

# Description
I was trying to change config of Redis backend connections (not Kombu _broker_transport_options_). 
This is not a problem for `socket_timeout` and `socket_connect_timeout` (I've set `CELERY_REDIS_SOCKET_TIMEOUT` and `CELERY_REDIS_SOCKET_CONNECT_TIMEOUT`), but problem to change `socket_keepalive` and `retry_on_timeout`.
I think this can be helpful - sometimes I catching `TimeoutError` from Beat on `'SUBSCRIBE'` event.

# Suggestions
I propose add `socket_keepalive` and `retry_on_timeout` to connparams of `RedisBackend`:
https://github.com/celery/celery/blob/240ef1f64c8340bfffc31359f842ea4a6c8c493a/celery/backends/redis.py#L185-L194


Discussion:
There are all sorts of Redis connection errors that could cause problems with Celery that we deal on a daily basis... Most typical ones are timeout errors. `retry_on_timeout`, as far as I know, does it only once, so it is almost useless...
> There are all sorts of Redis connection errors that could cause problems with Celery that we deal on a daily basis... Most typical ones are timeout errors. `retry_on_timeout`, as far as I know, does it only once, so it is almost useless...

Sometimes I catch TimeoutError on the start of periodic task (on "SUBSCRIPTION" event). This rare and important task and I think this retry can be helpful:

https://github.com/andymccurdy/redis-py/blob/ff69f0d77284643909462ee6d1e37233c6677672/redis/client.py#L877-L893

Yep, it will definitely help in this case.

Resolving patch:
diff --git a/celery/backends/redis.py b/celery/backends/redis.py
--- a/celery/backends/redis.py
+++ b/celery/backends/redis.py
@@ -185,6 +185,8 @@ def __init__(self, host=None, port=None, db=None, password=None,
 
         socket_timeout = _get('redis_socket_timeout')
         socket_connect_timeout = _get('redis_socket_connect_timeout')
+        retry_on_timeout = _get('redis_retry_on_timeout')
+        socket_keepalive = _get('redis_socket_keepalive')
 
         self.connparams = {
             'host': _get('redis_host') or 'localhost',
@@ -193,6 +195,8 @@ def __init__(self, host=None, port=None, db=None, password=None,
             'password': _get('redis_password'),
             'max_connections': self.max_connections,
             'socket_timeout': socket_timeout and float(socket_timeout),
+            'retry_on_timeout': retry_on_timeout or False,
+            'socket_keepalive': socket_keepalive or False,
             'socket_connect_timeout':
                 socket_connect_timeout and float(socket_connect_timeout),
         }


Test patch: