सर्च सर्व्हिस आर्किटेक्चर: वाल्कीसह स्टँडअलोन फ्लास्क अॅप्लिकेशन

हा लेख आमची सर्च सर्व्हिस एका वेगळ्या सर्व्हरवर स्टँडअलोन फ्लास्क अॅप्लिकेशन म्हणून कशी चालते हे स्पष्ट करतो, ज्यात Valkey (Redis फोर्क) हाय-परफॉर्मन्स वेक्टर सर्च, कॅशिंग आणि ऑटोकंप्लीटसाठी वापरले जाते.

समस्या: सर्च परफॉर्मन्स आणि स्केलेबिलिटी

सर्च ऑपरेशन्स संगणकीयदृष्ट्या महागडी असतात:

  • फिल्टर काढणे: प्रत्येक क्वेरीविरुद्ध २,५००+ वाक्प्रचार जुळवणे

  • संबंधित शोध: ६५K क्वेरीजमध्ये समानता मोजणे

  • ऑटोकंप्लीट: ६५K क्वेरीजवर उपसर्ग जुळवणे

  • उत्पादन फिल्टरिंग: ५K+ उत्पादने एकाधिक निकषांद्वारे फिल्टर करणे

ही ऑपरेशन्स मुख्य वेब सर्व्हरवर चालवल्याने होते:

  • पृष्ठ लोड हळू होणे: सर्च इतर विनंत्या अडवते

  • मेमरी प्रेशर: एम्बेडिंग्जमुळे प्रचंड मेमरी फुटप्रिंट होतो

  • CPU संघर्ष: समानता गणना CPU-इंटेन्सिव्ह असते

  • स्केलिंग अडचण: सर्च स्वतंत्रपणे स्केल करता येत नाही

आम्हाला एक समर्पित सर्च सर्व्हिसची गरज आहे जी स्वतंत्रपणे स्केल करू शकते.

उपाय: स्टँडअलोन सर्च सर्व्हिस

आम्ही एक समर्पित सर्व्हरवर एक वेगळे फ्लास्क अॅप्लिकेशन चालवतो:

मुख्य वेब सर्व्हर
    ↓ HTTP API कॉल्स
सर्च सर्व्हिस
    ↓ Valkey क्वेरीज
Valkey सर्व्हर

ही आर्किटेक्चर पुरवते:

  • स्वतंत्र स्केलिंग: मुख्य वेब सर्व्हरवर परिणाम न करता सर्च सर्व्हिस स्केल करा

  • संसाधन वेगळेपणा: सर्च ऑपरेशन्सचा मुख्य वेब सर्व्हरवर परिणाम होत नाही

  • कॅशिंग: Valkey पुनरावृत्ती क्वेरींसाठी निकाल जलद कॅश करते

  • उच्च उपलब्धता: सर्च सर्व्हिस मुख्य वेब सर्व्हरवर परिणाम न करता रीस्टार्ट होऊ शकते

सर्च सर्व्हिस घटक

१. फिल्टर काढणे API

  • एंडपॉइंट: /api/extract_filters

  • उद्देश: नैसर्गिक भाषेतील क्वेरीजमधून स्ट्रक्चर्ड फिल्टर्स काढणे

  • उदाहरण:

GET /api/extract_filters?q=mini+pc+16gb+ram

प्रतिसाद:
{
  "Form Factor": "Mini PC",
  "Main Memory": "16"
}

अंमलबजावणी:

कॅशिंग: वाक्प्रचार मॅपिंग्ज Valkey मध्ये कॅश केली जातात (३०-दिवस TTL)

२. संबंधित शोध API

  • एंडपॉइंट: /api/related

  • उद्देश: वेक्टर सर्च वापरून शब्दार्थाने समान क्वेरीज शोधणे

  • उदाहरण:

POST /api/related
{
  "query": "mini pc",
  "limit": 10
}

प्रतिसाद:
{
  "related": [
    {"query": "small computer", "similarity": 0.92},
    {"query": "compact desktop", "similarity": 0.89},
    {"query": "mini pc 8gb", "similarity": 0.87}
  ]
}

