Style Specifics (รายละเอียดเฉพาะของ Style)

หัวข้อต่อไปนี้จะอธิบาย artifact หลักเหล่านี้และวิธีการทำงานของมันอย่างละเอียด

Processing Unit (Processing Unit)

processing unit (แสดงใน Figure 16-3 ) ประกอบด้วย application logic (หรือบางส่วนของมัน) โดยมักรวมถึง web-based component เช่นเดียวกับ backend business logic เนื้อหาภายใน processing unit จะแตกต่างกันไปตามประเภทของแอปพลิเคชัน แอปพลิเคชัน web-based ขนาดเล็กมักถูก deploy ลงใน processing unit เดียว ในขณะที่แอปพลิเคชันขนาดใหญ่มักแบ่งฟังก์ชัน การทำงานออกเป็น processing unit หลายตัว ตาม functional area ของแอปพลิเคชัน processing unit ยังสามารถมี service ขนาดเล็กที่มีจุดประสงค์เดียว (คล้ายกับ microservices) ได้ด้วย นอกจากนี้ processing unit ยังมี in-memory data grid และ replication engine ซึ่งมักถูก implement ผ่านผลิตภัณฑ์อย่าง Hazelcast , Apache Ignite และ Oracle Coherence (ดู “Data Grid” )

Space-based processing unit

Figure 16-3. processing unit ประกอบด้วยฟังก์ชันการทำงานของแอปพลิเคชัน

Virtualized Middleware (Virtualized Middleware)

virtualized middleware ดังแสดงใน Figure 16-4 ประกอบด้วย artifact ที่เกี่ยวข้องกับ infrastructure หลายอย่าง และใช้เพื่อจัดการและควบคุม processing unit อย่างน้อยที่สุด middleware artifact นี้ต้องมี messaging grid เพื่อจัดการ input request และ user session state, data grid เพื่อจัดการการ replicate และ synchronize ข้อมูล และ deployment manager เพื่อ start และ tear down instance ของ processing unit ตามที่จำเป็นหรือไม่จำเป็น นอกจากนี้ virtualized middleware ยังอาจมี processing grid เพิ่มเติม ในกรณีที่ต้อง orchestrate processing unit ตั้งแต่สองตัวขึ้นไปสำหรับ business request เดียว สถาปนิกสามารถเพิ่มฟังก์ชันที่เกี่ยวข้องกับ infrastructure อื่น ๆ เข้าไปใน virtualized middleware ได้ ตามต้องการ เช่น ฟังก์ชันด้าน security หรือการเก็บ metric สำหรับ observability เป็นต้น

เนื่องจากไม่มีผลิตภัณฑ์ตัวเดียวที่ทำหน้าที่ทั้งหมดของ virtualized middleware ได้ จึงมักถูก implement ผ่านผลิตภัณฑ์จากบุคคลที่สาม เช่น web server, caching tool, load balancer, service orchestrator และ deployment manager เพื่อจัดการ monitoring, การ start และการ tear down processing unit แต่ละ middleware artifact เหล่านี้จะอธิบายอย่างละเอียดในหัวข้อถัดไป

Messaging Grid (Messaging Grid)

messaging grid ดังแสดงใน Figure 16-4 เป็นส่วนหนึ่งของ virtualized middleware และจัดการ input request กับ session state เมื่อ request เข้ามาที่ virtualized middleware component ของ messaging grid จะพิจารณาว่า processing unit ตัวไหนที่ active และพร้อมรับ request นั้น แล้วส่งต่อ request ไปยังหนึ่งใน processing unit เหล่านั้น

ความซับซ้อนของ messaging grid อาจแตกต่างกันไป ตั้งแต่ round-robin algorithm แบบง่าย ไปจนถึง next-available algorithm ที่ซับซ้อนกว่าซึ่งคอยติดตามว่า processing unit ตัวไหนว่างมากที่สุด component นี้มักถูก implement โดยใช้ web server ทั่วไปที่มีความสามารถด้าน load balancing (เช่น HA Proxy หรือ Nginx)

Messaging grid

Figure 16-4. messaging grid จัดการ request และ session state

Data Grid (Data Grid)

