شعار زيفيرنت

كومة المعاملات الحديثة

التاريخ:

لطالما كانت قواعد بيانات المعاملات العنصر الأكثر أهمية في تصميم التطبيقات. لماذا؟ لأن قاعدة البيانات الثابتة هي بشكل عام نقطة الإنفاذ النهائية للصحة في عالم موزع فوضوي. بدونهم كنا ندفع مبالغ زائدة ونخفض التكلفة. سنفقد الركاب الذين يحاولون العودة إلى الوطن من المطار ، وسنفقد بعض العناصر في عربات التسوق الخاصة بنا. ستفقد حساباتنا عبر الإنترنت أو تتكرر أو تتلف وتصبح غير قابلة للتشغيل. 

في الواقع ، كانت قاعدة بيانات المعاملات (تسمى عمومًا OLTP - اختصارًا لمعالجة المعاملات عبر الإنترنت - قاعدة البيانات) مركزية للغاية في تطوير التطبيقات ، حيث استهلكت بمرور الوقت المزيد والمزيد من وظائف التطبيق. ومع ذلك ، أدخلت الخدمات المصغرة وبنيات التطبيقات الحديثة الأخرى تعقيدات جديدة في تصميم التطبيق: يحتاج المطورون إلى إدارة البيانات عبر الخدمات المختلفة وضمان الاتساق بينها ، مما أجبرهم على بناء آليات معقدة لمزامنة البيانات ومعالجتها داخل الشركة. 

وهكذا ، كصناعة ، نشهد وعيًا متزايدًا بأن ضمانات المعاملات مطلوبة خارج النموذج التقليدي. نحن نشاهد ملف ظهور أنظمة توسع ضمانات معاملات قوية تتجاوز قاعدة البيانات ، إلى التطبيقات الموزعة نفسها

لقد قمنا بتتبع هذه الحلول على مدى السنوات القليلة الماضية. بشكل عام ، يسعون جاهدين للسماح بإدارة المعاملات للحالة في تطبيق موزع كبير ، دون خلق تحديات للتوسع مع توفير بيئة برمجة حديثة. 

نجد هذه الحلول مقسمة تقريبًا إلى فئتين. فئة واحدة تنسيق سير العمل. هذا يضمن بشكل أساسي أن كتلة من التعليمات البرمجية ستعمل حتى الاكتمال ، حتى في مواجهة الفشل. لذلك يمكن استخدامه لغرض إدارة آلة الحالة الموزعة بشكل حتمي دون التزعزع. الفئة الثانية هي قاعدة بيانات + سير العمل، مما يوسع تصميم قاعدة بيانات OLTP التقليدية ، مما يسمح بتنفيذ تعليمات برمجية عشوائية لنفس الغرض. 

لا تزال هذه منطقة ناشئة للغاية ، وهناك الكثير من الالتباس حول التسمية ، وكيف يتم استخدام كل أداة في الممارسة العملية ، ومن يجب أن يستخدمها. للمساعدة في الحصول على فهم أفضل ، سألنا الممارسين من المؤسسات الهندسية الرائدة عن مجموعة المعاملات الخاصة بهم وكيف يفكرون في ثلاثة مفاهيم أساسية لأعباء العمل الخاصة بالمعاملات: حالة التطبيق ومنطق العمل وبيانات الأعمال. 

قبل فحص هذه المجموعات الجديدة ، على الرغم من ذلك ، إليك استطراد سريع شبه تقني للمساعدة في فهم كيفية وصولنا إلى هنا.

المعاملات والضمانات والتطبيقات الحديثة 

الإصدار التقريبي للغاية هو هذا: هناك مجموعة من المهام - المعاملات - التي تريد القيام بها كلها أو لا شيء منها. أي شيء بينهما (القيام به جزئيًا) سينتهي بحالة فاسدة. من الصعب ضمان ذلك اى شى في نظام موزع ، لكن قواعد البيانات تعمل بشكل جيد مع المعاملات. لذلك ، فإن أسهل طريقة للتعامل مع الضمانات في العديد من الأنظمة هي إجراء معاملات معظم الأشياء والسماح لقاعدة البيانات بمعالجتها.

