SlideShare a Scribd company logo
1 of 18
Шардинг заказов
корзины каталога
Петр Трофимов
600 разделов
800 000 товаров
1000+ магазинов
и почти 5 000 000позиций
Cart.api
app1
app2
app3
app4
...
db1
db2
db3
db4
...
order
order1
order2
orderN
credentials.api
catalog.api
shop.api
geo.api
host1
db1
table1
Споты
spot1 spot2
table2
spot3
db2
spot4
spot5
host2
spot6
spot7
hostN
Карта спотов
start_id finish_id connection_name database spot_prefix
1 1000000 host100 cart10 chunk1_
1000001 2000000 host101 cart11 chunk2_
... ... ... ... ...
10000001 0 host110 cart120 chunk10_
abstract class Model extends EloquentModel
{
protected $spotIdKey;
public function spot()
{
return $this->spot ? : Map::spot($this->getAttributeFromArray($this->spotIdKey));
}
public function getConnection()
{
return $this->spotConnection($this->spot());
}
public function spotConnection(Spot $spot)
{
$configKey = "database.connections.{$spot->connectionName}";
if (!config($configKey)) {
app('config')->set($configKey, $this->spotConfig($spot));
}
return static::resolveConnection($spot->connectionName);
}
public function getTable()
{
return $this->spot()->database . '.' . $this->spot()->spotPrefix . parent::getTable();
}
}
Как искать в спотах?
spot1 spot2 spot3 spot4 spotN
client
SELECT * FROM orders WHERE shop_id = ?
Превью
spotN spot2 spotN
client
preview
preview
WRITE READ
client
spot1
preview
spot3
class PreviewUpdater
{
public function created(Order $order)
{
OrderPreview::create([
'id' => $order->id,
'user_id' => $order->user_id,
'status' => $order->status,
// ...
]);
}
public function updated(Order $order)
{
/** @var OrderPreview $orderPreview */
$orderPreview = OrderPreview::find($order->id);
$orderPreview->user_id = $order->user_id;
$orderPreview->status = $order->status;
// ...
$orderPreview->save();
}
public function deleted(Order $order)
{
OrderPreview::destroy($order->id);
}
}
abstract class Model extends EloquentModel
{
public static function find($id, $columns = ['*'])
{
if (is_array($id)) {
return static::findMany($id, $columns);
}
return static::spotQuery(Map::spot($id))->find($id, $columns);
}
public static function spotQuery(Spot $spot)
{
$instance = new static;
$instance->spot = $spot;
$connection = $instance->spotConnection($spot);
$builder = $instance->newEloquentBuilder(
new QueryBuilder($connection, $connection->getQueryGrammar(), $connection->getPostProcessor())
);
return $builder->setModel($instance);
}
// ...
}
$order = OrderPreview::orderQuery()->whereOrderKey($orderId)->first();
class OrderPreview extends Model
{
public static function orderQuery()
{
$instance = new static;
return (new QueryBuilder($instance->newBaseQueryBuilder(), new Order))->setModel($instance);
}
}
class QueryBuilder extends Builder
{
/** @var Model */
private $spotted;
private $with = [];
public function getModels($columns = ['*'])
{
return $this->spotted->findMany(array_pluck(parent::getModels($columns), 'id'), $columns,
$this->with)->all();
}
}
Запросы через превью
abstract class Model extends EloquentModel
{
public function hasMany($related, $foreignKey = null, $localKey = null)
{
//...
$instance = new $related;
$instance->spot = $this->spot();
return new HasMany(/*...*/, $instance->getTable() . '.' . $foreignKey);
}
}
Поддержка relations
Scenario: Spots with different databases
Given spots map contains spots:
| start_id | finish_id | connection_name | database | spot_prefix |
| 1 | 1 | catalog_cart | <test_db> | |
| 2 | 2 | catalog_cart_spot2 | <test_db>_spot2 | |
# ...
When I send POST request to "/orders"
Then request expectations should be met
And log file should be empty
And response status code should be 201
And SQL query "select * from <test_db>.orders" result should be like:
| id | user_id | shop_id | status | delivery_city | delivery_address | comment |
| 1 | 1 | 1 | 0 | Минск | пр-т Дзержинского, 5 | comment1 |
# ...
Behat-сценарии для спотов
Спасибо за внимание. Вопросы?
● https://catalog.onliner.by/
● https://cart.onliner.by/
● http://php.spb.ru/ms/description.html
● https://engineering.instagram.com/sharding-ids-at-
instagram-1cf5a71e5a5c
Генерация ID
● Auto-increment ID (1, 2, 3, …)
○ Закрыть информацию
○ Шардинг
● Hashids (3jR-OCl4rG0)
○ Number vector
○ Недостаточно безопасные
● UUID (550e8400-e29b-41d4-a716-446655440000)
○ Нечитаемые
● ID sequence
○ Читаемый набор символов (без i и 1)
○ Единый центр выдачи идентификаторов
○ Механизм отслеживания коллизий
$this->sequence = $connection->table('order_id_sequence');
// ...
for ($i = 1; $i <= config('order.key.collisions.limit'); $i++) {
try {
$order->key = $this->generateOrderKey();
$order->id = $this->sequence->insertGetId(['order_key' => $order->key]);
return;
} catch (QueryException $ex) {
if ($ex->getCode() != 23000) { // Integrity constraint violation
throw $ex;
}
}
if ($i == config('order.key.collisions.warning')) {
(new OnlinerLogger)->warning(
"cart-api: $i collisions occurred, think about increasing of order key length"
);
}
}
throw new RuntimeException(
"Failed to generate key for order from user {$order->user_id} to shop {$order->user_id}"
);
class Order extends SpotsModel
{
public $incrementing = false;
protected $spotIdKey = 'id';
protected $table = 'orders';
public function statusLogEntries()
{
return $this->hasMany(OrderStatusLogEntry::class);
}
public function save(array $options = [])
{
if (!$this->exists) {
// ...
app(IdGenerator::class)->generate($this);
}
return parent::save($options);
}
protected static function boot()
{
parent::boot();
// ...
static::observe(PreviewUpdater::class);
}
}