data grid เป็น component หนึ่ง—อาจเป็น component ที่สำคัญที่สุด—ของ virtualized middleware ใน implementation สมัยใหม่ส่วนใหญ่ data grid จะถูก implement อยู่ภายใน processing unit เพียงอย่างเดียว ในรูปแบบ in-memory replicated cache (ดู “Replicated and distributed caching” ) อย่างไรก็ตาม สำหรับ implementation ของ replicated caching ที่ต้องการ external controller หรือที่ใช้ distributed cache ฟังก์ชันนี้จะอยู่ใน ทั้ง processing unit และ component ของ data grid ใน virtualized middleware

เนื่องจาก messaging grid สามารถส่งต่อ request ไปยัง processing unit ตัวใดก็ได้ที่มีอยู่ จึงจำเป็นอย่าง ยิ่งที่ in-memory data grid ของ processing unit แต่ละตัวต้องมี ข้อมูลที่เหมือนกันทุกประการ ดังแสดงด้วยเส้นประใน Figure 16-5 การ replicate ข้อมูลมักทำแบบ asynchronous ระหว่าง processing unit โดยปกติจะ replicate ข้อมูลเสร็จ ภายในเวลาไม่ถึง 100 ms

Data grid

Figure 16-5. data grid synchronize in-memory cache

ข้อมูลจะถูก synchronize ระหว่าง processing unit ที่มี data grid ชื่อเดียวกัน ตัวอย่างเช่น โค้ด Java ต่อไปนี้ใช้ Hazelcast เพื่อสร้าง internal replicated data grid สำหรับ processing unit ที่มีข้อมูล customer profile:

HazelcastInstance hz = Hazelcast.newHazelcastInstance();
Map<String, CustomerProfile> profileCache =
    hz.getReplicatedMap("CustomerProfile");

processing unit ทุกตัวที่ต้องเข้าถึงข้อมูล customer profile ควรมีโค้ดนี้อยู่ด้วย เมื่อ processing unit ตัวใดตัวหนึ่งอัปเดตข้อมูลใน cache CustomerProfile data grid จะ replicate การอัปเดตนี้ไปยัง processing unit ตัวอื่น ๆ ที่มี cache ชื่อ CustomerProfile เดียวกัน processing unit หนึ่งตัวสามารถมี in-memory replicated cache ได้มากเท่าที่จำเป็นสำหรับงานของ มัน หรืออีกทางหนึ่ง processing unit ตัวหนึ่งสามารถเรียก remote call ไปยัง processing unit อีกตัวเพื่อขอ ข้อมูล (choreography) หรือใช้ processing grid (อธิบายในหัวข้อถัดไป) เพื่อ orchestrate การขอข้อมูล (ดู “Orchestration Versus Choreography” ใน Chapter 20 สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ orchestration และ choreography)

การใช้ data replication ภายใน processing unit ทำให้สามารถ start instance เพิ่มเติมได้โดยไม่ต้องอ่าน ข้อมูลจากฐานข้อมูล ตราบใดที่มีอย่างน้อยหนึ่ง instance ที่มี named replicated cache นั้นอยู่ เมื่อ processing unit instance ใหม่ start ขึ้น มันจะ broadcast request ผ่าน caching provider (เช่น Hazelcast) เพื่อเข้าร่วมกับ processing unit อื่น ๆ ที่มี cache ชื่อเดียวกัน เมื่อ processing unit อื่น ๆ acknowledge request ที่ broadcast มาและเชื่อมต่อกับ processing unit ใหม่แล้ว หนึ่งในนั้น (มักเป็น ตัวแรกที่เชื่อมต่อกับ processing unit ใหม่) จะส่งข้อมูล cache ไปยัง instance ใหม่ เพื่อให้ sync กับ instance อื่น ๆ ที่มี cache ชื่อเดียวกัน

processing unit แต่ละ instance จะมี member list ที่บรรจุ IP address และ port ของ processing-unit instance อื่น ๆ ทั้งหมดที่มี cache ชื่อเดียวกัน ตัวอย่างเช่น สมมติว่ามี processing-unit instance เดียวที่มีฟังก์ชัน customer profile และข้อมูล in-memory replicated cache ของมัน ในกรณีนี้มีเพียง instance เดียว ดังนั้น member list ของมันจึงมีแค่ ตัวมันเอง ดังแสดงใน logging statement ต่อไปนี้ ที่สร้างขึ้นโดยใช้ Hazelcast:

