Course-এর সূচি

17.3

Amazon OpenSearch Service

যেকোনো field ধরে search, আর DynamoDB, CloudWatch Logs ও Kinesis থেকে ডেটা আনার চেনা pipeline-গুলো।

16 মিনিট পড়া + Animation

টিপস: ডটেড-আন্ডারলাইন করা যেকোনো শব্দে ট্যাপ বা Hover করলে তার অর্থ দেখবে।

এই লেসন শেষে তুমি পারবে

  • বোঝাতে, কেন একটা search engine কয়েক millisecond-এ শব্দ, শব্দের অংশ আর বানান ভুলও খুঁজে পায়, যা একটা database পারে না: inverted index, analyser আর relevance score দিয়ে।
  • Amazon OpenSearch Service চেনাতে: Elasticsearch-এর একটা open-source fork, যেটা চলে managed domain হিসেবে (data node, shard, replica, Multi-AZ) বা OpenSearch Serverless হিসেবে (collection আর OCU), আর ওপরে থাকে OpenSearch Dashboards।
  • পরীক্ষার যেসব keyword OpenSearch-এর দিকে ইশারা করে (full-text search, log analytics, real-time application monitoring, Kibana) সেগুলো ধরতে, আর OpenSearch-কে আসল database-এর সঙ্গী হিসেবে ব্যবহার করতে, কখনো তার বদলে না।
  • IAM আর access policy, VPC access, fine-grained access control, Dashboards-এর জন্য Cognito বা SAML, at rest KMS আর in transit TLS দিয়ে একটা domain সুরক্ষিত করতে।
  • DynamoDB Streams, CloudWatch Logs আর Kinesis থেকে ডেটা আনার তিনটা pattern বানাতে, Lambda (real time) আর Firehose (near real time)-এর মধ্যে বাছতে, আর প্রতিটা ব্যর্থ হলে কী হয় বলতে।
  • ২০২৩–২৬-এর নতুন জিনিসগুলো ঠিক জায়গায় বসাতে: OpenSearch Ingestion, DynamoDB আর S3-এর সাথে zero-ETL, আর generative AI-এর জন্য vector search।

#Search engine লাগে কেন

#Database কোথায় দুর্বল

এ পর্যন্ত যত database দেখেছ, প্রত্যেকে দ্রুত খুঁজে পায় শুধু যে পথের জন্য তাকে বানানো হয়েছে সেই পথে:

  • DynamoDB উত্তর দেয় partition key (আর sort key) দিয়ে, নয়তো আগে থেকে বানিয়ে রাখা কোনো secondary index দিয়ে (লেসন ১৫.৫)। তাকে যদি বলো “যেসব product-এর বর্ণনায় কাতান আছে সব দাও”, তার হাতে থাকে শুধু একটা Scan, যেটা পুরো table পড়ে।
  • RDS আর Aurora-র column-এ B-tree index থাকে। WHERE id = 42 বা WHERE title LIKE 'metro%'-এ সেটা কাজ করে, কিন্তু WHERE body LIKE '%metro%'-এ না: যে pattern wildcard দিয়ে শুরু হয়, সে index কাজে লাগাতে পারে না, তাই database প্রতিটা সারি পড়ে। তার ওপর LIKE শুধু অক্ষর মেলায়: “floods” আর “flood” যে একই শব্দ, “kaatan” যে “katan”-এর বানান ভুল, বা হাজারটা মিলের মধ্যে কোনটা সবচেয়ে ভালো, কিছুই সে জানে না।

মানুষ search box-এ লেখে কথা বলার মতো করে: অর্ধেক শব্দ, ভুল বানান, যেকোনো ক্রমে শব্দ, আর আশা করে সবচেয়ে ভালো ফলটা আগে আসবে। এটা “এই key-এর সারিটা দাও”-এর থেকে একদম আলাদা সমস্যা, আর এর জন্য আলাদা data structure লাগে।

#Inverted index

Search engine সমস্যাটাকে উল্টো দিক থেকে ধরে। একটা document রাখার সময় তার লেখা যায় একটা analyser-এর ভেতর দিয়ে:

  1. Tokenise: লেখাটাকে শব্দে ভাঙে।
  2. Normalise: ছোট হাতের অক্ষর করে, accent সরায়, চাইলে খুব সাধারণ stop word (“the”, “in”) বাদ দেয়।
  3. Stem: শব্দকে তার মূলে নিয়ে যায়, ফলে “floods”, “flooded” আর “flooding” সবই হয়ে যায় “flood”।

এভাবে পাওয়া প্রতিটা term লেখা হয় একটা inverted index-এ: সব term-এর একটা সাজানো তালিকা, প্রতিটার পাশে কোন কোন document-এ (আর কোন অবস্থানে) সেটা আছে। Search এলে query-কেও একইভাবে analyse করা হয়, তারপর শুধু তার term-গুলো খোঁজা হয়; document দশটা হোক বা দশ হাজার কোটি, সময় লাগে সেই কয়েক millisecond।

এই খোঁজার ওপরে engine যোগ করে ব্যবহারকারী যা যা চায়:

  • শব্দের অংশ মেলানো আর autocomplete: একটা prefix থেকে সাজানো term-এর তালিকায় হাঁটা (“metr” → “metro”), বা শব্দের টুকরো (edge n-gram) index করে রাখা, যাতে টাইপ করতে করতেই সাজেশন আসে।
  • Fuzzy মেলানো: এক-দুই অক্ষর এদিক-ওদিক হলেও term মেনে নেওয়া (“criket” → “cricket”)।
  • Relevance অনুযায়ী সাজানো: প্রতিটা মিলকে BM25 দিয়ে score দেওয়া (যে শব্দ সব document মিলিয়ে বিরল, আর ছোট field-এ আছে, তার গুরুত্ব বেশি), আর সেরাটা আগে দেখানো।
  • Facet দিয়ে ছাঁকা আর aggregation: ফলের পাশে “শাড়ি (১২৪) · পাঞ্জাবি (৩৭) · ৫,০০০ টাকার নিচে (৬১)” এমন গোনা সংখ্যা, আর click করে করে ফল সরু করে আনার funnel। Notes একে বলেছে funnel filtering।
  • Highlight, সমার্থক শব্দ, geo search, আর বাংলাসহ অনেক ভাষার analyser।

