Почему мой API получает данные из базы данных быстрее, чем из Redis?
Я работаю с Django и GraphQL, чтобы создать бэкэнд для приложения электронной коммерции. Изначально API для получения товаров был медленным, поэтому я решил реализовать стек Redis, чтобы ускорить его. Однако я обнаружил, что получение данных из Redis происходит гораздо медленнее, чем из базы данных. Ниже приведены детали моей реализации:
Запрос к базе данных:
def resolve_products(self, info, **kwargs):
(filter_objects, method_filter, seller_lst, name, ar_name) = (
product_obj.call_filter_product()
)
kwargs["seller_list"] = eller_lst
query = (
Products.objects.filter(filter_objects, method_filter, active=True)
.filter(variants__seller__id__in=list(seller_lst))
.distinct()
)
query = query.filter(
Exists(
Variant.objects.filter(
product_id=OuterRef("id"),
seller_id__in=seller_lst,
stock_available=True,
)
)
)
start_index = int(offset)
end_index = start_index + int(kwargs.get("first"))
query_set = query[start_index:end_index]
final_qs = query_set.annotate(
stock_available=Exists(
Variant.objects.filter(
product_id=OuterRef("id"),
seller_id__in=seller_lst,
stock_available=True,
)
)
)
# Determine hasNextPage
has_next_page = end_index < len(query)
connection = ProductsConnection(
edges=[ProductsConnection.Edge(node=product) for product in final_qs],
total_count=query.count(),
details={
"header_en": name,
"header_ar": ar_name,
"method": kwargs.get("method"),
},
)
connection.page_info = PageInfo(
start_cursor=start_index,
end_cursor=(
int(kwargs.get("first")) + 1
if int(offset) == 0
else int(offset) + int(kwargs.get("first"))
),
has_next_page=has_next_page,
has_previous_page=start_index > 0,
)
return connection
Реализация Redis:
seller_lst = obj.get_seller_lst()
redis_obj = RedisUtility()
data = redis_obj.get_products(seller_lst, **kwargs)
if data:
product_ids = [int(product['id']) for product in data['products']]
products = Products.objects.filter(id__in=product_ids)
connection = ProductsConnection(
edges=[ProductsConnection.Edge(node=product) for product in products],
total_count=data['total_count'],
details={
"header_en": "name",
"header_ar": "ar_name",
"method": kwargs.get("method"),
},
)
connection.page_info = relay.PageInfo(
start_cursor=str(data['offset']),
end_cursor=str(
int(kwargs.get("first")) + 1
if int(data['offset']) == 0
else int(data['offset']) + int(kwargs.get("first"))
),
has_next_page=data['end_index'] < data['total_count'],
has_previous_page=data['offset'] > 0,
)
return connection
Утилита Redis:
class RedisUtility:
def __init__(
self,
host=settings.REDIS_STACK_HOST,
port=settings.REDIS_STACK_PORT,
username=settings.REDIS_STACK_USERNAME,
password=settings.REDIS_STACK_PASSWORD,
decode_responses=settings.REDIS_STACK_DECODE_RESPONSES,
):
self.host = host
self.port = port
self.username = username
self.password = password
self.decode_responses = decode_responses
self.connection = None
def connect(self):
if not self.connection:
self.connection = get_redis_connection(
host=self.host,
port=self.port,
username=self.username,
password=self.password,
decode_responses=self.decode_responses,
)
return self.connection
def get_products(self, seller_lst, **kwargs):
r = self.connect()
offset = kwargs.get("after") if kwargs.get("after") else 0
limit = int(kwargs.get("first", 10))
category_ids = self.get_category_ids(kwargs.get('slug'), kwargs.get('level'))
category_query = f"@category:{{{' | '.join(map(str, category_ids))}}}"
seller_query = f"@stock_available_seller:{{{' | '.join(map(str, seller_lst))}}}"
final_query = f"({category_query}) (@stock_available_seller:({seller_query}))"
count_query = Query(final_query)
total_count = r.ft(':product:index').search(count_query).total
q = Query(final_query).paging(offset, limit)
result = r.ft(':product:index').search(q)
products = [json.loads(doc.json) for doc in result.docs]
return {
'total_count': total_count,
'offset': offset,
'end_index': offset + limit,
'products': products
}
Проблема: Несмотря на внедрение Redis, API работает медленнее, чем при получении данных напрямую из базы данных. Я ожидал, что Redis ускорит этот процесс, но все происходит наоборот.
Вопросы:
- Какие причины могут быть причиной низкой производительности при использовании Redis?
- Как можно оптимизировать реализацию Redis для улучшения времени отклика?
- Существуют ли какие-либо лучшие практики использования Redis с Django/GraphQL для обеспечения лучшей производительности? Любые соображения или предложения будут очень признательны. Спасибо!