अंमलबजावणी:

  • all-mpnet-base-v2 वापरून क्वेरी एम्बेड करा

  • जवळचे शेजारी शोधण्यासाठी Valkey RediSearch क्वेरी करा

  • समानतेनुसार क्रमवारी लावलेले शीर्ष N निकाल परत करा

कॅशिंग: निकाल Valkey मध्ये कॅश केले जातात (७-दिवस TTL)

३. ऑटोकंप्लीट API

  • एंडपॉइंट: /api/autocomplete

  • उद्देश: वापरकर्ता टाइप करत असताना क्वेरीज सुचवणे

  • उदाहरण:

GET /api/autocomplete?q=mini+p&limit=5

प्रतिसाद:
{
  "suggestions": [
    "mini pc",
    "mini pc 16gb",
    "mini pc 8gb ram",
    "mini pc fanless",
    "mini pc windows 11"
  ]
}

अंमलबजावणी:

  • उपसर्ग जुळवणीसह Valkey RediSearch क्वेरी करा

  • लोकप्रियतेनुसार क्रमवारी लावा (इम्प्रेशन + क्लिक स्कोअर)

  • शीर्ष N सूचना परत करा

कॅशिंग: ऑटोकंप्लीट इंडेक्स Valkey मध्ये (दररोज अपडेट केले जाते)

४. लोकप्रिय क्वेरीज API

  • एंडपॉइंट: /api/popular

  • उद्देश: सर्वात लोकप्रिय क्वेरीज मिळवा

  • उदाहरण:

GET /api/popular?limit=10

प्रतिसाद:
{
  "queries": [
    "mini pc",
    "thin client",
    "industrial pc",
    "all in one pc"
  ]
}

अंमलबजावणी:

  • Valkey किंवा JSON मधून क्वेरीज लोड करा

  • ट्रॅफिक स्कोअरनुसार क्रमवारी लावा (इम्प्रेशन्स + क्लिक्स)

  • शीर्ष N क्वेरीज परत करा

कॅशिंग: लोकप्रिय क्वेरीज Valkey मध्ये कॅश केल्या जातात (३०-दिवस TTL)

Valkey एकत्रीकरण

Valkey हा एक Redis फोर्क आहे जो पुरवतो:

  • वेक्टर सर्च: समानता शोधासाठी RediSearch मॉड्यूल

  • कॅशिंग: जलद इन-मेमरी की-व्हॅल्यू स्टोअर

  • ऑटोकंप्लीट: सॉर्टेड सेटसह उपसर्ग जुळवणे

  • स्थायित्व: टिकाऊपणासाठी AOF (Append-Only File)

RediSearch सह वेक्टर सर्च

आम्ही वेक्टर समानता शोधासाठी Valkey चा RediSearch मॉड्यूल वापरतो:

इंडेक्स निर्मिती:

client.ft("queries_idx").create_index([
    VectorField("embedding", "FLAT", {
        "TYPE": "FLOAT32",
        "DIM": 768,
        "DISTANCE_METRIC": "COSINE"
    }),
    TextField("query"),
    NumericField("score")
])

वेक्टर सर्च:

query_embedding = model.encode(query)
results = client.ft("queries_idx").search(
    Query("*=>[KNN 10 @embedding $vec AS score]")
    .sort_by("score")
    .return_fields("query", "score")
    .dialect(2),
    query_params={"vec": query_embedding.tobytes()}
)

हे कोसाइन समानतेनुसार 10 जवळचे शेजारी परत करते.

कॅशिंग धोरण

आम्ही Valkey मध्ये एकाधिक डेटा प्रकार कॅश करतो:

वाक्प्रचार मॅपिंग्ज (३०-दिवस TTL):

client.setex(
    "seo:phrase_mappings",
    30 * 24 * 3600,
    json.dumps(phrase_mappings)
)

संबंधित शोध (७-दिवस TTL):

cache_key = f"related:{query_hash}"
client.setex(cache_key, 7 * 24 * 3600, json.dumps(results))

लोकप्रिय क्वेरीज (३०-दिवस TTL):

client.setex(
    "seo:popular_queries",
    30 * 24 * 3600,
    json.dumps(popular_queries)
)

ऑटोकंप्लीट इंडेक्स (दररोज अपडेट केले जाते):

for query, score in queries:
    client.zadd("autocomplete:mini", {query: score})