Inverted index দিয়ে search-এর ল্যাব

একটা পত্রিকা ছয়টা শিরোনাম index করেছে। কিছু একটা খোঁজো (বা নিচের একটা বেছে নাও), শব্দ কীভাবে মিলবে ঠিক করো, তারপর Search চাপো: দেখো OpenSearch কোন term খোঁজে, কোন document কেন মেলে, আর SQL-এর LIKE scan হলে কী হতো।

Document-গুলো (শিরোনাম)

  1. doc ১Floods hit Sylhet tea gardens
  2. doc ২Dhaka metro rail adds new trains
  3. doc ৩Bangladesh wins cricket series in Chattogram
  4. doc ৪Flood warning for Sunamganj and Sylhet
  5. doc ৫New metro station opens in Uttara
  6. doc ৬Tea exports rise after a good harvest

Inverted index: term → document

add → ২bangladesh → ৩chattogram → ৩cricket → ৩dhaka → ২export → ৬flood → ১,৪garden → ১good → ৬harvest → ৬hit → ১metro → ২,৫new → ২,৫open → ৫rail → ২rise → ৬series → ৩station → ৫sunamganj → ৪sylhet → ১,৪tea → ১,৬train → ২uttara → ৫warning → ৪win → ৩

তোমার search

এগুলো চেষ্টা করো

শব্দ কীভাবে মিলবে

Query চালাতে “Search” চাপো।

#Elasticsearch থেকে OpenSearch

Elasticsearch (সাথে log জড়ো করার Logstash আর dashboard-এর Kibana, তিনটা মিলে ELK stack) এক দশক ধরে সবচেয়ে জনপ্রিয় open-source search engine ছিল, আর AWS সেটা চালাত Amazon Elasticsearch Service নামে। ২০২১-এর জানুয়ারিতে Elastic নতুন version-গুলো এমন license-এ নিয়ে গেল যেগুলো open source না। তখন AWS আর অন্যরা শেষ open-source version-গুলো (Elasticsearch 7.10.2 আর Kibana 7.10.2) fork করে বানাল OpenSearch আর OpenSearch Dashboards, Apache 2.0 license-এ। ২০২১-এর সেপ্টেম্বরে service-টার নাম বদলে হলো Amazon OpenSearch Service। ২০২৪ থেকে project-টা Linux Foundation-এর অধীনে OpenSearch Software Foundation-এর।

আজ তোমার জন্য এর মানে:

  • OpenSearch Service চালায় OpenSearch (1.x, 2.x আর 3.x version), আর এখনো পুরোনো Elasticsearch domain সমর্থন করে 7.10 পর্যন্ত, যেটা শেষ open-source release। অনেক পুরোনো version ২০২৫-এর নভেম্বরে standard support থেকে বেরিয়ে গেছে, এখন প্রতি instance-ঘণ্টায় একটা extended support fee লাগে, তাই পুরোনো domain upgrade করে ফেলো।
  • OpenSearch Dashboards হলো Kibana-র উত্তরসূরি। পুরোনো Elasticsearch domain-এ dashboard tool-টার নাম এখনো Kibana, এজন্যই পরীক্ষার প্রশ্নে এখনো লেখা থাকে “Kibana dashboard”: উত্তর OpenSearch Service।
  • Elasticsearch 7.10-এর API আর client বেশিরভাগই বদল ছাড়াই চলে, তাই পুরোনো ELK setup সরিয়ে আনা সাধারণত সহজ।

#একটা domain কীভাবে ডেটা রাখে আর দেয়

#Document, index, shard আর node

  • Document হলো একটা JSON object: একটা খবর, একটা product, একটা log line। প্রত্যেকটার একটা ID থাকে।
  • Index হলো একই ধরনের document-এর সংগ্রহ (news, products, payments-2026.10.30), সাথে একটা mapping, যেটা বলে কোন field কোন type (text, keyword, number, date, geo point, vector)। তুমি mapping না দিলে OpenSearch প্রথম document দেখে আন্দাজ করে নেয়, আর field সেই type-ই ধরে রাখে: প্রথমে সংখ্যা পাঠিয়ে পরে string পাঠালে পরের document ফেরত আসে।
  • একটা index ভাগ হয় কয়েকটা primary shard-এ, যাতে তার ডেটা আর কাজ কয়েকটা machine-এ ছড়িয়ে যায়। প্রতিটা primary-র থাকতে পারে replica shard: অন্য node-এ রাখা পুরো copy। লেখা যায় আগে primary-তে, তারপর replica-তে; আর search-এর উত্তর দিতে পারে যেকোনো copy, তাই replica বাড়ায় টিকে থাকার ক্ষমতা আর পড়ার ক্ষমতা দুটোই। Primary shard-এর সংখ্যা index বানানোর সময়েই ঠিক হয়ে যায় (বদলাতে split, shrink বা reindex লাগে); replica-র সংখ্যা যেকোনো সময় বদলানো যায়।
  • Domain হলো OpenSearch cluster-এর AWS-এর দেওয়া নাম: কয়েকটা data node (EC2 instance, যারা shard রাখে; এক domain-এ সর্বোচ্চ ১,০০২টা) আর চাইলে dedicated cluster manager node (আগের নাম “master” node; তিনটা রাখার পরামর্শ), যারা নিজেরা ডেটা রাখে না, cluster-এর হিসাব রাখে আর ঠিক করে কোন shard কোথায় থাকবে।
  • লেখা search-এ আসে একটা refresh-এর পরে, default-এ প্রতি ১ সেকেন্ডে। OpenSearch near real-time, সঙ্গে সঙ্গে না।