Instance 1:
Members {size:1, ver:1} [
    Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268 this
]

เมื่อ processing unit อีกตัวหนึ่ง start ขึ้นด้วย cache ชื่อเดียวกัน member list ของทั้งสอง service จะถูกอัปเดตให้สะท้อน IP address และ port ของ processing unit แต่ละตัว:

Instance 1:
Members {size:2, ver:2} [
    Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268 this
    Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316
]

Instance 2:
Members {size:2, ver:2} [
    Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268
    Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316 this
]

เมื่อ processing unit ตัวที่สาม start ขึ้น member list ของ instance 1 และ instance 2 จะถูกอัปเดตทั้งคู่ ให้สะท้อนถึง instance ที่สามใหม่นี้:

Instance 1:
Members {size:3, ver:3} [
    Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268 this
    Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316
    Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753
]

Instance 2:
Members {size:3, ver:3} [
    Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268
    Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316 this
    Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753
]

Instance 3:
Members {size:3, ver:3} [
    Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268
    Member [172.19.248.90]:5702 - ea9e4dd5-5cb3-4b27-8fe8-db5cc62c7316
    Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753 this
]

ตอนนี้ทั้งสาม instance รู้จักกันและกันแล้ว (รวมถึงตัวเองด้วย ซึ่งแสดงด้วยคำว่า this ต่อท้าย member line) สมมติว่า instance 1 ได้รับ request จากลูกค้าให้อัปเดตที่อยู่สำหรับเรียกเก็บเงิน (bill-to address) เมื่อ instance 1 อัปเดต cache ด้วย cache.put() หรือ cache update method อื่นที่คล้ายกัน data grid (เช่น Hazelcast) จะอัปเดต cache ที่ replicate ไว้ ตัวอื่น ๆ แบบ asynchronous ด้วยการอัปเดตเดียวกัน เพื่อให้แน่ใจว่า customer profile cache ทั้งสามตัวมี ที่อยู่สำหรับเรียกเก็บเงินใหม่ จึงยังคง sync กันด้วยข้อมูลเดียวกันเสมอ

เมื่อ processing-unit instance ตัวใดตัวหนึ่ง down ไป member list ของ processing unit ตัวอื่น ๆ ทั้งหมด จะถูกอัปเดตอัตโนมัติให้สะท้อนการเปลี่ยนแปลงนั้น ตัวอย่างเช่น ถ้า instance 2 down ไป caching product จะอัปเดต member list ของ instance 1 และ 3 ทันทีเพื่อลบ instance ที่หายไปออก:

Instance 1:
Members {size:2, ver:4} [
    Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268 this
    Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753
]

Instance 3:
Members {size:2, ver:4} [
    Member [172.19.248.89]:5701 - 04a6f863-dfce-41e5-9d51-9f4e356ef268
    Member [172.19.248.91]:5703 - 1623eadf-9cfb-4b83-9983-d80520cef753 this
]

Replicated and distributed caching (Replicated Caching และ Distributed Caching)

Space-based architecture พึ่งพา caching ในการประมวลผล transaction ของแอปพลิเคชัน มันช่วยขจัดความ จำเป็นในการอ่านและเขียนฐานข้อมูลโดยตรง ซึ่งเป็นสาเหตุที่ทำให้รองรับ scalability, elasticity และ performance ระดับสูงได้ architecture style นี้ส่วนใหญ่พึ่งพา in-memory replicated caching แม้ว่า จะสามารถใช้ distributed caching ได้เช่นกัน

ด้วย replicated caching ดังแสดงใน Figure 16-6 processing unit แต่ละตัวจะมี in-memory data grid ของตัวเอง ซึ่งจะ synchronize ระหว่าง processing unit ทั้งหมดที่ใช้ cache ชื่อเดียวกันนั้น เมื่อ cache ภายใน processing unit ตัวใดตัวหนึ่งถูกอัปเดต processing unit ตัวอื่น ๆ จะถูกอัปเดตข้อมูลใหม่โดยอัตโนมัติ

