为了弄明白读写分离是如何配置的,我们先来看个例子:
<?phpreturn [ 'default' => [ 'driver' => env('DB_DRIVER', 'mysql'), 'read' => [ 'host' => ['192.168.1.1'], ], 'write' => [ 'host' => ['196.168.1.2'], ], 'sticky' => true, 'database' => env('DB_DATABASE', 'hyperf'), 'username' => env('DB_USERNAME', 'root'), 'password' => env('DB_PASSWORD', ''), 'charset' => env('DB_CHARSET', 'utf8'), 'collation' => env('DB_COLLATION', 'utf8_unicode_ci'), 'prefix' => env('DB_PREFIX', ''), 'pool' => [ 'min_connections' => 1, 'max_connections' => 10, 'connect_timeout' => 10.0, 'wait_timeout' => 3.0, 'heartbeat' => -1, 'max_idle_time' => (float) env('DB_MAX_IDLE_TIME', 60), ], ],];
把稳在以上的例子中,配置数组中增加了三个键,分别是 read, write 和 sticky。 read 和 write 的键都包含一个键为 host 的数组。而 read 和 write 的其他数据库都在键为 mysql 的数组中。

如果你想重写主数组中的配置,只须要修正 read 和 write 数组即可。以是,这个例子中: 192.168.1.1 将作为 「读」 连接主机,而 192.168.1.2 将作为 「写」 连接主机。这两个连接会共享 mysql 数组的各项配置,如数据库的凭据(用户名 / 密码),前缀,字符编码等。
sticky 是一个 可选值,它可用于立即读取在当前要求周期内已写入数据库的记录。若 sticky 选项被启用,并且当前要求周期内实行过 「写」 操作,那么任何 「读」 操作都将利用 「写」 连接。这样可确保同一个要求周期内写入的数据可以被立即读取到,从而避免主从延迟导致数据不一致的问题。不过是否启用它,取决于运用程序的需求。
官网配置链接:
https://hyperf.wiki/2.0/#/zh-cn/db/quick-start?id=%e8%af%bb%e5%86%99%e5%88%86%e7%a6%bb
看了读写分离,配置得这么大略,有没人思考过框架层是如何实现的?
这篇文章的来源是由于我看到了github issue里有一个人提了这个问题
https://github.com/hyperf/hyperf/issues/3079
hyperf mysql主从切换
这个question在github的回答有:
1 便是读操作走读的连接,写操作走写的连接,没有太繁芜的逻辑的
2 实质便是获取sql语句中的关键词,如果有update delete insert之类的关键词命中就利用write的链接,反之利用read的链接
如果答案如上所说,那看看框架源码是如何处理的~
定位到hyperf-->database-->Seeders->Connection.php
里面有一个方法getReadPdo(),这里面有利用到关键字 sticky
/ Get the current PDO connection used for reading. @return \PDO / public function getReadPdo() { if ($this->transactions > 0) { return $this->getPdo(); } if ($this->recordsModified && $this->getConfig('sticky')) { return $this->getPdo(); } if ($this->readPdo instanceof Closure) { return $this->readPdo = call_user_func($this->readPdo); } return $this->readPdo ?: $this->getPdo(); }
看方法的阐明是:Get the current PDO connection used for reading.
为只读sql语句获取链接,八九不离十,大概就从它开始。
连续搜索剖析getReadPdo 的代码,在依次上向查找方法的调用地方
下面列出调用方法之一的利用位置
/ Get the PDO connection to use for a select query. @param bool $useReadPdo @return \PDO /protected function getPdoForSelect($useReadPdo = true){ return $useReadPdo ? $this->getReadPdo() : $this->getPdo();}
/ Run a select statement against the database. /public function select(string $query, array $bindings = [], bool $useReadPdo = true): array{ return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) { if ($this->pretending()) { return []; } // For select statements, we'll simply execute the query and return an array // of the database result set. Each element in the array will be a single // row from the database table, and will either be an array or objects. $statement = $this->prepared($this->getPdoForSelect($useReadPdo) ->prepare($query)); $this->bindValues($statement, $this->prepareBindings($bindings)); $statement->execute(); return $statement->fetchAll(); });}
上面的select方法,大家熟习吗?还不熟习,那你在项目里写的这类语句可否熟习
Db::connection($dbName)->select($sql);
update这些关键字都在connection类里,就不再重复阐述了,大家有兴趣的可以看看。
这篇文章便是浅谈一下,hyperf读写分离框架层的代码位置。
下面问题来了[呆无辜][呆无辜][呆无辜][呆无辜][呆无辜][呆无辜]
1 mysql主从分离有几种方案?有没有现成可利用的方案?
2 依赖框架层的读写分离可靠性怎么样?
3 上面的利用场景是有哪些?
~~路漫漫其修远兮~~
喜好的话就关注我,点个赞吧,感激!
[碰拳]我将开始在头条分享github里的点点滴滴与精良的开源项目,希望大家多多支持。