Cluster নিজের স্বাস্থ্য জানায় রং দিয়ে: green (প্রতিটা primary আর replica জায়গামতো আছে), yellow (সব primary আছে, কিন্তু কিছু replica নেই: ডেটা হারায়নি, তবে বাড়তি copy নেই), red (অন্তত একটা primary-র কোনো চালু copy নেই: ডেটার একটা অংশ পাওয়া যাচ্ছে না)।

Multi-AZ। OpenSearch Service node-গুলো দুই বা তিনটা Availability Zone-এ ছড়িয়ে দিতে পারে, আর shard-এর replica রাখে তার primary-র থেকে আলাদা AZ-এ, তাই একটা AZ বন্ধ হলেও কিছু হারায় না। Multi-AZ with Standby আরও এক ধাপ এগিয়ে: তিনটা AZ-এ node, যার একটা standby, কয়েক সেকেন্ডে দায়িত্ব নিয়ে নেয়, ৯৯.৯৯% availability-র SLA সহ। একটা domain থাকে একটা Region-এ; অন্য Region-এর জন্য cross-cluster replication বা snapshot ব্যবহার করো।

Backup। Service প্রতি ঘণ্টায় automated snapshot নেয়, আর ১৪ দিন রাখে, বিনা খরচে, এমন storage-এ যা তুমি দেখতে পাও না। অন্য domain বা Region-এ restore করতে চাইলে নিজের S3 bucket-এ manual snapshot নাও।

Domain-এর ভেতরে: shard, replica আর দুটো Availability Zone

একটা পত্রিকার search domain-এ দুটো AZ-এ দুটো data node। News index-এ দুটো primary shard (P0, P1), আর প্রতিটার একটা করে replica (R0, R1) রাখা অন্য node-এ।

পরিস্থিতি

লেখা আগে যায় primary shard-এ, তারপর অন্য AZ-এ তার replica-তে।

AZ a
AZ b
News siteখবর লেখে
পাঠকsearch box
Data node ১P0 · R1
Data node ২P1 · R0
doc ১০০১ index
ধাপ 1 / 4
1

Site একটা নতুন খবর পাঠায় JSON document হিসেবে, ID ১০০১। যেকোনো node request নিতে পারে; node ১ ID-টা hash করে shard বাছে, আর ১০০১ পড়ে shard 0-তে, যার primary এই node-এই।

#Query করা: Query DSL, SQL আর PPL

খোঁজার নিজস্ব উপায় হলো Query DSL: একটা JSON request, যাতে থাকে match (analyse করা full text), term (হুবহু মান), prefix, fuzzy, range, এগুলো জোড়া দিতে bool, আর গোনা, গড়, histogram-এর জন্য aggregation (প্রতিটা dashboard chart-এর ভিত্তি)।

OpenSearch Service-এর প্রতিটা domain-এ একটা SQL plugin-ও দেওয়া থাকে: _plugins/_sql endpoint-এ SELECT ... FROM payments WHERE ... পাঠাতে পারো, log-এর জন্য PPL (Piped Processing Language, source=payments | where status=500 | stats count() by host) ব্যবহার করতে পারো, আর JDBC driver দিয়ে BI tool জুড়তে পারো। কাজের জিনিস, তবে OpenSearch relational database না: transaction নেই, join সীমিত।

#প্রতিদিন বাড়তে থাকা log-এর জন্য storage tier

Log analytics-এর domain চিরকাল বাড়তেই থাকে, যদি না তুমি সামলাও। OpenSearch Service-এ তিনটা স্তর:

Tierকীকিসের জন্য
HotEBS volume বা local NVMe-সহ data node (আর OpenSearch Optimized instance, যারা একটা copy S3-এ রাখে)সাম্প্রতিক, প্রায়ই খোঁজা আর লেখা ডেটা
UltraWarmশুধু পড়ার index, রাখা S3-এ, UltraWarm node-এ cache হয়; প্রতি GB অনেক সস্তা, query ধীরগত কয়েক সপ্তাহ বা মাসের log
ColdS3-এ খুলে রাখা (detached) index, সবচেয়ে সস্তা; query-র আগে UltraWarm-এ attach করতে হয়কালেভদ্রে লাগে, audit-এর জন্য রাখা পুরোনো ইতিহাস

একটা Index State Management (ISM) policy index-গুলো পুরোনো হলে এক স্তর থেকে আরেক স্তরে সরায়, শেষে মুছে দেয়। এটা না থাকলে disk ভরে যায়, আর জায়গা ফুরালে cluster বাঁচাতে OpenSearch Service লেখা বন্ধ করে দেয়।

#চালানোর দুই উপায়: domain আর Serverless

Slide এদের বলে দুই mode: একটা managed cluster আর একটা serverless।

Managed domain (provisioned)OpenSearch Serverless
কী বানাওএকটা domain: instance type, node সংখ্যা, storage, AZ, cluster manager nodeএকটা collection, type search, time series বা vector search
CapacityNode আর storage তুমি মাপো আর বাড়াও (blue/green পরিবর্তন)OCU (OpenSearch Compute Unit, প্রতিটা 6 GiB memory) নিজে নিজে বাড়ে-কমে, indexing আর search-এর জন্য আলাদাভাবে, তোমার দেওয়া সর্বনিম্ন আর সর্বোচ্চের মধ্যে
StorageEBS / instance storage, UltraWarm, coldডেটা S3-এ, compute unit-গুলো cache করে
দামপ্রতি instance-ঘণ্টা আর storage (ছাড়ের জন্য Reserved Instance)প্রতি OCU-ঘণ্টা আর প্রতি GB-মাস storage
নিয়ন্ত্রণপুরো: plugin, version, shard সংখ্যা, tier, cross-cluster replicationসামান্য: shard AWS ঠিক করে, refresh প্রায় ১০ সেকেন্ড, কিছু API আর plugin নেই, অন্য Region বা অন্য account থেকে access নেই
কার জন্য ভালোস্থির, বড় বা খুব tune করা workload; যখন প্রতি GB খরচ গুরুত্বপূর্ণওঠানামা করা বা অজানা workload, নতুন project, OpenSearch চালানোর লোক নেই এমন team, generative AI-এর vector store