More Related Content

Similar to Шардинг заказов корзины каталога Onliner.by

Beyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the codeBeyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the codeWim Godden
 
Beyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeBeyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeWim Godden
 
Beyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the codeBeyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the codeWim Godden
 
Apache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customizationApache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customizationBartosz Konieczny
 
Reverse Engineering iOS apps
Reverse Engineering iOS appsReverse Engineering iOS apps
Reverse Engineering iOS appsMax Bazaliy
 
Работа с реляционными базами данных в C++
Работа с реляционными базами данных в C++Работа с реляционными базами данных в C++
Работа с реляционными базами данных в C++corehard_by
 
performance vamos dormir mais?
performance vamos dormir mais?performance vamos dormir mais?
performance vamos dormir mais?tdc-globalcode
 
New Framework - ORM
New Framework - ORMNew Framework - ORM
New Framework - ORMOdoo
 
Internationalizing CakePHP Applications
Internationalizing CakePHP ApplicationsInternationalizing CakePHP Applications
Internationalizing CakePHP ApplicationsPierre MARTIN
 
Distributed Queries in IDS: New features.
Distributed Queries in IDS: New features.Distributed Queries in IDS: New features.
Distributed Queries in IDS: New features.Keshav Murthy
 
19 programming sq lite on windows phone 8.1
19   programming sq lite on windows phone 8.119   programming sq lite on windows phone 8.1
19 programming sq lite on windows phone 8.1WindowsPhoneRocks
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applicationselliando dias
 
Compare mysql5.1.50 mysql5.5.8
Compare mysql5.1.50 mysql5.5.8Compare mysql5.1.50 mysql5.5.8
Compare mysql5.1.50 mysql5.5.8Philip Zhong
 
Write Faster SQL with Trino.pdf
Write Faster SQL with Trino.pdfWrite Faster SQL with Trino.pdf
Write Faster SQL with Trino.pdfEric Xiao
 