Replicated caching

Figure 16-6. Replicated caching synchronize in-memory cache ระหว่าง processing unit

replicated caching ไม่เพียงเร็วมาก แต่ยังรองรับ fault tolerance ระดับสูงด้วย เนื่องจากไม่มี central server ตัวใดที่เก็บ cache ไว้ replicated caching จึงไม่มี single point of failure 1

แม้ replicated caching จะเป็น caching model มาตรฐานสำหรับ space-based architecture แต่ก็มีบางกรณี ที่ใช้ไม่ได้ กรณีหนึ่งคือเมื่อระบบต้องรองรับ data volume สูง เมื่อ internal memory cache มีขนาด ใหญ่กว่า 100 MB processing unit แต่ละตัวจะต้องใช้ memory มากจนอาจก่อปัญหาด้าน elasticity และ scalability processing unit มักถูก deploy ภายใน virtual machine หรือ container (เช่น Docker) ซึ่งแต่ละตัวมี memory จำกัดสำหรับใช้เป็น internal cache สิ่งนี้จำกัดจำนวน processing-unit instance ที่สามารถ start ขึ้นเพื่อรองรับสถานการณ์ที่มี throughput สูง

อีกสถานการณ์หนึ่งที่ replicated data cache ทำงานได้ไม่ดีคือเมื่อข้อมูลใน cache ถูกอัปเดตบ่อยมาก ดังแสดงใน “Data Collisions” ถ้า update rate ของข้อมูลใน cache สูงเกินไป data grid อาจตามไม่ทัน ซึ่งอาจทำลาย data consistency ทั่วทุก processing-unit instance เมื่อเกิดสถานการณ์เหล่านี้ สถาปนิกส่วนใหญ่มักเลือกใช้ distributed cache แทน

Distributed caching ดังแสดงใน Figure 16-7 ต้องการ external server หรือ service ที่ทำหน้าที่เก็บ centralized cache โดยเฉพาะ ในโมเดลนี้ processing unit จะไม่เก็บข้อมูลไว้ใน internal memory แต่จะใช้ proprietary protocol เพื่อเข้าถึง ข้อมูลจาก central cache server แทน distributed caching รองรับ data consistency ระดับสูง เพราะ ข้อมูลทั้งหมดถูกเก็บไว้ที่เดียวและไม่จำเป็นต้อง replicate อย่างไรก็ตาม โมเดลนี้ทำงานได้ไม่ดีเท่า replicated caching เพราะต้องเข้าถึงข้อมูล cache จากระยะไกล ซึ่งเพิ่ม latency โดยรวมของระบบ

Distributed caching

Figure 16-7. Distributed caching สร้าง data consistency ที่ดีระหว่าง processing unit

fault tolerance ก็เป็นปัญหาสำหรับ distributed caching เช่นกัน ถ้า cache server ที่เก็บข้อมูล down ไป processing unit ทุกตัวจะไม่สามารถเข้าถึงหรืออัปเดตข้อมูลได้เลย single point of failure นี้ สามารถบรรเทาได้ด้วยการทำ mirror ให้ distributed cache แต่ก็อาจก่อปัญหาด้าน consistency ได้ ถ้า primary cache server down กะทันหันและข้อมูลไปไม่ถึง mirrored cache server

เมื่อขนาดของ cache ค่อนข้างเล็ก (ต่ำกว่า 100 MB) และ update rate ของ cache ต่ำพอที่ replication engine ของ caching product จะตามทัน การตัดสินใจระหว่างใช้ replicated cache กับ distributed cache จะกลายเป็นคำถามเรื่องการให้ความสำคัญกับ data consistency เทียบกับ performance และ fault tolerance distributed cache จะให้ data consistency ที่ดีกว่า replicated cache เสมอ เพราะข้อมูลอยู่ที่เดียว ไม่กระจายไปตาม processing unit หลายตัว อย่างไรก็ตาม performance และ fault tolerance จะดีกว่าเสมอ เมื่อใช้ replicated cache หลายครั้งปัจจัยตัดสินสุดท้ายจะขึ้นอยู่กับ ประเภท ของข้อมูลที่ cache ไว้ใน processing unit ถ้าความต้องการหลักของระบบคือข้อมูลที่ consistency สูง (เช่น จำนวนสินค้าคงคลังที่มีอยู่) มักจะต้องใช้ distributed cache ถ้าข้อมูลไม่ค่อยเปลี่ยนแปลง (เช่น reference data อย่าง name/value pair, รหัสสินค้า และคำอธิบายสินค้า) ให้พิจารณาใช้ replicated cache เพื่อการค้นหาที่รวดเร็ว Table 16-1 สรุปเกณฑ์บางอย่างสำหรับการเลือกใช้ distributed cache เทียบกับ replicated cache