পরীক্ষার নিয়ম: “cluster সামলাতে চাই না, অনিশ্চিত বা মাঝে মাঝে আসা search বা log workload” → OpenSearch Serverless। “নির্দিষ্ট instance type, UltraWarm, নিজের plugin বা পুরো নিয়ন্ত্রণ চাই” → managed domain।

#Security

OpenSearch-এ থাকে ঠিক সেই ডেটা যা আক্রমণকারীর পছন্দ (user ID-তে ভরা log, payment event, ব্যক্তিগত তথ্য), আর ২০১৮–২০২০-এ হাজার হাজার নিজে চালানো Elasticsearch cluster ফাঁস হয়েছিল, কারণ সেগুলো password ছাড়াই internet-এ খোলা ছিল। Managed service তোমাকে কয়েক স্তরের সুরক্ষা দেয়:

  • Network। বাছো VPC access (domain তোমার private subnet-এ network interface পায়, security group পাহারা দেয়) অথবা policy দিয়ে পাহারা দেওয়া একটা public endpoint। বাছাইটা হয় তৈরির সময়, পরে আর বদলানো যায় না। Serverless-এ এই কাজ করে network policy (VPC endpoint বা public)।
  • কে API ডাকতে পারবে: IAM। একটা domain access policy (resource-based, S3 bucket policy-র মতো) আর identity-based IAM policy ঠিক করে কোন principal কোন index-এ কোন HTTP method ডাকতে পারবে; request SigV4 দিয়ে sign করা হয়। Public domain-এ IP-ভিত্তিক policy-ও সম্ভব, তবে দুর্বল।
  • ভেতরে কে কী দেখবে: fine-grained access control (FGAC)। OpenSearch-এর ভেতরের role দিয়ে access দেওয়া যায় index ধরে, document ধরে (শুধু একটা query-র সাথে মেলা সারি), আর field ধরে (ফোন নম্বরের মতো field লুকানো বা ঢেকে দেওয়া)। FGAC-এর জন্য লাগে HTTPS, encryption at rest আর node-to-node encryption।
  • Dashboards-এ কে login করবে। Amazon Cognito user pool (আর AWS credential-এর জন্য identity pool), অফিসের IdP-র সাথে SAML federation, অথবা HTTP basic authentication-সহ ভেতরের user database।
  • Encryption। At rest KMS দিয়ে (ডেটা, log, snapshot, swap); in transit TLS দিয়ে: client-এর জন্য HTTPS বাধ্যতামূলক, আর cluster-এর ভেতরে node-to-node encryption। Serverless সবসময় encrypt করে, AWS-এর বা তোমার নিজের KMS key দিয়ে (encryption policy)।
  • Audit। Configuration API call যায় CloudTrail-এ; কে কী খুঁজল, FGAC-এর audit log-এ লেখা থাকে।

#OpenSearch Dashboards আর log analytics

OpenSearch Dashboards হলো প্রতিটা domain আর collection-এর সাথে আসা web UI: কাঁচা event খোঁজা আর ছাঁকার জন্য Discover, visualisation আর dashboard (chart, map, table), alerting (monitor, যেটা ধরো প্রতি মিনিটে error ৫০ ছাড়ালেই SNS বা অন্য কিছু দিয়ে খবর দেয়), anomaly detection, observability (instrument করা application-এর log, trace আর metric একসাথে), Security Analytics (SIEM-এর ধাঁচে সন্দেহ ধরার নিয়ম) আর SQL ও PPL-এর জন্য Query Workbench।

এজন্যই notes বলছে OpenSearch ব্যবহার হয় application log, system tracking, VPC Flow Logs আর real-time monitoring-এ: ডেটা পৌঁছায় কয়েক সেকেন্ডে, যেকোনো field দিয়ে খোঁজা যায়, আর একই tool dashboard আঁকে, alert-ও দেয়। অনেক সাধারণ কাজ বাড়তি service ছাড়াই CloudWatch Logs Insights (লেসন ১৯.৪) দিয়ে হয়ে যায়; OpenSearch জেতে যখন অনেক source জুড়ে full-text search, কম খরচে লম্বা সময় রাখা, জটিল dashboard, বা অনেক team-এর নিজে নিজে ব্যবহারের tool দরকার।

#ডেটা ঢোকানো: তিনটা pattern

OpenSearch প্রায় সবসময় একটা copy। Slide সোজাসুজি বলে: OpenSearch-কে আরেকটা database-এর সঙ্গী হিসেবে ব্যবহার করাই সাধারণ। ডেটা লেখা হয় আসল জায়গায় (DynamoDB, Aurora, S3, CloudWatch Logs, একটা Kinesis stream), তারপর সেখান থেকে OpenSearch-এ যায়। নিজস্ব ingestion পথ হলো Amazon Data Firehose, AWS IoT Core (একটা rule action, যেটা device-এর message সোজা domain-এ পাঠায়), CloudWatch Logs subscription, আর ২০২৩ থেকে OpenSearch Ingestion। পরীক্ষার তিনটা চেনা pattern নিচে।

#Pattern ১: DynamoDB → DynamoDB Streams → Lambda → OpenSearch