التطبيقات الحديثة هي أنظمة موزعة كبيرة حيث يقوم الكثير من المستخدمين بأشياء كثيرة. لذا ، حتى الحفاظ على حالة التطبيق متسقة (مثل تتبع مكان وجود مستخدمين مختلفين في تدفق تسجيل المغادرة) يتحول إلى مشكلة معاملة موزعة. في البنى التقليدية المتجانسة ، كانت إدارة المعاملات باستخدام SQL مع قاعدة بيانات OLTP فعالة إلى حد ما. ولكن في العالم الجديد والمعقد للخدمات المصغرة التي تتفاعل من خلال واجهات برمجة التطبيقات عالية المستوى (مثل REST أو gRPC) ، أصبحت احتياجات المعاملات موزعة بطبيعتها. 

ومع ذلك ، فإن العديد من الشركات التي تقوم برحلة إلى الخدمات المصغرة لم تفعل الكثير لتوسيع ضمانات المعاملات القوية خارج قاعدة البيانات. ومن الناحية العملية ، هذا تقريبا دائما نعم. ولكن مع زيادة حجم التطبيقات ، تتزايد التناقضات في البيانات ، كما هو الحال مع الأخطاء الناتجة عن الأخطاء التي لم يتم تسويتها في بيانات الأعمال. والتي ، بالطبع ، يمكن أن تكون مشكلة كبيرة. هذا يفرض على مطوري التطبيقات التعامل مع مجموعة واسعة من سيناريوهات الفشل واستراتيجيات حل النزاعات ، ولضمان اتساق الحالة من خلال الخروج باستراتيجياتهم الخاصة من خلال أنماط معمارية مختلفة.

التعريفات

بيانات الأعمال ("البيانات") يشير إلى البيانات المهمة للأعمال المخزنة تقليديًا في قاعدة بيانات OLTP للاستمرار والمعالجة (على سبيل المثال ، معلومات ملف تعريف المستخدم مثل الاسم والعنوان ودرجة الائتمان وما إلى ذلك).