Table 16-1. Distributed Cache เทียบกับ Replicated Cache | เกณฑ์การตัดสินใจ | Replicated cache | Distributed cache | | --- | --- | --- | | จุดที่เน้น Optimize | Performance | Consistency | | ขนาด Cache | เล็ก (<100 MB) | ใหญ่ (>500 MB) | | ประเภทข้อมูล | ค่อนข้าง Static | เปลี่ยนแปลงสูง (Dynamic) | | ความถี่ในการอัปเดต | ค่อนข้างต่ำ | อัปเดตบ่อย | | Fault Tolerance | สูง | ต่ำ |

เมื่อจะเลือก caching model ที่จะใช้กับ space-based architecture โปรดจำไว้ว่าในกรณีส่วนใหญ่ ทั้งสอง โมเดลสามารถใช้ได้ กล่าวอีกนัยหนึ่งคือ ทั้ง replicated caching และ distributed caching ต่างก็ไม่ สามารถแก้ปัญหาได้ทุกกรณี processing unit ที่แตกต่างกันก็สามารถใช้โมเดลที่แตกต่างกันได้เช่นกัน แทนที่จะประนีประนอมด้วยการเลือก caching model เดียวที่สอดคล้องกันทั่วทั้งแอปพลิเคชัน ให้ใช้จุดแข็ง ของแต่ละโมเดลแทน ตัวอย่างเช่น สำหรับ processing unit ที่ดูแลสินค้าคงคลังปัจจุบัน ให้เลือก distributed caching model เพื่อ data consistency ส่วน processing unit ที่ดูแล customer profile ให้เลือก replicated cache เพื่อ performance และ fault tolerance .

Near-cache considerations (ข้อพิจารณาเรื่อง Near-Cache)

near-cache คือ hybrid caching model ที่เชื่อม in-memory data grid เข้ากับ distributed cache ในโมเดลนี้ (แสดงใน Figure 16-8 ) distributed cache จะถูกเรียกว่า full backing cache และ in-memory data grid แต่ละตัวที่อยู่ภายใน processing unit จะถูกเรียกว่า front cache front cache จะมีข้อมูลเพียงส่วนย่อยของ full backing cache เสมอ และใช้ eviction policy เพื่อลบรายการเก่าออกเพื่อให้เพิ่มรายการใหม่ได้ front cache มี eviction policy ให้เลือกสามแบบ ได้แก่ cache แบบ most recently used ที่เก็บรายการที่ใช้ล่าสุด, cache แบบ most frequently used ที่เก็บรายการที่ใช้บ่อยที่สุด หรือ eviction policy แบบ random replacement ซึ่งลบรายการแบบสุ่มเมื่อต้องการพื้นที่ random replacement เป็น eviction policy ที่ดีเมื่อไม่มีการ วิเคราะห์ข้อมูลที่ชัดเจนพอจะให้เหตุผลว่าควรเก็บรายการที่ใช้ล่าสุดหรือใช้บ่อยที่สุด

Near-cache model

Figure 16-8. near-cache model ใช้ทั้ง front cache และ backing cache