“P-17 item-টা দাও”-তে DynamoDB অসাধারণ, আর “৮,০০০ টাকার নিচে লাল কাতান শাড়ি খোঁজো”-তে অচল। তাই:

  1. Application আগের মতোই DynamoDB table-এ লেখে (create, update, delete: CRUD)।
  2. DynamoDB Streams প্রতিটা item-এর পরিবর্তন লিখে রাখে, item ধরে ক্রম ঠিক রেখে, ২৪ ঘণ্টার জন্য (লেসন ১৫.৫)।
  3. একটা Lambda function event source mapping দিয়ে stream পড়ে, আর OpenSearch-এ মিলে যাওয়া document index করে, update করে বা মুছে দেয়; document ID হিসেবে নেয় item-এর key, যাতে retry হলে নতুন copy না বানিয়ে পুরোনোটার ওপর বসে।
  4. Application ব্যবহার করে দুটো API: item খোঁজার API (OpenSearch মিলে যাওয়া ID সাজিয়ে দেয়) আর item আনার API (DynamoDB key দিয়ে item-এর এখনকার অবস্থা দেয়)।

শেষ item DynamoDB থেকে আনাটা ইচ্ছাকৃত। Index মোটামুটি এক সেকেন্ড পিছিয়ে থাকে, আর sync ব্যর্থ হলে কোনো পরিবর্তন হারাতেও পারে; দাম, stock আর permission আসতে হবে আসল ডেটা থেকে।

DynamoDB-র ডেটায় search: Streams, Lambda আর OpenSearch

একটা online শাড়ির দোকান product রাখে DynamoDB-তে, যেটা শুধু key দিয়ে আনতে পারে। একটা stream আর একটা Lambda function প্রতিটা পরিবর্তন OpenSearch-এ copy করে, যাতে ক্রেতা যেকোনো field দিয়ে খুঁজতে পারে।

পরিস্থিতি

Table-এ প্রতিটা লেখা stream হয়ে OpenSearch-এ পৌঁছায়, মোটামুটি এক সেকেন্ডের মধ্যে।

Shop app
Products tableআসল ডেটা
Table stream২৪ ঘণ্টা থাকে
Sync function
Search domain
P-17 লেখো
ধাপ 1 / 4
1

দোকান একটা নতুন product যোগ করে: লাল টাঙ্গাইলের কাতান শাড়ি। App সেটা লেখে DynamoDB-তে, যেটা আসল ডেটার জায়গা। DynamoDB এটা খুঁজে পায় key (product ID) বা index দিয়ে, কিন্তু বর্ণনার ভেতরের “লাল কাতান” দিয়ে না।

#Pattern ২: CloudWatch Logs → subscription filter → Lambda বা Firehose

AWS-এর প্রতিটা service আর তোমার নিজের application CloudWatch Logs-এ log লিখতে পারে (লেসন ১৯.২)। একটা log group-এর ওপর subscription filter মিলে যাওয়া event (সবগুলো, বা শুধু ERROR-এর মতো pattern মেলা line) gzip করে একটা destination-এ পাঠায়। আজ একটা log group-এ সর্বোচ্চ পাঁচটা subscription filter রাখা যায় (পুরোনো material-এ লেখা দুটো)। OpenSearch-এ যাওয়ার destination দুটো:

Subscription filter → Lambda → OpenSearchSubscription filter → Firehose → OpenSearch
গতিReal time: log লেখার কয়েক সেকেন্ডের মধ্যে indexNear real time: Firehose buffer করে (OpenSearch-এর জন্য 1–100 MB বা ০–৯০০ সেকেন্ড)
Codeতোমার নিজের একটা function (console template থেকে বানিয়ে দিতে পারে)কিছু না: শুধু stream configure করো
হঠাৎ চাপFunction-এর concurrency throttle হতে পারে; invocation asynchronous, তাই Lambda throttle হওয়া event queue-তে রেখে ৬ ঘণ্টা পর্যন্ত আবার চেষ্টা করে: log দেরিতে পৌঁছায়Buffer চাপ সামলে নেয়; batch শুধু তাড়াতাড়ি ভরে
ব্যর্থতাব্যর্থ invocation Lambda আরও দুইবার চেষ্টা করে, তারপর event পাঠায় on-failure destination-এ, যদি দিয়ে থাকো; নইলে হারিয়ে যায়Retry duration ধরে চেষ্টা (default ৩০০ সেকেন্ড), তারপর ব্যর্থ document যায় S3 backup bucket-এ (AmazonOpenSearchService_failed/)
বাড়তিযেকোনো রূপান্তর, যেমন খুশিচাইলে Lambda transform, সব বা শুধু ব্যর্থ record-এর S3 backup

CloudWatch Logs থেকে OpenSearch: real time নাকি near real time

একটা wallet-এর payment API তার log লেখে CloudWatch Logs-এ। একটা subscription filter মিলে যাওয়া log event পাঠায় হয় একটা Lambda function-এ (real time), নয়তো একটা Firehose stream-এ (near real time)।

পরিস্থিতি

Subscription filter একটা function চালায়, যেটা কয়েক সেকেন্ডে event-গুলো index করে।

Payment API
CloudWatch Logs
Log shipperreal time
Log domain
log line
ধাপ 1 / 4
1

Payment API তার log group-এ log line লেখে, AWS-এর যেকোনো service যেমন পারে।

#Pattern ৩: Kinesis Data Streams → Firehose বা Lambda → OpenSearch

Event যখন আগে থেকেই Kinesis Data Streams দিয়ে চলছে (লেসন ১৩.৫), তখনো পথ দুটো:

  • KDS → Firehose → OpenSearch (near real time)। Firehose একজন consumer হিসেবে stream পড়ে, চাইলে ডেটা রূপান্তরের জন্য একটা Lambda function চালায় (field ঢাকা, format বদলানো, তথ্য যোগ), buffer করে, তারপর bulk load করে। Function যেগুলোকে failed বলে, সেগুলো যায় S3-এর processing-failed/-এ; OpenSearch যেগুলো ফেরত দেয়, সেগুলো যায় AmazonOpenSearchService_failed/-এ (লেসন ১৩.৬)।
  • KDS → Lambda → OpenSearch (real time)। একটা Lambda event source mapping প্রতিটা shard পড়ে, আর তোমার code প্রায় এক সেকেন্ডের মধ্যে batch-টা index করে। সব নিয়ন্ত্রণ তোমার, আবার retry, duplicate আর বিষাক্ত (poison) record-ও তোমার মাথাব্যথা (retry-র সীমা, bisect on error আর on-failure destination ঠিক করো)।