Webinar: Index Tuning and Evaluation
Webinar: Index Tuning and EvaluationWebinar: Index Tuning and Evaluation
Webinar: Index Tuning and EvaluationMongoDB
 
Relational Database Access with Python ‘sans’ ORM
Relational Database Access with Python ‘sans’ ORM  Relational Database Access with Python ‘sans’ ORM
Relational Database Access with Python ‘sans’ ORM Mark Rees
 
PyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialPyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialjbellis
 
Introducere in web
Introducere in webIntroducere in web
Introducere in webAlex Eftimie
 
SequoiaDB Distributed Relational Database
SequoiaDB Distributed Relational DatabaseSequoiaDB Distributed Relational Database
SequoiaDB Distributed Relational Databasewangzhonnew
 
Introduction to-mongo db-execution-plan-optimizer-final
Introduction to-mongo db-execution-plan-optimizer-finalIntroduction to-mongo db-execution-plan-optimizer-final
Introduction to-mongo db-execution-plan-optimizer-finalM Malai
 

Similar to Шардинг заказов корзины каталога Onliner.by (20)

Beyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the codeBeyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the code
 
Beyond php - it's not (just) about the code
Beyond php - it's not (just) about the codeBeyond php - it's not (just) about the code
Beyond php - it's not (just) about the code
 
Beyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the codeBeyond PHP - it's not (just) about the code
Beyond PHP - it's not (just) about the code
 
Apache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customizationApache Spark in your likeness - low and high level customization
Apache Spark in your likeness - low and high level customization
 
Reverse Engineering iOS apps
Reverse Engineering iOS appsReverse Engineering iOS apps
Reverse Engineering iOS apps
 
Работа с реляционными базами данных в C++
Работа с реляционными базами данных в C++Работа с реляционными базами данных в C++
Работа с реляционными базами данных в C++
 
performance vamos dormir mais?
performance vamos dormir mais?performance vamos dormir mais?
performance vamos dormir mais?
 
New Framework - ORM
New Framework - ORMNew Framework - ORM
New Framework - ORM
 
Internationalizing CakePHP Applications
Internationalizing CakePHP ApplicationsInternationalizing CakePHP Applications
Internationalizing CakePHP Applications
 
Distributed Queries in IDS: New features.
Distributed Queries in IDS: New features.Distributed Queries in IDS: New features.
Distributed Queries in IDS: New features.
 
19 programming sq lite on windows phone 8.1
19   programming sq lite on windows phone 8.119   programming sq lite on windows phone 8.1
19 programming sq lite on windows phone 8.1
 
PHP and Rich Internet Applications
PHP and Rich Internet ApplicationsPHP and Rich Internet Applications
PHP and Rich Internet Applications
 
Compare mysql5.1.50 mysql5.5.8
Compare mysql5.1.50 mysql5.5.8Compare mysql5.1.50 mysql5.5.8
Compare mysql5.1.50 mysql5.5.8
 
Write Faster SQL with Trino.pdf
Write Faster SQL with Trino.pdfWrite Faster SQL with Trino.pdf
Write Faster SQL with Trino.pdf
 
Webinar: Index Tuning and Evaluation
Webinar: Index Tuning and EvaluationWebinar: Index Tuning and Evaluation
Webinar: Index Tuning and Evaluation
 
Relational Database Access with Python ‘sans’ ORM
Relational Database Access with Python ‘sans’ ORM  Relational Database Access with Python ‘sans’ ORM
Relational Database Access with Python ‘sans’ ORM
 
PyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialPyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorial
 
Introducere in web
Introducere in webIntroducere in web
Introducere in web
 
SequoiaDB Distributed Relational Database
SequoiaDB Distributed Relational DatabaseSequoiaDB Distributed Relational Database
SequoiaDB Distributed Relational Database
 
Introduction to-mongo db-execution-plan-optimizer-final
Introduction to-mongo db-execution-plan-optimizer-finalIntroduction to-mongo db-execution-plan-optimizer-final
Introduction to-mongo db-execution-plan-optimizer-final
 