แม้ front cache จะถูกทำให้ sync กับ full backing cache อยู่เสมอ แต่ front cache ที่อยู่ภายใน processing unit แต่ละตัวจะไม่ถูก synchronize ระหว่าง processing unit อื่น ๆ ที่ใช้ข้อมูลชุดเดียวกัน ซึ่งหมายความว่า processing unit หลายตัวที่ใช้ data context เดียวกัน (เช่น customer profile) มี แนวโน้มที่จะมีข้อมูลต่างกันใน front cache ของตัวเอง สิ่งนี้ก่อให้เกิดความไม่สอดคล้องกันด้าน performance และ responsiveness ระหว่าง processing unit ดังนั้นเราจึงไม่แนะนำให้ใช้ near-cache model ใน space-based architecture

Processing Grid (Processing Grid)

processing grid ดังแสดงใน Figure 16-9 เป็น component เสริมภายใน virtualized middleware ที่จัดการ orchestrated request processing เมื่อมี processing unit หลายตัวเกี่ยวข้องกับ business request เดียว ถ้า request ต้องการการประสานงานระหว่าง processing unit มากกว่าหนึ่งประเภท (เช่น order-processing unit และ payment-processing unit) processing grid จะทำหน้าที่เป็นตัวกลางและ orchestrate request ระหว่าง processing unit ทั้งสองนั้น

Processing grid

Figure 16-9. processing grid จัดการ orchestration ระหว่าง processing unit

การ implement space-based สมัยใหม่ส่วนใหญ่ (โดยเฉพาะที่ใช้ fine-grained service) จะ implement ฟังก์ชันของ processing grid ผ่าน orchestration processing unit แบบ fine-grained ที่แยกจากกัน แทนที่จะใช้ orchestration engine แบบ coarse-grained ตัวเดียว โดยแต่ละ orchestration processing unit จะจัดการ workflow หลักเพียงหนึ่งเดียว ยกตัวอย่างอีคอมเมิร์ซ สมมติว่าเมื่อ ลูกค้าวางคำสั่งซื้อ processing unit สามตัวต้องประสานงานกัน ได้แก่ Order Placement , Payment และ Inventory Adjustment สถาปนิกสามารถสร้าง processing unit ชื่อ Order Placement Orchestrator เพื่อ orchestrate processing unit ทั้งสามตัวนี้ พวกเขายังอาจสร้าง orchestration processing unit แยก ต่างหากสำหรับ workflow หลักอื่น ๆ เช่น การจัดการคำสั่งซื้อที่ถูกส่งคืนและการเติมสินค้าคงคลัง

Deployment Manager (Deployment Manager)

component Deployment Manager จัดการการ startup และ shutdown ของ processing-unit instance แบบ dynamic ตามสภาวะ load component นี้ คอย monitor response time และ user load อยู่ตลอด จะ start processing unit ใหม่เมื่อ load เพิ่มขึ้น และ shut down processing unit เมื่อ load ลดลง มันมีความสำคัญอย่างยิ่งต่อการบรรลุ variable scalability (elasticity) ภายในแอปพลิเคชัน cloud-based infrastructure ส่วนใหญ่จัดการหน้าที่นี้ได้ เช่นเดียวกับ ผลิตภัณฑ์ด้าน service-orchestration อย่าง Kubernetes

Data Pumps (Data Pumps)

data pump คือวิธีการส่งข้อมูลไปยัง processor อีกตัวหนึ่ง ซึ่งจะอัปเดตฐานข้อมูลต่อ space-based architecture ต้องการ data pump เพราะ processing unit ไม่อ่านและเขียนฐานข้อมูลโดยตรง data pump ใน space-based architecture จะเป็น asynchronous เสมอ ทำให้เกิด eventual consistency ระหว่าง in-memory cache กับ ฐานข้อมูล เมื่อ processing-unit instance ได้รับ request และอัปเดต cache ของมัน processing unit นั้นจะ กลายเป็นเจ้าของการอัปเดตนั้น และมีหน้าที่ส่งข้อมูลผ่าน data pump เพื่อให้ฐานข้อมูลถูกอัปเดตในที่สุด

data pump มักถูก implement ใน space-based architecture โดยใช้ messaging ดังแสดงใน Figure 16-10 .

Data pump

Figure 16-10. data pump ใช้ส่งข้อมูลไปยังฐานข้อมูล