Kinesis retention period পর্যন্ত record রেখে দেয় বলে, দুই পথেই fix-এর পরে replay করা যায়, আর অন্য consumer-রা (fraud ধরা, S3 archive) একই stream আলাদাভাবে পড়ে।

Kinesis থেকে OpenSearch: Firehose দিয়ে নাকি Lambda দিয়ে

একটা ride-sharing app trip event পাঠায় Kinesis Data Streams-এ। Support staff OpenSearch-এ trip খোঁজে। সেখানে পৌঁছানোর দুই পথ: Firehose, চাইলে সাথে একটা transform function; নয়তো একটা Lambda consumer।

পরিস্থিতি

Near real time, consumer code নেই; একটা ছোট function প্রতিটা batch পরিষ্কার করে।

Ride apptrip event
Data stream
Transform
Firehose stream
Backup bucket
Trips domain
trip event
ধাপ 1 / 4
1

প্রতিটা trip শুরু, শেষ আর ভাড়া লেখা হয় data stream-এ, partition key হিসেবে trip ID।

#আরও কিছু পথ

  • OpenSearch Ingestion (২০২৩): একটা serverless, managed Data Prepper pipeline (Data Prepper হলো OpenSearch-এর open-source ডেটা সংগ্রাহক, এখনকার Logstash)। Source-এর মধ্যে আছে HTTP আর trace collector, S3 (SQS notification-সহ), DynamoDB, DocumentDB, Kinesis Data Streams আর Kafka/MSK; সে ডেটা ছাঁকে, তথ্য যোগ করে, আর domain বা collection-এ পাঠায়। Bill হয় প্রতি Ingestion OCU-ঘণ্টায়; টাকা বাঁচাতে pipeline থামিয়ে রাখা যায়।
  • S3, CloudWatch Logs আর Security Lake-এর সাথে zero-ETL (direct query, ২০২৪): log যেখানে আছে সেখানেই query করো, domain-এ load না করেই, আর শুধু প্রায়ই খোঁজা অংশটুকু দ্রুত করে নাও। কালেভদ্রে খোঁজা archive-এর জন্য ভালো।
  • AWS IoT Core-এর rule action, Logstash বা Fluent Bit agent, অথবা _bulk API দিয়ে নিজের code।

শব্দ ছাড়াও OpenSearch vector index করতে পারে: সংখ্যার তালিকা, যা একটা embedding model বানায় কোনো লেখা বা ছবির অর্থ ধরে রাখতে। একটা k-NN (k-nearest neighbours) query সেই document-গুলো ফেরত দেয় যাদের vector query-র vector-এর সবচেয়ে কাছে, ফলে “cheap flights to Cox’s Bazar” খুঁজে পেতে পারে “Budget trips to the sea beach” শিরোনামের একটা লেখা, যেখানে একটা শব্দও মেলে না। এটাই semantic search, আর এটা RAG (retrieval-augmented generation)-এর খুঁজে আনার ধাপ: প্রাসঙ্গিক অংশ খুঁজে বের করো, তারপর প্রশ্নের সাথে সেগুলো একটা LLM-কে দাও।

Domain-এ থাকে k-NN plugin; Serverless-এ আছে আলাদা vector search collection type (search আর time series type-এ k-NN index চলে না)। Amazon Bedrock Knowledge Bases তোমার হয়ে একটা OpenSearch Serverless vector collection বানিয়ে ব্যবহার করতে পারে (লেসন ১৮.২)। পরীক্ষার ইঙ্গিত: “vector database / generative AI application-এর embedding রাখতে হবে, fully managed” → OpenSearch Serverless (vector search) একটা চেনা উত্তর।

#কোথায় গোলমাল হয়

লক্ষণসম্ভাব্য কারণসমাধান
লেখা “blocked” error দিয়ে ব্যর্থ; search চলছেDisk ভর্তি: ISM policy নেই, log কখনো মোছা হয়নিISM: rollover, UltraWarm/cold-এ সরানো, মোছা; storage বাড়ানো; free storage space-এর ওপর alarm
Cluster yellowReplica বসানো যাচ্ছে না (node বা AZ হারানো, replica-র তুলনায় node কম)Node বদলানোর অপেক্ষা; প্রতি AZ-এ যথেষ্ট node; Multi-AZ
Cluster red, আংশিক ফলএকটা primary shard-এর কোনো copy নেই: replica শূন্য আর একটা node বিকলSnapshot থেকে restore; production-এ সবসময় অন্তত একটা replica
“Too many requests” (429)লেখা বা search-এর thread pool ভর্তি: অনেক ছোট request, node কমবড় batch-এ _bulk, প্রতি node-এ কম shard, scale out; backoff দিয়ে retry
কিছু document ফেরত, বাকি index হলোMapping-এর গোলমাল (একটা field-এর type বদলে গেছে)Mapping বা index template আগে থেকে ঠিক করা; transform-এ ডেটা পরিষ্কার
মোছা item তবু search-এ আসেSync function REMOVE event উপেক্ষা করেপ্রতিটা event type সামলাও; শেষ ডেটা আনো আসল জায়গা থেকে
Search index কয়েক ঘণ্টা পিছিয়েLambda throttle বা একটা বিষাক্ত batch-এ আটকে; stream record-এর মেয়াদ ফুরাচ্ছেConcurrency, retry-র সীমা, bisect, on-failure destination, iterator age-এর alarm; নয়তো Firehose / zero-ETL
Domain internet থেকে ঢোকা যায়খোলা access policy-সহ public endpointVPC access, কড়া domain access policy, FGAC
অল্প ডেটায় বিশাল খরচপুরোনো log রাখা অতিরিক্ত বড় hot tier; বেশি replica; অলস বড় clusterTier আর ISM; মাপমতো করা; ওঠানামা করা load-এ Serverless