सॉर्टेड सेटसह ऑटोकंप्लीट

आम्ही ऑटोकंप्लीटसाठी Valkey सॉर्टेड सेट वापरतो:

इंडेक्स स्ट्रक्चर:

autocomplete:m     → ["mini pc": 5000, "mini computer": 3000]
autocomplete:mi    → ["mini pc": 5000, "mini computer": 3000]
autocomplete:min   → ["mini pc": 5000, "mini computer": 3000]
autocomplete:mini  → ["mini pc": 5000, "mini computer": 3000]

उपसर्ग शोध:

prefix = "mini"
results = client.zrevrange(f"autocomplete:{prefix}", 0, 9, withscores=True)

हे "mini" ने सुरू होणाऱ्या शीर्ष 10 क्वेरीज, स्कोअरनुसार क्रमवारी लावून परत करते.

API संप्रेषण

मुख्य वेब सर्व्हर HTTP द्वारे सर्च सर्व्हिसला कॉल करतो:

फिल्टर काढणे

from app.shared.filter_service import extract_filters_from_query

filters = extract_filters_from_query("mini pc 16gb ram")
# आतून कॉल करते: GET SEARCH_SERVICE_URL/api/extract_filters?q=...

संबंधित शोध

import requests

response = requests.post(
    "SEARCH_SERVICE_URL/api/related",
    json={"query": "mini pc", "limit": 10},
    timeout=2
)
related = response.json()["related"]

ऑटोकंप्लीट

response = requests.get(
    "SEARCH_SERVICE_URL/api/autocomplete",
    params={"q": "mini p", "limit": 5},
    timeout=1
)
suggestions = response.json()["suggestions"]

त्रुटी हाताळणी आणि फॉलबॅक

मुख्य वेब सर्व्हर सर्च सर्व्हिस अपयशांना सुसह्यपणे हाताळतो:

try:
    filters = extract_filters_from_query(query)
except Exception as e:
    logger.error(f"Search service failed: {e}")
    filters = {}  # रिकाम्या फिल्टर्सकडे फॉलबॅक करा

हे सुनिश्चित करते की सर्च सर्व्हिस डाउन असली तरीही मुख्य वेब सर्व्हर कार्यरत राहते.


### नेटवर्क कॉन्फिगरेशन

सर्व सर्व्हर्स खाजगी नेटवर्कवर आहेत:

- **मुख्य वेब सर्व्हर**: सर्च सर्व्हिस आणि Valkey वर प्रवेश करू शकतो

- **सर्च सर्व्हिस**: Valkey वर प्रवेश करू शकतो

- **Valkey**: फक्त मुख्य वेब सर्व्हर आणि सर्च सर्व्हिसकडून प्रवेशयोग्य

सर्च सर्व्हिस किंवा Valkey वर बाह्य प्रवेश नाही.

## SEO पाईपलाइनसह एकत्रीकरण

सर्च सर्व्हिस SEO पाईपलाइनसह एकत्रित होते:

### चरण ११: Valkey कडे मायग्रेट करा

SEO पाईपलाइन डेटा Valkey मध्ये लोड करते:

```python
# क्वेरी एम्बेडिंग्ज लोड करा
for query, embedding in zip(queries, embeddings):
    client.hset(f"query:{query_hash}", mapping={
        "query": query,
        "embedding": embedding.tobytes(),
        "score": score
    })

# RediSearch इंडेक्स तयार करा
client.ft("queries_idx").create_index([...])

तपशीलांसाठी Valkey मायग्रेशन पहा.

क्वेरी लॉगिंग

सर्च सर्व्हिस SEO पाईपलाइनसाठी क्वेरीज लॉग करते:

log_entry = {
    "timestamp": datetime.now(timezone.utc).isoformat(),
    "query": query,
    "filters_extracted": filters,
    "results_count": len(results)
}
with open(SEO_LIVE_QUERIES_LOG, "a") as f:
    f.write(json.dumps(log_entry) + "\n")

हे लॉग चरण १d: लाइव्ह क्वेरीज मिळवा मध्ये परत फीड होतात.

संदर्भ

तांत्रिक संकल्पना

  • Valkey - अधिकृत वेबसाइट

  • Redis - अ