Apache Lucene'yi temel alan açık kaynaklı bir arama ve analiz motorudur. Elasticsearch'ü kullanarak değişiklik verileri yakalama (CDC) verileri üzerine uygulamalar oluştururken, sistemi bir dizindeki mevcut belgelerde sık sık yapılan güncellemeleri veya değişiklikleri yönetecek şekilde tasarlamak isteyeceksiniz. Elasticsearch, Bu blogda, tam güncellemeler, kısmi güncellemeler ve komut dosyasıyla yazılmış güncellemeler dahil olmak üzere güncellemeler için mevcut olan farklı seçenekleri inceleyeceğiz. Ayrıca bir belgeyi değiştirirken neler olduğunu ve güncellemelerin sıklığının sistemdeki CPU kullanımını nasıl etkilediğini de tartışacağız. Elasticsearch'te Sık Güncellenen Örnek Uygulama kullanım örneklerini daha iyi anlamak için Netflix gibi bir video yayın hizmetine yönelik arama uygulamasına bakalım. Bir kullanıcı bir diziyi, yani "siyasi gerilim"i aradığında, anahtar kelimelere ve diğer meta verilere dayalı bir dizi alakalı sonuçla karşılaşır. Sık sık güncellenen “House of Cards” adlı gösterinin Elasticsearch'teki örnek belgesine bakalım: { "name": "House of Cards", "description": "Frank Underwood is a Democrat appointed as the Secretary of State. Along with his wife, he sets out on a quest to seek revenge from the people who betrayed him while successfully rising to supremacy.", "genres": ["drama", "thriller"], "views": 100, } Arama, Elasticsearch'te ve tam metin arama alanları olarak kullanacak şekilde yapılandırılabilir. Başlık başına görüntüleme sayısını saklayan alanı, içeriği artırmak ve daha popüler programları daha üst sıralara çıkarmak için kullanılabilir. Kullanıcı bir programın veya filmin bir bölümünü her izlediğinde alanı artırılır. name description views views Bu arama yapılandırmasını ölçeğindeki bir uygulamada kullanırken, gerçekleştirilen güncelleme sayısı, göre kolaylıkla dakika başına milyonları aşabilir. Rapora göre kullanıcılar Ocak'tan Temmuz'a kadar yaklaşık 100 milyar saat içerik izledi. Bölüm veya film başına ortalama izlenme süresinin 15 dakika olduğu varsayıldığında, dakika başına izlenme sayısı ortalama 1,3 milyona ulaşıyor. Yukarıda belirtilen arama yapılandırmasıyla her görünüm, milyon ölçeğinde bir güncelleme gerektirecektir. Netflix Netflix Etkileşim Raporu'na Birçok arama ve analiz uygulaması, özellikle CDC verileri üzerine oluşturulduklarında sık sık güncellemeler yaşayabilir. Elasticsearch'te güncellemeler gerçekleştirme Aşağıdaki kodla Elasticsearch'te nasıl güncelleme yapılacağına dair genel bir örneği inceleyelim: - from elasticsearch import Elasticsearch # Connect to your Elasticsearch instance es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID you want to update index_name = 'movies' document_id = 'your_document_id' # Retrieve the current document to get the current 'views' value try: current_doc = es.get(index=index_name, id=document_id) current_views = current_doc['_source']['views'] except Exception as e: print(f"Error retrieving current document: {e}") current_views = 0 # Set a default value if there's an error # Define the update body to increment 'views' by 1 update_body = { "doc": { "views": current_views + 1 # Increment 'views' by 1 } } # Perform the update try: es.update(index=index_name, id=document_id, body=update_body) print("Document updated successfully!") except Exception as e: print(f"Error updating document: {e}") Elasticsearch'te Tam Güncellemeler ve Kısmi Güncellemeler Elasticsearch'te bir güncelleme gerçekleştirirken, mevcut bir belgeyi değiştirmek için veya bir belgede kısmi güncelleme yapmak için kullanabilirsiniz. indeks API'sini güncelleme API'sini Dizin API'si belgenin tamamını alır, belgede değişiklikler yapar ve ardından belgeyi yeniden dizine ekler. Güncelleme API'si ile belgenin tamamı yerine değiştirmek istediğiniz alanları göndermeniz yeterlidir. Bu yine de belgenin yeniden indekslenmesine neden olur ancak ağ üzerinden gönderilen veri miktarını en aza indirir. Güncelleme API'si özellikle belge boyutunun büyük olduğu ve belgenin tamamını ağ üzerinden göndermenin zaman alıcı olacağı durumlarda kullanışlıdır. Python kodunu kullanarak hem indeks API'sinin hem de güncelleme API'sinin nasıl çalıştığını görelim. Elasticsearch'teki indeks API'sini kullanarak tam güncellemeler from elasticsearch import Elasticsearch # Connect to Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID index_name = "your_index" document_id = "1" # Retrieve the existing document existing_document = es.get(index=index_name, id=document_id) # Make your changes to the document existing_document["_source"]["field1"] = "new_value1" existing_document["_source"]["field2"] = "new_value2" # Call the index API to perform the full update es.index(index=index_name, id=document_id, body=existing_document["_source"]) Yukarıdaki kodda görebileceğiniz gibi, dizin API'si Elasticsearch'e iki ayrı çağrı gerektirir, bu da kümenizde daha yavaş performansa ve daha fazla yüke neden olabilir. Elasticsearch'teki güncelleme API'sini kullanan kısmi güncellemeler Kısmi güncellemeler dahili olarak kullanır, ancak daha iyi performans için yalnızca tek bir ağ çağrısı gerektirecek şekilde yapılandırılmışlardır. reindex API'sini from elasticsearch import Elasticsearch # Connect to Elasticsearch es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID index_name = "your_index" document_id = "1" # Specify the fields to be updated update_fields = { "field1": "new_value1", "field2": "new_value2" } # Use the update API to perform a partial update es.update(index=index_name, id=document_id, body={"doc": update_fields}) Görüntüleme sayısını güncellemek için Elasticsearch'teki güncelleme API'sini kullanabilirsiniz ancak güncelleme API'si tek başına görüntüleme sayısını önceki değere göre artırmak için kullanılamaz. Bunun nedeni, yeni görüntüleme sayısı değerini ayarlamak için eski görüntüleme sayısına ihtiyacımız olmasıdır. Güçlü bir kodlama dili olan Painless'ı kullanarak bunu nasıl düzeltebileceğimizi görelim. Elasticsearch'te Painless komut dosyalarını kullanan kısmi güncellemeler Elasticsearch için tasarlanmış bir kodlama dilidir ve sorgu ve toplama hesaplamaları, karmaşık koşullar, veri dönüşümleri ve daha fazlası için kullanılabilir. Painless ayrıca karmaşık mantığa dayalı olarak belgeleri değiştirmek için güncelleme sorgularında komut dosyalarının kullanılmasına da olanak tanır. Painless, Aşağıdaki örnekte, tek bir API çağrısında güncelleme gerçekleştirmek ve eski görüntüleme sayısının değerine göre yeni görüntüleme sayısını artırmak için Painless komut dosyasını kullanıyoruz. from elasticsearch import Elasticsearch # Connect to your Elasticsearch instance es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID you want to update index_name = 'movies' document_id = 'your_document_id' # Define the Painless script for the update update_script = { "script": { "lang": "painless", "source": "ctx._source.views += 1" # Increment 'views' by 1 } } # Perform the update using the Painless script try: es.update(index=index_name, id=document_id, body=update_script) print("Document updated successfully!") except Exception as e: print(f"Error updating document: {e}") Painless betiğinin anlaşılması oldukça sezgiseldir; her belge için görüntüleme sayısını 1 oranında artırmak yeterlidir. Elasticsearch'te Yuvalanmış Bir Nesneyi Güncelleme Elasticsearch'teki nesne dizilerinin tek bir ana belge içinde ayrı belgeler olarak indekslenmesine olanak tanıyan bir veri yapısıdır. İç içe geçmiş nesneler, nesnelerin içindeki nesneler gibi, doğal olarak iç içe geçmiş bir yapı oluşturan karmaşık verilerle uğraşırken kullanışlıdır. Tipik bir Elasticsearch belgesinde, nesne dizileri düzleştirilir ancak iç içe geçmiş veri türünün kullanılması, dizideki her nesnenin bağımsız olarak indekslenmesine ve sorgulanmasına olanak tanır. iç içe geçmiş nesneler, Elasticsearch'te iç içe geçmiş nesneleri güncellemek için ağrısız komut dosyaları da kullanılabilir. from elasticsearch import Elasticsearch # Connect to your Elasticsearch instance es = Elasticsearch([{'host': 'localhost', 'port': 9200}]) # Index name and document ID for the example index_name = 'your_index' document_id = 'your_document_id' # Specify the nested field and the updated value nested_field = "nested_field_name" updated_value = "new_value" # Define the Painless script for the update update_script = { "script": { "lang": "painless", "source": "ctx._source.nested_field_name = params.updated_value", "params": { "updated_value": updated_value } } } # Perform the update using the Update API and the Painless script try: es.update(index=index_name, id=document_id, body=update_script) print("Nested object updated successfully!") except Exception as e: print(f"Error updating nested object: {e}") Elasticsearch'e Yeni Alan Ekleme Elasticsearch'te bir belgeye yeni bir alan eklemek, bir indeks işlemiyle gerçekleştirilebilir. Güncelleme API'sini kullanarak mevcut bir belgeyi yeni alanla kısmen güncelleyebilirsiniz. Dizinde dinamik eşleme etkinleştirildiğinde yeni bir alanın tanıtılması basittir. Bu alanı içeren bir belgeyi indekslemeniz yeterlidir; Elasticsearch otomatik olarak uygun eşlemeyi bulur ve yeni alanı eşlemeye ekler. Dizindeki dinamik eşleme devre dışı bırakıldığında, güncelleme eşleme API'sini kullanmanız gerekecektir. Film dizinine bir “kategori” alanı ekleyerek dizin eşlemesinin nasıl güncelleneceğine ilişkin bir örneği aşağıda görebilirsiniz. PUT /movies/_mapping { "properties": { "category": { "type": "keyword" } } } Elasticsearch Under the Hood'daki Güncellemeler Kod basit olsa da, veriler değişmez segmentlerde depolandığından, Elasticsearch bu güncellemeleri gerçekleştirmek için dahili olarak çok fazla ağır iş yapıyor. Sonuç olarak, Elasticsearch bir belgede kolayca yerinde güncelleme yapamaz. Güncelleme gerçekleştirmenin tek yolu, hangi API'nin kullanıldığına bakılmaksızın belgenin tamamını yeniden indekslemektir. Elasticsearch, Apache Lucene'yi temel olarak kullanıyor. Lucene endeksi bir veya daha fazla bölümden oluşur. Segment, genel endeksin bir alt kümesini temsil eden, bağımsız, değişmez bir dizin yapısıdır. Belgeler eklendiğinde veya güncellendiğinde, yeni Lucene segmentleri oluşturulur ve eski belgeler geçici olarak silinmek üzere işaretlenir. Zamanla yeni belgeler eklendikçe veya mevcut belgeler güncellendikçe birden fazla segment birikebilir. Endeks yapısını optimize etmek için Lucene periyodik olarak daha küçük segmentleri daha büyük segmentlerle birleştirir. Güncellemeler aslında Elasticsearch'e eklenenlerdir Her güncelleme işlemi bir yeniden indeksleme işlemi olduğundan, tüm güncellemeler esasen geçici silmelerle yapılan eklemelerdir. Bir güncellemeyi bir ekleme işlemi olarak ele almanın maliyet etkileri vardır. Bir yandan, verilerin geçici olarak silinmesi, eski verilerin bir süre daha tutulduğu ve endeksin depolama ve hafızasının şişirildiği anlamına gelir. Geçici silme, yeniden indeksleme ve çöp toplama işlemlerinin gerçekleştirilmesi de CPU'ya ağır bir yük getirir; bu yük, bu işlemlerin tüm kopyalarda tekrarlanmasıyla daha da kötüleşir. Ürününüz büyüdükçe ve verileriniz zamanla değiştikçe güncellemeler daha karmaşık hale gelebilir. Elasticsearch'ün performansını korumak için kümenizdeki parçaları, analizörleri ve belirteçleri güncellemeniz gerekir; bu da kümenin tamamının yeniden indekslenmesini gerektirir. Üretim uygulamaları için bu, yeni bir küme kurulmasını ve tüm verilerin taşınmasını gerektirecektir. Kümelerin taşınması hem zaman alıcı hem de hataya açık bir işlem olduğundan hafife alınacak bir işlem değildir. Elasticsearch'teki güncellemeler Elasticsearch'teki güncelleme işlemlerinin basitliği, sistemin altında gerçekleşen ağır operasyonel görevleri maskeleyebilir. Elasticsearch, her güncellemeyi bir ek olarak ele alır ve tüm belgenin yeniden oluşturulmasını ve yeniden indekslenmesini gerektirir. Sık güncelleme yapılan uygulamalar için bu, her dakika milyonlarca güncellemenin gerçekleştiği Netflix örneğinde gördüğümüz gibi hızla pahalı hale gelebilir. İş yükünüze gecikme katan kullanarak güncellemeleri toplu hale getirmenizi veya Elasticsearch'te sık güncellemelerle karşılaşıldığında alternatif çözümlere bakmanızı öneririz. toplu API Bulutta yerleşik bir arama ve analiz veritabanı olan Rockset, Elasticsearch'e değiştirilebilir bir alternatiftir. Değiştirilebilirliği ile popüler hale gelen bir anahtar-değer deposu olan üzerine inşa edilen Rockset, belgelerde yerinde güncellemeler yapabilir. Bu, belgenin tamamı yerine yalnızca bireysel alanların değerinin güncellenmesine ve yeniden dizine eklenmesine neden olur. RocksDB Güncelleme ağırlıklı iş yükleri için Elasticsearch ve Rockset'in performansını karşılaştırmak isterseniz, 300 $ krediyle başlatabilirsiniz. Rockset'in ücretsiz deneme sürümünü