#System design-এ OpenSearch

  • এটা দ্বিতীয় ভান্ডার। আসল ডেটা রাখো DynamoDB, Aurora বা S3-এ, আর OpenSearch এমনভাবে রাখো যাতে সেখান থেকে আবার বানানো যায়। Index হারালে বা নষ্ট হলে আবার index করো; কখনো তা থেকে order বা টাকা নিও না।
  • Search box, log analytics, observability, security analytics, vector search: এগুলোই তার কাজ। Transaction না (Aurora), যেকোনো মাপে key দিয়ে খোঁজা না (DynamoDB), বছরের পর বছরের ডেটায় SQL report না (Redshift), S3-এর file-এ মাঝে মাঝে SQL না (Athena)। ব্যবসার dashboard-এর জন্য এটা QuickSight-এর সাথেও জোড়া যায় (লেসন ১৭.৫)।
  • Ingestion-এর পথ বাছো দেরি আর code দেখে: Firehose (near real time, code নেই), Lambda (real time, তোমার code), OpenSearch Ingestion / zero-ETL (managed, code না লিখে configure)।
  • বাড়ার জন্য পরিকল্পনা করো: shard-এর মাপ মোটামুটি 10–50 GB, অন্তত একটা replica, দুই বা তিনটা AZ, production-এ dedicated cluster manager node, log-এর জন্য tier।
প্রশ্নে লেখা থাকে…উত্তর
DynamoDB item যেকোনো attribute দিয়ে, শব্দের অংশ দিয়ে খোঁজোDynamoDB Streams → Lambda → OpenSearch (বা zero-ETL)
CloudWatch Logs থেকে real-time log analyticsSubscription filter → Lambda → OpenSearch
Near real-time, code নেই, CloudWatch Logs বা Kinesis থেকেFirehose → OpenSearch
Kibana, ELK, নিজে চালানো Elasticsearch সরিয়ে আনাOpenSearch Service
Log খোঁজার dashboard, log pattern-এ alertOpenSearch Dashboards
Cluster সামলানো ছাড়া search, অনিশ্চিত loadOpenSearch Serverless
Generative AI app-এর vector storeOpenSearch Serverless vector search collection (k-NN)
User দেখবে শুধু নিজের document, বা PII field দেখবে নাFine-grained access control
অফিসের user দিয়ে Dashboards-এ loginCognito বা SAML

#নিজে করে দেখো

# 1. Create a small managed domain (2 data nodes in 2 AZs, encrypted, HTTPS only, FGAC on).
aws opensearch create-domain --domain-name news-example \
  --engine-version OpenSearch_2.19 \
  --cluster-config InstanceType=t3.small.search,InstanceCount=2,ZoneAwarenessEnabled=true,ZoneAwarenessConfig={AvailabilityZoneCount=2} \
  --ebs-options EBSEnabled=true,VolumeType=gp3,VolumeSize=10 \
  --encryption-at-rest-options Enabled=true \
  --node-to-node-encryption-options Enabled=true \
  --domain-endpoint-options EnforceHTTPS=true \
  --advanced-security-options 'Enabled=true,InternalUserDatabaseEnabled=true,MasterUserOptions={MasterUserName=admin,MasterUserPassword=Example-Passw0rd!}' \
  --access-policies '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::111122223333:root"},"Action":"es:ESHttp*","Resource":"arn:aws:es:ap-southeast-1:111122223333:domain/news-example/*"}]}'

# Wait until Processing is false and an endpoint appears (10–20 minutes).
aws opensearch describe-domain --domain-name news-example \
  --query 'DomainStatus.{Processing:Processing,Endpoint:Endpoint}'
{ "Processing": false, "Endpoint": "search-news-example-abc123.ap-southeast-1.es.amazonaws.com" }
E=https://search-news-example-abc123.ap-southeast-1.es.amazonaws.com
A='admin:Example-Passw0rd!'

# 2. Create an index with 2 primaries and 1 replica, and an explicit mapping.
curl -s -u "$A" -X PUT "$E/news" -H 'Content-Type: application/json' -d '{
  "settings": { "number_of_shards": 2, "number_of_replicas": 1 },
  "mappings": { "properties": {
    "title": { "type": "text" }, "district": { "type": "keyword" },
    "published": { "type": "date" } } } }'

# 3. Index two documents (bulk) and search with full text, prefix and fuzzy queries.
curl -s -u "$A" -X POST "$E/_bulk?refresh=true" -H 'Content-Type: application/x-ndjson' --data-binary $'
{"index":{"_index":"news","_id":"1001"}}
{"title":"Floods hit Sylhet tea gardens","district":"Sylhet","published":"2026-10-28"}
{"index":{"_index":"news","_id":"1002"}}
{"title":"Dhaka metro rail adds new trains","district":"Dhaka","published":"2026-10-29"}
'
curl -s -u "$A" "$E/news/_search?filter_path=hits.hits._id,hits.hits._score" \
  -H 'Content-Type: application/json' -d '{"query":{"match":{"title":"flood sylhet"}}}'
{"hits":{"hits":[{"_id":"1001","_score":1.3862942}]}}
curl -s -u "$A" "$E/news/_search?filter_path=hits.hits._id" -H 'Content-Type: application/json' \
  -d '{"query":{"prefix":{"title":"metr"}}}'                       # autocomplete-style → 1002
curl -s -u "$A" "$E/news/_search?filter_path=hits.hits._id" -H 'Content-Type: application/json' \
  -d '{"query":{"fuzzy":{"title":{"value":"gardns"}}}}'             # one typo → 1001

