Перенести состояние вектора LangGraph из памяти в хранилище Redis
Перенос состояния векторов LangGraph из памяти в Redis с использованием фабрики get_vector_store, хранение метаданных сессий при вводе данных, фильтрованное поиск и удаление по сессии.
Источники: From In-Memory to Redis: Vector Persistence
Хранилища векторов в памяти представляют собой самую простую корректную архитектуру только тогда, когда один процесс контролирует всю конверсацию. Реальные бэкенды нарушают это предположение: запуск новых CLI-инструментов, новые HTTP-рабочие процессы, перезагрузки и развертывание в нескольких экземплярах. Персистентность означает перемещение тех же узлов LangGraph в Redis (или другой долговечный индекс векторов) без необходимости переписывания логики продукта.
1. get_vector_store() — единственная функция, которую пришлось изменить
Абстрактная структура, скрывающая детали реализации. Используется в памяти для тестирования; URL к Redis и имя индекса — в развернутых средах.
_SESSION_STORES: Dict[str, InMemoryVectorStore] = {}
def get_vector_store(session_id: str) -> InMemoryVectorStore:
if session_id not in _SESSION_STORES:
_SESSION_STORES[session_id] = InMemoryVectorStore(embeddings)
return _SESSION_STORES[session_id]
def get_vector_store(session_id: str) -> RedisVectorStore:
redis_config = RedisConfig(
index_name=f"session:{session_id}",
redis_url=config.REDIS_URL,
embedding_dimensions=config.EMBEDDING_DIMENSIONS,
metadata_schema=[
{"name": "session_id", "type": "tag"},
{"name": "file_name", "type": "tag"},
],
)
return RedisVectorStore(embeddings, config=redis_config, ttl=config.SESSION_TTL_SECONDS)
docs = [
Document(
page_content=c["text"],
metadata={
"session_id": state["session_id"], # <-- added back
"file_name": c["file_name"],
"chunk_index": c["chunk_index"],
},
)
for c in chunks
]
state["retrieved"] = vs.similarity_search(
state["query"],
k=config.TOP_K,
filter=Tag("session_id") == state["session_id"],
)
def clear_session(session_id: str) -> None:
get_vector_store(session_id).index.delete(drop=True)
uv add langgraph langchain-core langchain-openai langchain-text-splitters \
azure-ai-documentintelligence azure-core \
langchain-redis redisvl \
python-dotenv
REDIS_PASSWORD=changeme docker compose up -d
[+] Running 3/3
✔ Network redismanualvectorization_default Created 0.0s
✔ Volume "redismanualvectorization_redis-data" Created 0.0s
✔ Container usb-redis-vector-store Started
AZURE_OPENAI_ENDPOINT=https://aif-cus-aisearchegs-dev-01.cognitiveservices.azure.com/
AZURE_OPENAI_API_KEY=<Redacted>
# AZURE_OPENAI_API_VERSION = os.environ.get("AZURE_OPENAI_API_VERSION", "2024-10-21")
AZURE_OPENAI_EMBEDDING_DEPLOYMENT=text-embedding-3-small
AZURE_OPENAI_CHAT_DEPLOYMENT="gpt-5-mini"
# --- Azure Document Intelligence (used for all file text extraction) ---
DOCUMENTINTELLIGENCE_ENDPOINT=https://adi-cus-aisearchegs-dev-01.cognitiveservices.azure.com/
DOCUMENTINTELLIGENCE_KEY=<Redacted>
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=changeme
SESSION_TTL_SECONDS=14400
uv run python -m src.redismanualvectorization.main \
--session demo1 \
--files ./source/sample_bank_statement.pdf ./source/sample_loan_agreement.pdf
Ingested 2 file(s) into session 'demo1' (persisted in Redis).
docker exec -it usb-redis-vector-store redis-cli -a changeme
FT._LIST
# Execution results
1) session:demo2
2) session:demo1
FT.INFO session:demo1
# Execution results
1) index_name
2) session:demo1
3) index_options
4) (empty array)
5) index_definition
6) 1) key_type
2) HASH
3) prefixes
4) 1) session:demo1:
5) default_score
6) "1"
7) attributes
8) 1) 1) identifier
2) text
3) attribute
4) text
5) type
6) TEXT
7) WEIGHT
8) "1"
2) 1) identifier
2) embedding
3) attribute
4) embedding
5) type
6) VECTOR
7) algorithm
8) FLAT
9) data_type
10) FLOAT32
11) dim
12) (integer) 1536
13) distance_metric
14) COSINE
3) 1) identifier
2) _index_name
3) attribute
4) _index_name
5) type
6) TEXT
7) WEIGHT
8) "1"
4) 1) identifier
2) _metadata_json
3) attribute
4) _metadata_json
5) type
6) TEXT
7) WEIGHT
8) "1"
5) 1) identifier
2) session_id
3) attribute
4) session_id
5) type
6) TAG
7) SEPARATOR
8) |
6) 1) identifier
2) file_name
3) attribute
4) file_name
5) type
6) TAG
7) SEPARATOR
8) |
9) num_docs
10) (integer) 24
11) max_doc_id
12) (integer) 24
13) num_terms
14) (integer) 850
15) num_records
16) (integer) 1921
17) inverted_sz_mb
18) "0.09056949615478516"
19) vector_index_sz_mb
20) "6.0091552734375"
21) total_inverted_index_blocks
22) (integer) 853
23) offset_vectors_sz_mb
24) "0.0028848648071289063"
25) doc_table_size_mb
26) "0.017791748046875"
27) sortable_values_size_mb
28) "0"
29) key_table_size_mb
30) "7.74383544921875e-4"
31) tag_overhead_sz_mb
32) "1.10626220703125e-4"
33) text_overhead_sz_mb
34) "0.028371810913085938"
35) total_index_memory_sz_mb
36) "0.14574527740478516"
37) geoshapes_sz_mb
38) "0"
39) records_per_doc_avg
40) "80.04166412353516"
41) bytes_per_record_avg
42) "49.43727111816406"
43) offsets_per_term_avg
44) "1.5065070390701294"
45) offset_bits_per_record_avg
46) "8.362128257751465"
47) hash_indexing_failures
48) (integer) 0
49) total_indexing_time
50) "11.055999755859375"
51) indexing
52) (integer) 0
53) percent_indexed
54) "1"
55) number_of_uses
56) (integer) 3
57) cleaning
58) (integer) 0
59) gc_stats
60) 1) bytes_collected
2) "0"
3) total_ms_run
4) "0"
5) total_cycles
6) "0"
7) average_cycle_time_ms
8) "nan"
9) last_run_time_ms
10) "0"
11) gc_numeric_trees_missed
12) "0"
13) gc_blocks_denied
14) "0"
61) cursor_stats
62) 1) global_idle
2) (integer) 0
3) global_total
4) (integer) 0
5) index_capacity
6) (integer) 128
7) index_total
8) (integer) 0
63) dialect_stats
64) 1) dialect_1
2) (integer) 0
3) dialect_2
4) (integer) 1
5) dialect_3
6) (integer) 0
7) dialect_4
8) (integer) 0
65) Index Errors
66) 1) indexing failures
2) (integer) 0
3) last indexing error
4) N/A
5) last indexing error key
6) "N/A"
7) background indexing status
8) OK
67) field statistics
68) 1) 1) identifier
2) text
3) attribute
4) text
5) Index Errors
6) 1) indexing failures
2) (integer) 0
3) last indexing error
4) N/A
5) last indexing error key
6) "N/A"
2) 1) identifier
2) embedding
3) attribute
4) embedding
5) Index Errors
6) 1) indexing failures
2) (integer) 0
3) last indexing error
4) N/A
5) last indexing error key
6) "N/A"
3) 1) identifier
2) _index_name
3) attribute
4) _index_name
5) Index Errors
6) 1) indexing failures
2) (integer) 0
3) last indexing error
4) N/A
5) last indexing error key
6) "N/A"
4) 1) identifier
2) _metadata_json
3) attribute
4) _metadata_json
5) Index Errors
6) 1) indexing failures
2) (integer) 0
3) last indexing error
4) N/A
5) last indexing error key
6) "N/A"
5) 1) identifier
2) session_id
3) attribute
4) session_id
5) Index Errors
6) 1) indexing failures
2) (integer) 0
3) last indexing error
4) N/A
5) last indexing error key
6) "N/A"
6) 1) identifier
2) file_name
3) attribute
4) file_name
5) Index Errors
6) 1) indexing failures
2) (integer) 0
3) last indexing error
4) N/A
5) last indexing error key
6) "N/A"
num_docs 24
vector_index_sz_mb 6.0091552734375
24 × 1536 × 4 bytes = 147,456 bytes ≈ 0.14 MB
FT.SEARCH session:demo1 "*" LIMIT 0 5 RETURN 3 file_name session_id text
# Execution Results
1) (integer) 24
2) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G2V"
3) 1) "file_name"
2) "sample_bank_statement.pdf"
3) "session_id"
4) "demo1"
5) "text"
6) "##### Monthly Maintenance Fee\n\nA $12.00 monthly maintenance fee applies unless one of the following waiver conditions is met during the statement period: (a) a minimum daily balance of\n$1,500 is maintained, (b) total qualifying direct deposits of $500 or more are received, or (c) the account holder is enrolled in a linked student or senior\naccount program. Fee waiver eligibility is evaluated at the end of each statement cycle based on the criteria above.\n\n\n##### Error Resolution & Your Rights"
4) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G31"
5) 1) "file_name"
2) "sample_loan_agreement.pdf"
3) "session_id"
4) "demo1"
5) "text"
6) "\"Scheduled Payment Date\" means the 15th calendar day of each month during the Loan Term, or the next Business Day\nif the 15th falls on a non-Business Day.\n\n<!-- PageBreak -->\n\n\n# SAMPLE AGREEMENT - SYNTHETIC TEST DATA - NOT A REAL LOAN DOCUMENT\n\n\n## 4. Amortization Schedule (First 12 Payments)"
6) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G34"
7) 1) "file_name"
2) "sample_loan_agreement.pdf"
3) "session_id"
4) "demo1"
5) "text"
6) "A complete 48-month amortization schedule is available from the Lender upon request. Figures above are rounded to the\nnearest cent and may differ slightly from actual billed amounts due to daily interest accrual conventions.\n\n\n## 5. Prepayment\n\nBorrower may prepay all or part of the outstanding Principal Amount at any time without penalty. Partial prepayments will be\napplied first to accrued interest, then to outstanding fees, then to Principal, and will not change the Scheduled Payment\nDate or Monthly Payment amount unless the Borrower requests and the Lender approves a loan re-amortization in writing.\n\n\n### 6. Late Payments and Default"
8) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G2T"
9) 1) "file_name"
2) "sample_bank_statement.pdf"
3) "session_id"
4) "demo1"
5) "text"
6) "##### Interest Rate & Annual Percentage Yield\n\nThis account earns interest at a variable rate, currently 0.15% with an Annual Percentage Yield (APY) of 0.15%, applied to the average daily balance.\nInterest is compounded monthly and credited to your account on the last business day of the statement period, shown in the Transaction History as 'Interest\nPayment'. Rates are subject to change without notice at the bank's discretion and are current as of the statement date shown on page one.\n\n\n##### Monthly Maintenance Fee"
10) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G2W"
11) 1) "file_name"
2) "sample_bank_statement.pdf"
3) "session_id"
4) "demo1"
5) "text"
6) "##### Error Resolution & Your Rights\n\nIn case of errors or questions about electronic transfers, telephone the bank at the number on your card or write to the address on file as soon as possible.\nThe bank must hear from you no later than 60 days after the first statement on which the problem appears. You will need to provide your name and account\nnumber, describe the error, and state the dollar amount of the suspected error. The bank will investigate and report results within 10 business days, or\nwithin 45 days for transactions initiated outside a 30-day period after the first deposit to the account.\n\n\n##### Funds Availability"
127.0.0.1:6379> SCAN 0 MATCH session:demo1:*
1) "22"
2) 1) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G2S"
2) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G2X"
3) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G2R"
4) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G33"
5) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G2V"
6) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G30"
7) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G2Z"
8) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G36"
9) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G2P"
10) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G2Y"
1) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G2V"
file_name sample_bank_statement.pdf
session_id demo1
text "##### Monthly Maintenance Fee
A $12.00 monthly maintenance fee applies unless one of the
following waiver conditions is met during the statement
period: (a) a minimum daily balance of $1,500 is
maintained..."
2) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G31"
file_name sample_loan_agreement.pdf
session_id demo1
text "\"Scheduled Payment Date\" means the 15th calendar day of
each month during the Loan Term...
<!-- PageBreak -->
# SAMPLE AGREEMENT - SYNTHETIC TEST DATA - NOT A REAL LOAN
DOCUMENT"
SCAN 0 MATCH session:demo1:*
# Execution Results
1) "22"
2) 1) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G2S"
2) "session:demo1:01M1MN5JG8DDCXP7K2XHP54G2X"
... (8 more)
import redis
from src.redismanualvectorization.graph import get_vector_store
session_id = "demo1"
vs = get_vector_store(session_id)
r = redis.Redis(host="localhost", port=6379, password="changeme")
keys = r.keys(f"session:{session_id}:*")
print(f"{len(keys)} chunk(s) in this session")
raw = r.hgetall(keys[0])
vector = vs.convert_vector({"embedding": raw[b"embedding"]})
print("Vector length:", len(vector)) # expect 1536
print("First 8 dims:", [round(v, 5) for v in vector[:8]])
print("Chunk text:", raw[b"text"][:120])
# Results for execution
uv run python -m src.redismanualvectorization.raw_vector_check
24 chunk(s) in this session
Vector length: 1536
First 8 dims: [-0.01327, -0.06799, 0.00346, 0.01323, -0.01469, 0.0217, -0.01146, 0.05652]
Chunk text: b'<td>Lumen Electric Utility</td>\n<td>Bill Payment</td>\n<td>-$24.03</td>\n<td>$7,265.31</td>\n</tr>\n<tr>\n<td>02/14/2026</td>'
krishnansriram@mac RedisManualVectorization % uv run python -m src.redismanualvectorization.main \
--session demo1 \
--query "What's the overdraft protection fee?"
Q: What's the overdraft protection fee?
A: The overdraft protection transfer fee is $10.00 per occurrence.
Sources:
- sample_bank_statement.pdf (chunk 7): #### Important Account Disclosures ##### Overdraft Protection If a transaction is presented that ...
- sample_bank_statement.pdf (chunk 9): ##### Monthly Maintenance Fee A $12.00 monthly maintenance fee applies unless one of the following ...
- sample_bank_statement.pdf (chunk 8): ##### Interest Rate & Annual Percentage Yield This account earns interest at a variable rate, curre...
- sample_bank_statement.pdf (chunk 3): <td>-$10.44</td> <td>$8,096.52</td> </tr> <tr> <td>02/07/2026</td> <td>Greenfield Grocers</td> <td>D...
krishnansriram@mac RedisManualVectorization % uv run python -m src.redismanualvectorization.main \
--session demo2 \
--query "What's the overdraft protection fee?"
Q: What's the overdraft protection fee?
A: I don't know — no relevant content about an overdraft protection fee was found in the uploaded files.
2. ingest_node — session_id вновь подключается к метаданным
Каждый фрагмент должен содержать ключ сессии (или арендатора), который позже используется для фильтрации. Потеря метаданных при загрузке приводит к утечкам информации.
3. retrieve_node — явная фильтрация плюс соблюдение правил индекса
Применяйте фильтрацию по сессии даже в том случае, если имя индекса указано для конкретной сессии. Такой подход надежнее оптимистичного изоляционирования.
5. Зависимости — прямые импорты дают прямые записи
Укажите конкретные версии клиента Redis и инструментов интеграции с векторными данными. Косвенные обновления ранее приводили к сбоям в типах полей индекса.
Проверка сохранённых данных
1. Какие индексы существуют
Список индексов формируется после развертывания; неудачные попытки создания остаются незамеченными до первого запроса с пустым результатом.
2. Схема
Убедитесь, что размерность векторов, текстовые поля и поля тегов соответствуют коду.
3. Список записей без вывода необработанных векторов
4. Полная метаинформация о записи
Визуальное просмотрение вектора — декодирование чисел с плавающей точкой при отладке несоответствий размерностей
Ограничения даже при использовании управляемого Redis
Вам всё равно понадобятся резервные копии, механизмы аутентификации, ограничения на объём памяти и способ удаления данных по окончании сессии. Механизмы сохранения данных решают проблему перезагрузок, но не создают системы управления.
Рассматривайте памятную версию данных как учебный инструмент, а Redis — как стандарт для любого совместного или многозапросного использования одной и той же графовой структуры.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Добавьте тест на проверку работоспособности, который загружает две сессии, извлекает данные из каждой и проверяет отсутствие взаимного влияния. Запускайте его против Redis в CI с временным контейнером, чтобы ошибки никогда не попадали в общие среды.
Функция сохранения также влияет на способы возникновения сбоев: частичная обработка данных может привести к появлению «орфанских» записей. Убедитесь, что операции добавления/обновления являются идемпотентными по идентификаторам блоков, а также предусмотрите задачу переиндексации для воссоздания сессии на основе исходных документов.
Для локальной разработки храните механизм работы в памяти под управлением флага среды, чтобы инженерам не приходилось запускать Redis для редактирования промптов. Для совместной стадии тестирования полностью запретите использование пути в памяти.
Измеряйте задержку получения данных на уровне p95 до и после переноса в Redis. Даже корректная функция сохранения, но в три раза медленнее, заставит людей обращаться к небезопасным ускорениям.
При завершении работы сессии необходимо удалять записи по фильтру, а не опустошать базу данных. В руководствах по эксплуатации должны приводиться точные команды CLI/FT.DROP или delete-query с примерами их использования.
Когда несколько экземпляров приложения записывают данные одновременно, выбирайте такую структуру индекса, которая позволяет обрабатывать одновременные операции добавления/обновления, а при шардинге — соблюдайте ограничения хеш-тегов в Redis Cluster.
Для поддержки записывайте имя индекса и фильтр сессии при каждом запросе к данным. Пустые результаты часто свидетельствуют о неправильном индексе или фильтре, а не о сбое модели.
Механизм сохранения также влияет на способы возникновения сбоев: частичная обработка данных может привести к появлению «орфанских» записей. Используйте операции добавления/обновления с гарантией идемпотентности по идентификаторам блоков и предусмотрите задачу пересоздания индекса на основе исходных документов.
Для локальной разработки храните объекты в оперативной памяти под управлением флага среды, чтобы инженерам не приходилось запускать Redis для редактирования данных. Для совместной стадии тестирования полностью запретите использование пути в оперативной памяти.
Измеряйте задержку запросов на уровне p95 до и после перехода на Redis. Даже корректный механизм сохранения, работающий в три раза медленнее, заставит людей прибегать к небезопасным ускорениям.
При закрытии сессии необходимо удалять данные по фильтру, а не опустошать всю базу данных. В руководствах по эксплуатации должны приводиться точные команды CLI/FT.DROP или запросы к удаляемым данным с примерами их использования.
Когда несколько экземпляров приложения записывают данные одновременно, выбирайте такую структуру индекса, которая поддерживает одновременные операции добавления/обновления, а при шардинге учитывайте ограничения хеш-тегов Redis Cluster.
Для отладки записывайте имя индекса и параметры фильтра сессии при каждом запросе к данным. Пустые результаты часто свидетельствуют о неправильном индексе или фильтре, а не об ошибке модели.
Функция сохранения данных также влияет на возможные сбои: частичная обработка данных может привести к появлению «орфанских» записей. Сделайте операции добавления/обновления идемпотентными по идентификаторам блоков и предусмотрите задачу пересоздания индекса на основе исходных документов.
Для локальной разработки храните механизм работы в памяти под управлением флага среды, чтобы инженерам не приходилось запускать Redis для редактирования сообщений. Для совместной стадии тестирования полностью запретите использование пути в памяти.
Измеряйте задержку запросов на уровне p95 до и после перехода на Redis. Даже корректная функция сохранения данных, работающая в три раза медленнее, заставит людей возвращаться к небезопасным ускорениям.
При завершении сессии необходимо использовать метод удаления по фильтру, а не очистку базы данных. Руководства по эксплуатации должны содержать точные команды CLI/FT.DROP или запросы на удаление с примерами.
Когда несколько экземпляров приложения записывают данные одновременно, следует выбрать такую структуру индекса, которая позволяет выполнять одновременные операции добавления/обновления, а при шардинге — соблюдать ограничения хеш-тегов в Redis Cluster.
Для облегчения диагностики необходимо записывать имя индекса и параметры фильтрации сессии при каждом запросе к данным. Пустые результаты часто свидетельствуют об ошибке индекса или фильтра, а не о сбое самой модели.
Постоянное хранение данных также влияет на возможные сбои: частичная обработка данных может привести к появлению «орфанских» записей. Операции добавления/обновления должны быть идемпотентными по идентификаторам блоков, а также должна существовать задача пересоздания индекса на основе исходных документов.