حالة التطبيق يشير إلى الحالة الحالية للنظام ؛ يتم تحديد حالة التطبيق من خلال القيمة المخزنة في نظام تخزين البيانات والخطوة التي يتم تنفيذ البرنامج بها في آلة ذات حالة محدودة (على سبيل المثال ، حالة الطلب ، مثل "الطلب المستلم" ، "فحص المخزون" ، "التحقق من الائتمان ، "تم شحنها").

منطق الأعمال يشير إلى جزء البرنامج الذي يتعامل مع كيفية عمل التطبيق فعليًا أو ما يفعله ، بدلاً من تفاصيل التنفيذ (على سبيل المثال ، "If user_income> $ 100K & credit_score> 650 mortgage_approved = TRUE").

لأغراض هذه المناقشة ، من المهم التمييز بين حالة التطبيق وبيانات الأعمال. على سبيل المثال ، معرفة أن العميل قد أدخل بطاقته الائتمانية ولكنه لم يسحب هو حالة التطبيق. البيانات الخاصة ببطاقة الائتمان والعناصر الموجودة في عربة التطبيق هي بيانات العمل. 

في التدفق النموذجي ، يأتي الطلب من الواجهة الأمامية ، ويتم مصادقته ، ثم يتم توجيهه عبر بوابة API أو GraphQL إلى نقطة النهاية ذات الصلة. 

يجب الآن على نقطة نهاية API الفردية هذه أن تنظم عشرات أو مئات الخدمات المصغرة لتسليم المعاملات التجارية إلى العميل النهائي. هذا هو المكان الذي يقوم فيه المطورون عادةً بتجميع كل شيء في كتل منطقية للأعمال ، ثم يستخدمون مجموعة من قوائم الانتظار وذاكرة التخزين المؤقت وآليات إعادة المحاولة المرمزة يدويًا للحصول على البيانات إلى قاعدة البيانات - ونأمل أن يتم الالتزام بها كمعاملة كاملة.

مع زيادة حجم التطبيق ، يزداد أيضًا تعقيد إدارة قوائم الانتظار وذاكرة التخزين المؤقت ، بالإضافة إلى عدد الحواف الحادة في منطق التسوية عند ظهور المشكلات. 

ظهور مكدسات المعاملات المتمحورة حول سير العمل والمرتكزة على قاعدة البيانات

حسنًا ، المعاملات مهمة. لم يكن برنامج LAMP الموجود في قاعدة البيانات كافياً للقياس. وهناك كرة شعر عملاقة من قوائم الانتظار ومنطق إعادة المحاولة هش للغاية. للتعامل مع هذا ، رأينا ، خلال السنوات القليلة الماضية ، ظهور حلول جديدة تعيد العقل إلى منطق المعاملات. يمكن تصنيفها تقريبًا إما كنهج تتمحور حول سير العمل أو نهج تتمحور حول قاعدة البيانات.

حتى الآن ، تعمل محركات سير العمل بشكل أساسي على حالة التطبيق بدلاً من بيانات الأعمال ، وغالبًا ما تتطلب بعض التعقيد عند التكامل مع قواعد البيانات التقليدية. تضيف الأساليب التي تتمحور حول قاعدة البيانات منطق التطبيق إلى جانب بيانات الأعمال ، ولكن ليس لديها حتى الآن نفس تطور تنفيذ التعليمات البرمجية لمحركات سير العمل. 

يوفر الرسم البياني أدناه رسمًا تقريبيًا لكيفية استخدام نهج سير العمل و / أو قاعدة البيانات في تطبيق Javascript / Typescript ، بافتراض أن كلاهما قيد الاستخدام. على الرغم من أنها أجزاء مميزة من هذه البنية اليوم ، فقد رأينا علامات مبكرة لاتجاه حيث تدمج قواعد البيانات ميزات سير العمل وتبدأ تدفقات العمل في اعتماد التخزين الدائم. يشير هذا الدمج للقدرات إلى أن الخطوط الفاصلة بين الطريقتين غير واضحة وأصبحت أقل تميزًا في البنى الحديثة. 

نهج تتمحور حول سير العمل بالتفصيل 

سير العمل هو مجرد كتل من التعليمات البرمجية التي يتم تنفيذها بناءً على الأحداث ، أو أجهزة ضبط الوقت ، التي تطور جهاز حالة التطبيق. يضمن سير عمل المعاملات تنفيذ الكود بضمانات قوية ، مما يمنع الحالات الجزئية أو غير المقصودة في التطبيق. يكتب المطورون المنطق ، ويتعامل محرك سير العمل مع المعاملات والطفرات والبطالة. تقدم محركات سير العمل المختلفة مقايضات مختلفة من حيث مقدار تفاصيل المعاملة التي يتعرض لها المطورون. 

كمثال ، يوجد أدناه تمثيل مرئي لسير عمل السحب الذي يعمل على Orkes (موصل): 

هناك نهجين تقريبيين التي من خلالها تكتسب محركات سير العمل قوة الجر. في واحدة (تم تمييزها بواسطة Temporal.io) ، يكتب المطورون التعليمات البرمجية باستخدام لغات البرمجة الخلفية القياسية (مثل Go أو Java) و سيضمن النظام تشغيل الكود حتى الاكتمال، حتى أثناء الفشل. في هذا النموذج ، يتم الاحتفاظ بمكدس استدعاءات البرنامج حتى إذا كانت الشفرة تنتظر اكتمال مكالمة الحظر (مثل القراءة أو الكتابة). للقيام بذلك ، يتم تعديل وقت تشغيل اللغة لمنع التنفيذ الجزئي للتعليمات البرمجية أثناء حالات الفشل. الجانب الإيجابي لهذا النهج هو أنه يمكن للمطورين الكتابة بلغات مألوفة وتصحيح الأخطاء بسهولة باستخدام مكدس مكالمات يتم الاحتفاظ به. نرى هذا النهج أكثر شيوعًا مع الفرق الخلفية التي تتعامل مع تطبيقات كبيرة ومتطورة. 

الجانب السلبي هو أنه غالبًا ما يتطلب الكثير من أعمال التكامل والتعليمات البرمجية المجمعة لعرض واجهات مفيدة وآمنة لمطوري التطبيقات. الجانب السلبي الآخر هو أنه يعتمد على طبقة تنفيذ مخصصة بدلاً من اللغة المجردة ، وهناك حالات حافة يختلف فيها التنفيذ عن وقت تشغيل اللغة الأصلية. لذلك ، بينما يمكن للمطورين استخدام اللغات المألوفة لهم ، لا يزالون بحاجة إلى فهم كيفية عمل النظام الأساسي.  

الأسلوب الآخر ، الأكثر شيوعًا بين مطوري التطبيقات (خاصةً Typescript / Javascript) لمحرك سير العمل بمثابة منظم للوظائف غير المتزامنة (على سبيل المثال ، الابتكارات والتأجيل والتشغيل). في هذا النموذج ، يتم توجيه أحداث أو وظائف الطرف الثالث إلى محرك سير العمل ، والذي سيرسل بعد ذلك المنطق المسجل بواسطة مبرمجي التطبيق ، الذين يجب عليهم إعادة التحكم بمجرد ظهور الحاجة إلى حظر وظيفة غير متزامنة أخرى. الجانب الإيجابي هو أن هذه طريقة خفيفة الوزن للاندماج في البرنامج. كما أنه يفرض بنية كافية على الكود بحيث يمكن للفريق الذي يعمل عليه فهمه بسهولة أكبر. ومع ذلك ، قد يكون تصحيح هذا الأسلوب أكثر صعوبة بدون دعم الأدوات ، لذلك يميل تصحيح الأخطاء إلى أن يكون خاصًا بالنظام الأساسي.

تعتبر محركات سير العمل قوية بشكل خاص من حيث أنها تسمح بالاعتماد التدريجي بواسطة التطبيقات الحالية. يمكن تطبيقها على أساس مجزأ على تدفقات عمل معينة بأقل قدر من البصمة. ومع ذلك ، فإن أكبر عيوب في محركات سير العمل تنبع من حقيقة أنها لا تمتد إلى قاعدة البيانات. نتيجة لذلك ، لا يوجد مصدر واحد للحقيقة يمكن الاستعلام عنه عبر حالة التطبيق وبيانات الأعمال. أيضًا ، تختلف دلالات المعاملات عمومًا عن دلالات قاعدة البيانات ، مما يتطلب من مطوري التطبيقات التعامل مع شروط الحافة. 

على الرغم من أن هذا ليس هو المعيار اليوم ، إلا أننا نريد توضيح البنى المفاهيمية لكيفية استخدام تدفقات العمل في كثير من الحالات كمخازن بيانات ثابتة:

أمثلة على بنيات سير العمل فقط

هندسة سير العمل فقط: تطبيقات JavaScript

بنية سير العمل فقط: التطبيقات التي تستخدم الخدمات المصغرة

النهج المتمحورة حول قواعد البيانات بالتفصيل 

تبدأ المناهج المرتكزة على قاعدة البيانات بقاعدة بيانات ، ولكنها توسعها لدعم تنفيذ التعليمات البرمجية العشوائية للسماح بمهام سير العمل جنبًا إلى جنب مع إدارة البيانات. يفعلون ذلك من خلال منح السيطرة للمبرمجين حتى يتمكنوا من اتخاذ قرارات صريحة بشأن الطفرات والمعاملات والوقت العاطفي لكتل ​​التعليمات البرمجية العادية - بشكل أساسي عن طريق تعريض دلالات OLTP مباشرة. المبرمج مسؤول عن الحفاظ على منطق الأعمال وبيانات الأعمال منفصلة عن حالة التطبيق. 

في الواقع ، وجهة نظر قاعدة البيانات البحتة هي أنه يمكن دائمًا اشتقاق حالة التطبيق من بيانات الأعمال. يتم ذلك عادةً عن طريق تخزين حالة التطبيق كمجموعة من المعاملات التي تعدل بيانات الأعمال في قاعدة البيانات. من الأسهل التفكير في هذا كقاعدة بيانات يمكنها تنفيذ كتل من التعليمات البرمجية بنفس الضمانات القوية مثل أنظمة سير العمل الموضحة أعلاه. 

داخليا ، نسمي هذا منصة معاملات منطقية التطبيق (ALTP) النهج لأنه ، في النهاية ، يوسع معاملات OLTP في التطبيق. ولكن ما يميز ALTP حقًا هو أنه ، بالنسبة لتطبيقات الحقول الخضراء ، يمكن أن يلغي تمامًا الحاجة إلى مطوري التطبيقات لإدارة البنية التحتية الخلفية مباشرةً.  

من عدسة ALTP ، بدأ الأسلوب الأكثر استخدامًا مع Firebase ، والذي يوفر ملف خدمة كاملة "تجربة خلفية" ، بما في ذلك المصادقة ومخزن البيانات وقواعد البيانات والمزيد. لا يزال Firebase والوافدين الجدد ، مثل Supabase ، منصات شائعة جدًا لمشاريع Greenfield. وعلى الرغم من أنهم يميلون إلى البقاء مخلصين لجذور OLTP الخاصة بهم - وبالتالي لا يدعمون تنفيذ التعليمات البرمجية التعسفية للوظائف الخلفية للمعاملات - بدأت Supabase بالفعل في إضافة دعم لعمليات سير العمل.

ومع ذلك، عروض ALTP من الجيل التالي مثل Convex تسمح بتنفيذ رمز تعسفي كمعاملة بجانب قاعدة البيانات. تسمح هذه العروض بكتابة تعليمات برمجية متوافقة تمامًا مع المعاملات بلغة عادية (مثل Javascript / Typescript) ، حيث يمكن لكتلة واحدة من التعليمات البرمجية قراءة البيانات وكتابتها وتعديلها - كل من حالة التطبيق وبيانات الأعمال. بمعنى أنه يمنح المطورين مصدرًا واحدًا للحقيقة يمكن الاستعلام عنه ، ويوفر أساسيات سير العمل مثل الاشتراكات. 

يحل ALTP مشكلة محركات سير العمل في فصلها عن قاعدة البيانات ، ولكن نتيجة لذلك ، تطلب من المستخدمين الاعتماد على عرض قاعدة البيانات الخاصة بهم بدلاً من OLTP القياسي من أجل الحصول على الفوائد. نتيجة لذلك ، نرى أن الفرق تعتمد بشكل أساسي على ALTP لتطبيقات الحقول الخضراء ، بدلاً من دمجها في الخلفيات الحالية المعقدة.

الرسم البياني أعلاه عبارة عن مزيج من العديد من المشغلين الذين تحدثنا معهم. سيستخدم البعض محرك سير العمل فقط. سيستخدم البعض نهجًا يركز على قاعدة البيانات فقط. لكن سيستخدم الكثيرون كلاهما - خاصةً عندما يبدأون للتو في اعتماد مهام سير العمل. يميل مستخدمو محركات سير العمل اليوم إلى أن يكونوا فرقًا خلفية تتعامل مع تطبيقات كبيرة ومعقدة ، على الرغم من أننا رأينا أيضًا العديد من الفرق الكاملة التي تتبناها. تميل الحلول الخلفية كخدمة إلى أن تكون أكثر ملاءمة لمطوري التطبيقات وتكون أكثر شيوعًا عندما يقود التطبيق اختيار التكنولوجيا. 

التقارب

أصبح من الواضح أن مناهج سير العمل التي تتمحور حول قواعد البيانات والأساليب التي تتمحور حول قواعد البيانات في مسار تصادمي. السبب الرئيسي لذلك هو أنه على الرغم من أن حالة التطبيق وحالة قاعدة البيانات منفصلان منطقيًا ، إلا أنهما يعتمدان على بعضهما البعض ، والنظام الذي لا يغطي كليهما معقد للحصول على الحق والتصحيح.  

كمثال ، ضع في اعتبارك محرك سير العمل الذي يتم استخدامه لتتبع آلة الحالة لعملية تسجيل الخروج للمستخدم ، ويضيف هذا المستخدم عنصرًا إلى عربة التسوق. عادةً ما تضمن محركات سير العمل تشغيل خطوة التعليمات البرمجية حتى في حالة حدوث عطل. ومع ذلك ، قد تكون هناك حالات يحتاج فيها المحرك إلى إعادة تشغيل خطوة معينة أثناء الفشل لأنه ليس متأكدًا تمامًا مما إذا كانت الخطوة قد اكتملت بالكامل أم لا. إذا كانت هذه الخطوة تتضمن كتابة بيانات العمل إلى قاعدة بيانات تقليدية (في هذه الحالة ، العنصر الموجود في سلة التسوق) ولم تكن قاعدة البيانات على دراية بإعادة المحاولة المكررة ، فسينتهي الأمر بإدخال مكرر. 

هناك طريقتان للتعامل مع هذا. تتمثل إحدى الطرق في دفع المشكلة إلى مطور التطبيق ، والذي سيستخدم رقمًا غير قياسي يوفره نظام سير العمل لضمان كتابة عنصر واحد فقط. لكن هذا يفترض أن المطور يفهم العاطفة ، وهو أمر يصعب فهمه بشكل صحيح ، وهذا يتجنب الكثير من سحر وجود نظام سير عمل. والطريقة الأخرى هي ربط محرك سير العمل بقاعدة بيانات تدرك دلالات معاملات سير العمل. لم يحدث هذا بعد ، لكن ليس من الصعب تصديق أنه سيحدث. 

من ناحية أخرى ، تدرك المناهج المرتكزة على قاعدة البيانات أن سير العمل العام مفيد حقًا لمطوري التطبيقات. وهكذا بدأنا نرى قواعد البيانات (مثل محدب) - التي تدعم وظائف قاعدة البيانات التقليدية مثل الاستعلامات والطفرات والفهارس وما إلى ذلك - تنفذ وظائف مثل الجدولة والاشتراكات. هذه تسمح لهم باستخدامها كمحركات سير العمل. أي أنها تسمح بتنفيذ كتل التعليمات البرمجية التعسفية بضمانات قوية. 

كما قال إيان ليفينغستون (الذي قدم تعليقًا على هذه القطعة) ، "إنها العبارة الكلاسيكية "هل تجلب منطق التطبيق إلى قاعدة البيانات ، أم قاعدة البيانات إلى منطق التطبيق؟" اللعب مرة أخرى ... هذه المرة تم إحضارها عن طريق تفكيك الكتلة المتراصة. " بعد أن كان هناك هذا الانقسام لعقود من الزمن ، من الواضح أن كلا النموذجين سيستمران على المدى القصير. من غير الواضح بكثير أن تظل الحالة على هذا النحو على المدى الطويل. 

شكر خاص لـ Charly Poly (Defer) ، Dan Farrelly (Inngest) ، David Khourshid (Stately) ، Ian Livingstone (Cape Security) ، Enes Akar (Upstash) ، James Cowling (Convex) ، Jamie Turner (Convex) ، Paul Copplestone (Supabase) ) ، Sam Lambert (PlanetScale) ، Tony Holdstock-Brown (Inngest) ، Matt Aitken (Trigger) لمراجعة هذا المنشور وتقديم التعليقات. بالإضافة إلى ذلك ، بفضل بنيامين هندمان (ريبوت) ، وفريدريك بيورك (جرافبيس) ، وجلوبر كوستا (تشيزلسترايك) ، وغيوم ساليس (لايفبلوكس) ، ومكسيم فاتيف (مؤقت) ، وستيفن فابر (لايفبلوكس) ، وفيرين بارايا (أوركس) لمساعدتنا في ذلك. البحث.