# 4. The same data through the SQL plugin, and the cluster's health and shard placement.
curl -s -u "$A" -X POST "$E/_plugins/_sql?format=txt" -H 'Content-Type: application/json' \
  -d '{"query":"SELECT district, COUNT(*) FROM news GROUP BY district"}'
curl -s -u "$A" "$E/_cluster/health?filter_path=status,number_of_nodes,unassigned_shards"
curl -s -u "$A" "$E/_cat/shards/news?v"
{"status":"green","number_of_nodes":2,"unassigned_shards":0}
index shard prirep state   docs node
news  0     p      STARTED    1 9c1f…
news  0     r      STARTED    1 4a7e…
news  1     p      STARTED    1 4a7e…
news  1     r      STARTED    1 9c1f…
# 5. Stream a CloudWatch Logs group into OpenSearch through Firehose (near real time).
#    (Firehose stream "logs-to-os-example" with the domain as destination already exists.)
aws logs put-subscription-filter --log-group-name /payments/api \
  --filter-name to-opensearch --filter-pattern 'ERROR' \
  --destination-arn arn:aws:firehose:ap-southeast-1:111122223333:deliverystream/logs-to-os-example \
  --role-arn arn:aws:iam::111122223333:role/CWLtoFirehoseRole
aws logs describe-subscription-filters --log-group-name /payments/api

# 6. OpenSearch Serverless: a search collection needs an encryption policy first,
#    then a network policy and a data access policy.
aws opensearchserverless create-security-policy --name products-enc --type encryption \
  --policy '{"Rules":[{"ResourceType":"collection","Resource":["collection/products-example"]}],"AWSOwnedKey":true}'
aws opensearchserverless create-security-policy --name products-net --type network \
  --policy '[{"Rules":[{"ResourceType":"collection","Resource":["collection/products-example"]}],"AllowFromPublic":true}]'
aws opensearchserverless create-collection --name products-example --type SEARCH
aws opensearchserverless batch-get-collection --names products-example \
  --query 'collectionDetails[0].{status:status,endpoint:collectionEndpoint}'

# 7. Clean up.
aws logs delete-subscription-filter --log-group-name /payments/api --filter-name to-opensearch
aws opensearchserverless delete-collection --id <collection-id>
aws opensearch delete-domain --domain-name news-example

Console-এও চেষ্টা করো: domain-এর OpenSearch Dashboards URL খোলো, news*-এর জন্য একটা index pattern বানাও, আর Discover-এ জেলা ধরে ছাঁকো; তারপর Query Workbench খুলে ওপরের SQL-টাই চালাও।

#সারসংক্ষেপ

মূল কথাগুলো

  • Search engine লেখা রাখে একটা inverted index-এ (term → document), analysis-এর পরে (শব্দে ভাঙা, ছোট হাতের করা, শব্দমূল), তাই কয়েক millisecond-এ খুঁজে পায় শব্দ, আংশিক মিল (prefix, autocomplete), বানান ভুল (fuzzy), আর relevance (BM25) ধরে সাজায়। LIKE '%x%'-কে প্রতিটা সারি পড়তে হয়, আর এসবের কিছুই সে বোঝে না।
  • Amazon OpenSearch Service = Amazon Elasticsearch Service-এর উত্তরসূরি (২০২১-এ নাম বদল), চালায় OpenSearch (Elasticsearch 7.10-এর fork) আর পুরোনো Elasticsearch, 7.10 পর্যন্ত। Kibana-র জায়গায় OpenSearch Dashboards। পরীক্ষার keyword: full-text search, log analytics, real-time application monitoring, Kibana, ELK।
  • DynamoDB-তে খোঁজো key বা index দিয়ে; OpenSearch-এ যেকোনো field, এমনকি আংশিক খোঁজা যায়। এটা আসল database-এর সঙ্গী, কখনো আসল ডেটার জায়গা না।
  • Domain = primary আর replica shard রাখা data node, চাইলে dedicated cluster manager node, Multi-AZ (২–৩টা AZ, ৯৯.৯৯%-এর জন্য Multi-AZ with Standby), প্রতি ঘণ্টায় automated snapshot। Green / yellow / red স্বাস্থ্য। Near real-time (refresh প্রায় ১ সেকেন্ড)।
  • Managed domain (node তুমি মাপো, পুরো নিয়ন্ত্রণ, UltraWarm আর cold tier, ISM) বনাম OpenSearch Serverless (collection: search, time series, vector; OCU indexing আর search আলাদাভাবে বাড়ায়-কমায়)।
  • SQL চলে ভেতরে বসানো SQL plugin দিয়ে (সাথে PPL), কিন্তু নিজের ভাষা Query DSL।
  • Security: VPC বা public access (তৈরির সময় ঠিক হয়), IAM আর domain access policy, fine-grained access control (index, document, field), Dashboards-এর জন্য Cognito বা SAML, at rest KMS, in transit আর node-to-node TLS।
  • Ingestion: Firehose, IoT Core, CloudWatch Logs, OpenSearch Ingestion। Pattern: DynamoDB → Streams → Lambda → OpenSearch (সেখানে খোঁজো, আনো DynamoDB থেকে); CloudWatch Logs → subscription filter → Lambda (real time) বা Firehose (near real time); KDS → Firehose (+ transform Lambda) বা KDS → Lambda।
  • মনে রাখার মতো ব্যর্থতা: disk ভর্তি হলে লেখা বন্ধ (ISM আর alarm দাও), replica শূন্য হলে একটা node গেলেই red cluster, REMOVE event উপেক্ষা করলে ভূত থেকে যায়, Lambda throttle হলে log দেরিতে আসে, Firehose ফেরত আসা document S3-এ রেখে দেয়।
  • ২০২৩ থেকে নতুন: OpenSearch Ingestion, DynamoDB থেকে zero-ETL আর S3 ও CloudWatch Logs-এ direct query, generative AI-এর vector store হিসেবে vector search (k-NN)।