Recently uploaded

Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?XfilesPro
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 

Recently uploaded (20)

Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 

Шардинг заказов корзины каталога Onliner.by

  • 2.
  • 3. 600 разделов 800 000 товаров 1000+ магазинов и почти 5 000 000позиций
  • 6. Карта спотов start_id finish_id connection_name database spot_prefix 1 1000000 host100 cart10 chunk1_ 1000001 2000000 host101 cart11 chunk2_ ... ... ... ... ... 10000001 0 host110 cart120 chunk10_
  • 7. abstract class Model extends EloquentModel { protected $spotIdKey; public function spot() { return $this->spot ? : Map::spot($this->getAttributeFromArray($this->spotIdKey)); } public function getConnection() { return $this->spotConnection($this->spot()); } public function spotConnection(Spot $spot) { $configKey = "database.connections.{$spot->connectionName}"; if (!config($configKey)) { app('config')->set($configKey, $this->spotConfig($spot)); } return static::resolveConnection($spot->connectionName); } public function getTable() { return $this->spot()->database . '.' . $this->spot()->spotPrefix . parent::getTable(); } }
  • 8. Как искать в спотах? spot1 spot2 spot3 spot4 spotN client SELECT * FROM orders WHERE shop_id = ?
  • 10. class PreviewUpdater { public function created(Order $order) { OrderPreview::create([ 'id' => $order->id, 'user_id' => $order->user_id, 'status' => $order->status, // ... ]); } public function updated(Order $order) { /** @var OrderPreview $orderPreview */ $orderPreview = OrderPreview::find($order->id); $orderPreview->user_id = $order->user_id; $orderPreview->status = $order->status; // ... $orderPreview->save(); } public function deleted(Order $order) { OrderPreview::destroy($order->id); } }
  • 11. abstract class Model extends EloquentModel { public static function find($id, $columns = ['*']) { if (is_array($id)) { return static::findMany($id, $columns); } return static::spotQuery(Map::spot($id))->find($id, $columns); } public static function spotQuery(Spot $spot) { $instance = new static; $instance->spot = $spot; $connection = $instance->spotConnection($spot); $builder = $instance->newEloquentBuilder( new QueryBuilder($connection, $connection->getQueryGrammar(), $connection->getPostProcessor()) ); return $builder->setModel($instance); } // ... }
  • 12. $order = OrderPreview::orderQuery()->whereOrderKey($orderId)->first(); class OrderPreview extends Model { public static function orderQuery() { $instance = new static; return (new QueryBuilder($instance->newBaseQueryBuilder(), new Order))->setModel($instance); } } class QueryBuilder extends Builder { /** @var Model */ private $spotted; private $with = []; public function getModels($columns = ['*']) { return $this->spotted->findMany(array_pluck(parent::getModels($columns), 'id'), $columns, $this->with)->all(); } } Запросы через превью
  • 13. abstract class Model extends EloquentModel { public function hasMany($related, $foreignKey = null, $localKey = null) { //... $instance = new $related; $instance->spot = $this->spot(); return new HasMany(/*...*/, $instance->getTable() . '.' . $foreignKey); } } Поддержка relations
  • 14. Scenario: Spots with different databases Given spots map contains spots: | start_id | finish_id | connection_name | database | spot_prefix | | 1 | 1 | catalog_cart | <test_db> | | | 2 | 2 | catalog_cart_spot2 | <test_db>_spot2 | | # ... When I send POST request to "/orders" Then request expectations should be met And log file should be empty And response status code should be 201 And SQL query "select * from <test_db>.orders" result should be like: | id | user_id | shop_id | status | delivery_city | delivery_address | comment | | 1 | 1 | 1 | 0 | Минск | пр-т Дзержинского, 5 | comment1 | # ... Behat-сценарии для спотов
  • 15. Спасибо за внимание. Вопросы? ● https://catalog.onliner.by/ ● https://cart.onliner.by/ ● http://php.spb.ru/ms/description.html ● https://engineering.instagram.com/sharding-ids-at- instagram-1cf5a71e5a5c
  • 16. Генерация ID ● Auto-increment ID (1, 2, 3, …) ○ Закрыть информацию ○ Шардинг ● Hashids (3jR-OCl4rG0) ○ Number vector ○ Недостаточно безопасные ● UUID (550e8400-e29b-41d4-a716-446655440000) ○ Нечитаемые ● ID sequence ○ Читаемый набор символов (без i и 1) ○ Единый центр выдачи идентификаторов ○ Механизм отслеживания коллизий
  • 17. $this->sequence = $connection->table('order_id_sequence'); // ... for ($i = 1; $i <= config('order.key.collisions.limit'); $i++) { try { $order->key = $this->generateOrderKey(); $order->id = $this->sequence->insertGetId(['order_key' => $order->key]); return; } catch (QueryException $ex) { if ($ex->getCode() != 23000) { // Integrity constraint violation throw $ex; } } if ($i == config('order.key.collisions.warning')) { (new OnlinerLogger)->warning( "cart-api: $i collisions occurred, think about increasing of order key length" ); } } throw new RuntimeException( "Failed to generate key for order from user {$order->user_id} to shop {$order->user_id}" );
  • 18. class Order extends SpotsModel { public $incrementing = false; protected $spotIdKey = 'id'; protected $table = 'orders'; public function statusLogEntries() { return $this->hasMany(OrderStatusLogEntry::class); } public function save(array $options = []) { if (!$this->exists) { // ... app(IdGenerator::class)->generate($this); } return parent::save($options); } protected static function boot() { parent::boot(); // ... static::observe(PreviewUpdater::class); } }

Editor's Notes

  1. Привет, петр трофимов, спасибо, несмотря на дедлайны, чтото полезное, вопросы в конце 1 мин
  2. Кто заказывает товары через корзину в каталоге? Поднять Кто нет? А кто будет теперь? (из названия хехе) До этого - телефоны, але?, рога и копыта, нету да, положить денег на телефон Октябрь 2015 - декабрь 2015 Все проще, нажимаем, превращается вот в такую Конечно не все так просто, там еще эту и эту нажать Уведомление 3 мин
  3. Какова специфика каталога онлайнер? 800 тысяч, 600, 1000, 5 млн Заказов больше, чем в одиночном магазине - много данных Много разнородных магазинов - частые обновления, получить актуальные данные Частые изменения прайсов - фиксация данных, много данных Состав может меняться - нужно фиксировать, снэпшоты, много данных Заказы храним очень долго, пока не удалят - много данных, чем старше тем ненужнее Можно ли сохранить в одной таблице? Приватные сообщения Шардинг в начале, потом очень сложно Что происходит после нажатия кнопки отправить заказ? 4 мин
  4. Разбивка по магазину, JWT токен, микросервисы, внутренние запросы, выбор хранилища
  5. Кусочек данных, перенос между серверами, балансировка, закрытие открытие Что из себя представляет карта?
  6. Просто таблица, неравномерные диапазоны, хост, база, префикс, открытые диапазоны Все ходят в эту таблицу? Нет, офлайн сброс
  7. Абстрактный, спот айди, Выбор спота, переопределить системный метод подключения, Сет подключения в конфиг, выбор таблицы - переопределить
  8. Спотов много, делать запрос к каждому?
  9. Запись и туда и туда, чтение через превью, репликация ()
  10. Листенер, создание, обновление, удаление
  11. Метод поиска, выбор подключения
  12. Что такое релейшнс, связанные таблицы, ограничение - один спот, джойны
  13. Коллизии - 5 и 100, уникальный индекс, Кто знает что такое Hashids? Реакция - ты крутой
  14. Сиквенс обычная таблица, несколько попыток перед исключением, Вставка в уникальный индекс, ловим исключение, Ворнинг
  15. Спец родительский класс, отключаем автоинкремент, Указываем спотируемое поле, таблица обычное имя, Релейшны можно, генерация айди, Превью апдейтер, сколько нужно