* * *

الآراء المعبر عنها هنا هي آراء أفراد AH Capital Management، LLC ("a16z") المقتبس منهم وليست آراء a16z أو الشركات التابعة لها. تم الحصول على بعض المعلومات الواردة هنا من مصادر خارجية ، بما في ذلك من شركات محافظ الصناديق التي تديرها a16z. على الرغم من أنه مأخوذ من مصادر يُعتقد أنها موثوقة ، لم تتحقق a16z بشكل مستقل من هذه المعلومات ولا تقدم أي تعهدات حول الدقة الدائمة للمعلومات أو ملاءمتها لموقف معين. بالإضافة إلى ذلك ، قد يتضمن هذا المحتوى إعلانات جهات خارجية ؛ لم تقم a16z بمراجعة مثل هذه الإعلانات ولا تصادق على أي محتوى إعلاني وارد فيها.

يتم توفير هذا المحتوى لأغراض إعلامية فقط ، ولا ينبغي الاعتماد عليه كمشورة قانونية أو تجارية أو استثمارية أو ضريبية. يجب عليك استشارة مستشاريك بخصوص هذه الأمور. الإشارات إلى أي أوراق مالية أو أصول رقمية هي لأغراض توضيحية فقط ، ولا تشكل توصية استثمارية أو عرضًا لتقديم خدمات استشارية استثمارية. علاوة على ذلك ، هذا المحتوى غير موجه أو مخصص للاستخدام من قبل أي مستثمرين أو مستثمرين محتملين ، ولا يجوز الاعتماد عليه تحت أي ظرف من الظروف عند اتخاذ قرار بالاستثمار في أي صندوق تديره a16z. (سيتم تقديم عرض للاستثمار في صندوق a16z فقط من خلال مذكرة الاكتتاب الخاص واتفاقية الاشتراك والوثائق الأخرى ذات الصلة لأي صندوق من هذا القبيل ويجب قراءتها بالكامل.) أي استثمارات أو شركات محفظة مذكورة ، يشار إليها ، أو الموصوفة لا تمثل جميع الاستثمارات في السيارات التي تديرها a16z ، ولا يمكن أن يكون هناك ضمان بأن الاستثمارات ستكون مربحة أو أن الاستثمارات الأخرى التي تتم في المستقبل سيكون لها خصائص أو نتائج مماثلة. قائمة الاستثمارات التي أجرتها الصناديق التي يديرها Andreessen Horowitz (باستثناء الاستثمارات التي لم يمنحها المُصدر إذنًا لـ a16z للإفصاح علنًا عن الاستثمارات غير المعلنة في الأصول الرقمية المتداولة علنًا) على https://a16z.com/investments /.

الرسوم البيانية والرسوم البيانية المقدمة في الداخل هي لأغراض إعلامية فقط ولا ينبغي الاعتماد عليها عند اتخاذ أي قرار استثماري. الأداء السابق ليس مؤشرا على النتائج المستقبلية. المحتوى يتحدث فقط اعتبارًا من التاريخ المشار إليه. أي توقعات وتقديرات وتنبؤات وأهداف وآفاق و / أو آراء معبر عنها في هذه المواد عرضة للتغيير دون إشعار وقد تختلف أو تتعارض مع الآراء التي يعبر عنها الآخرون. يرجى الاطلاع على https://a16z.com/disclosures للحصول على معلومات إضافية مهمة.

بقعة_صورة

أحدث المعلومات الاستخباراتية

بقعة_صورة