messaging ไม่เพียงรองรับการสื่อสารแบบ asynchronous เท่านั้น แต่ยังรองรับ guaranteed delivery, message persistence และ message order ผ่าน first-in, first-out (FIFO) queuing นอกจากนี้ messaging ยัง decouple processing unit กับ data writer ออกจากกัน ทำให้ถ้า data writer ไม่พร้อมใช้งาน การประมวลผล ภายใน processing unit ก็จะไม่หยุดชะงัก

space-based architecture ส่วนใหญ่มี data pump หลายตัว โดยทั่วไปแต่ละตัวจะถูกกำหนดให้ดูแล domain หรือ subdomain เฉพาะ (เช่น customer หรือ inventory) แต่ก็สามารถกำหนดให้ดูแล cache แต่ละประเภท (เช่น CustomerProfile , CustomerWishlist และอื่น ๆ) หรือ processing-unit domain (เช่น Customer ) ที่มี general cache ขนาดใหญ่กว่ามากรวมอยู่ด้วย

data pump มักมี contract รวมถึง action ที่เกี่ยวข้องกับข้อมูลใน contract (add, delete หรือ update) contract อาจเป็น JSON schema, XML schema, object หรือแม้แต่ value-driven message (map message ที่บรรจุ name-value pair) สำหรับการอัปเดต payload ของ message ใน data pump มักจะมีแค่ ค่าข้อมูลใหม่เท่านั้น ตัวอย่างเช่น ถ้าลูกค้าเปลี่ยนเบอร์โทรศัพท์ใน profile ของตัวเอง ก็จะส่งแค่เบอร์ โทรศัพท์ใหม่ พร้อมกับ customer ID และ action สำหรับอัปเดตข้อมูล

Data Writers (Data Writers)

component Data Writer รับ message จาก data pump และอัปเดตฐานข้อมูลด้วยข้อมูลใน payload ของมัน (ดู Figure 16-10 ) data writer สามารถ implement เป็น service, แอปพลิเคชัน หรือ data hub (เช่น Ab Initio ) granularity ของมันสามารถแตกต่างกันไปตามขอบเขตของ data pump และ processing unit

domain-based data writer ประกอบด้วย database logic ที่จำเป็นสำหรับจัดการการอัปเดตทั้งหมดภายใน domain หนึ่ง (เช่น order processing) ไม่ว่าจะอ่านข้อมูลจาก data pump กี่ตัวก็ตาม ระบบใน Figure 16-11 มี processing unit สี่ตัวและ data pump สี่ตัวที่แทน customer domain ( Profile , WishList , Wallet และ Preferences )—แต่มี data writer เพียงตัวเดียว data writer ของ customer ตัวนี้จะคอยฟัง data pump ทั้งสี่ตัว และมี database logic (เช่น SQL) สำหรับอัปเดตข้อมูลที่เกี่ยวกับ customer ในฐานข้อมูล

Domain-based Data Writer

Figure 16-11. Domain-based data writer

อีกทางหนึ่ง processing unit แต่ละคลาสสามารถมี component Data Writer เฉพาะของตัวเองได้ ดังแสดงใน Figure 16-12 ในโมเดลนี้ data writer แต่ละตัวจะถูกกำหนดให้ดูแล data pump ที่สอดคล้องกันเท่านั้น และมีเฉพาะ database processing logic สำหรับ processing unit นั้น ๆ (เช่น Wallet ) แม้โมเดลนี้มักทำให้เกิด data-writer component จำนวนมาก แต่ก็ให้ scalability และ agility ที่ดีกว่า เพราะทำให้ processing unit, data pump และ data writer สอดคล้องกัน

Dedicated Data Writer

Figure 16-12. Dedicated data writer สำหรับ data pump แต่ละตัว

Data Readers (Data Readers)

ในขณะที่ data writer มีหน้าที่อัปเดตฐานข้อมูล data reader จะอ่านข้อมูลจากฐานข้อมูลและส่งให้ processing unit ผ่าน reverse data pump (ซึ่งเราจะพูดถึงในอีกสักครู่) ใน space-based architecture data reader จะถูกเรียกใช้ใน 3 สถานการณ์ เท่านั้น คือ processing unit instance ทั้งหมดของ cache ชื่อเดียวกัน crash, processing unit ทั้งหมด ภายใน cache ชื่อเดียวกันถูก redeploy หรือต้องดึงข้อมูล archive ที่ไม่ได้อยู่ใน replicated cache

ถ้า instance ทั้งหมด down ไปเนื่องจากระบบ crash ทั้งระบบหรือมีการ redeploy ข้อมูลจะต้องถูกโหลดเข้า cache จากฐานข้อมูล—ซึ่งเป็นสิ่งที่เราพยายามหลีกเลี่ยงใน space-based architecture โดยทั่วไป เมื่อ instance ของ processing unit คลาสหนึ่งเริ่มกลับมาทำงาน แต่ละตัวจะพยายามคว้า lock บน cache ตัวแรกที่ได้ lock จะกลายเป็นเจ้าของ cache ชั่วคราว ส่วนตัวอื่น ๆ จะเข้าสู่สถานะรอจนกว่า lock จะถูกปล่อย (สิ่งนี้อาจ แตกต่างกันไปตามประเภทของ cache implementation แต่ไม่ว่าจะอย่างไร ในสถานการณ์นี้จะมีเจ้าของ cache หลัก เพียงตัวเดียว) เพื่อโหลด cache เจ้าของ cache ชั่วคราวจะส่ง message ไปยัง queue เพื่อขอข้อมูล component Data Reader จะรับ read request นี้ แล้วทำ database-query logic ที่จำเป็นเพื่อดึงข้อมูลที่ต้องการ จากนั้นส่งข้อมูล นั้นไปยัง queue อีกตัวที่เรียกว่า reverse data pump ซึ่งจะส่งต่อไปยัง processing unit ที่เป็นเจ้าของ cache ชั่วคราว เมื่อโหลด cache เสร็จแล้ว เจ้าของชั่วคราวจะปล่อย lock instance อื่น ๆ ทั้งหมดจะถูก synchronize จากนั้นจึงเริ่มประมวลผลได้ processing flow นี้แสดงอยู่ใน Figure 16-13 .

Data reader

Figure 16-13. data reader ส่งข้อมูลไปยัง processing unit

เช่นเดียวกับ data writer data reader ก็สามารถเป็นแบบ domain based หรือกำหนดเฉพาะให้กับ processing unit คลาสใดคลาสหนึ่งได้ (แบบหลังพบได้บ่อยกว่า) การ implement ของมันก็เหมือนกับ data writer คือเป็น service, แอปพลิเคชัน หรือ data hub

data writer และ data reader โดยพื้นฐานแล้วรวมกันเป็น data abstraction layer (หรือ data access layer ในบางกรณี) ความแตกต่างระหว่างสองอย่างนี้อยู่ที่ปริมาณความรู้เชิงรายละเอียดที่ processing unit มี เกี่ยวกับ database schema (โครงสร้างของตาราง) ด้วย data access layer processing unit จะถูก couple เข้ากับโครงสร้างข้อมูลพื้นฐานในฐานข้อมูล และเข้าถึงฐานข้อมูลทางอ้อมผ่าน data reader และ data writer เท่านั้น ในทางกลับกัน ด้วย data abstraction layer processing unit จะถูก decouple ออกจาก schema พื้นฐาน ผ่านการใช้ contract แยกต่างหาก

Space-based architecture โดยทั่วไปพึ่งพา data abstraction layer model เพื่อให้ replicated cache schema ในแต่ละ processing unit สามารถแตกต่างจาก database schema พื้นฐานได้ ซึ่งหมายความว่าการ เปลี่ยนแปลงฐานข้อมูลแบบค่อยเป็นค่อยไปไม่จำเป็นต้องกระทบ processing unit เพื่อรองรับการเปลี่ยนแปลง แบบค่อยเป็นค่อยไปนี้ data writer และ data reader จึงมี transformation logic อยู่ ถ้า column type เปลี่ยนไป หรือ column หรือ table ถูกลบ data reader และ data writer สามารถ buffer การเปลี่ยนแปลง ฐานข้อมูลไว้ได้ จนกว่าจะทำการเปลี่ยนแปลงที่จำเป็นกับ cache ของ processing unit ได้