php yaf框架扩展实践五——数据层
从狭义角度上来理解数据层就是数据库,比较广义的理解来看数据库、远程数据、文件等都可以看做数据层。项目初期的时候一般单一的数据库就可以了,随着流量的增大就要对数据层做很多的改进,例如增加从库分散读压力,使用kv缓存增加系统性能,又或者使用分布式服务这样就会涉及到到远程数据调用。这么多东西该怎么整呢?项目好像越来越乱了。
当涉及的东西多了,如果没有良好的项目结构就会导致项目层次越来越乱,很容易出问题。下面就分享一下在yaf中数据层设计经验。分为如下:
- 数据抽象层DAO
- 数据库Mysql
- KV缓存Redis
- 远程调用Http
yaf扩展数据层
数据抽象层DAO
DAO全称就是Data Access Object,通俗的讲就是数据访问对象。该层提供统一对外的数据访问接口,具体是要调用数据库、http、redis的数据由DAO决定处理。DAO层保存在目录:application/models/DAO
例如我们需要根据用户编号获取用户信息,可以在DAO目录下新建一个User.php文件,其中有一个find方法:
|
1
2
3
4
|
public function find($userId) { $mysql = \Mysql\UserModel::getInstance(); return $mysql->find($userId);} |
这里就是直接从数据库里进行读取。当这个方法调用很频繁,数据库负载上来时,我们考虑使用kv缓存来缓解数据库压力:
|
1
2
3
4
5
6
7
8
9
10
|
$redis = \Redis\Db0\UserModel::getInstance();$user = $redis->find($userId);if (!$user) { $mysql = \Mysql\UserModel::getInstance(); $user = $mysql->find($userId); if ($user) { $redis->update($userId, $user); }}return $user; |
这里先从redis内读取用户信息,如果没有则从mysql里读取。因为使用了redis缓存,如果数据有更新的时候需要同步更新缓存里的内容,这个在DAO层内就很容易做到了。
此外在DAO层的抽象方法里实现了一个方法,当访问的方法不存在的时候会自动调用数据库mysql对应的同名方法,这个在项目前期可以大大提高开发效率,缺点就是当用ide调用的时候没有代码提示。
数据库Mysql
yaf没有提供数据库操作的封装,这里使用了zend framework2的db类库进行数据库的操作。zend framework虽然整体性能慢,但是类库非常齐全、封装的也非常好,这里直接使用zend framework的db库进行操作避免重复造车轮子。mysql的保存目录:application/models/Mysql
创建数据表操作类
mysql层有一个抽象类,定义了表名和表主键属性,文件建议以表名进行命名而后继承mysql的抽象类,在类中指明相应的表和主键就可以了。如用户表文件User.php:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class UserModel extends \Mysql\AbstractModel { /** * 表名 * * @var string */ protected $_tableName = 'user'; /** * 主键 * * @var string */ protected $_primaryKey = 'user_id'; ....} |
在mysql的抽象类里封装了find、fetchAll、insert、update、remove增删改查的方法,可以直接使用User的类实例进行调用,就像上面讲DAO时直接调用find方法。这些方法基本可以满足80%-90%的数据查询需求,倘使需要更加复杂的查询,可以调用父类的_getDbSelect方法获取\Zend\Db\Sql\Select对象自定义查询,关于\Zend\Db\Sql\Select可以参考zend framework手册。
使用从库
如果需要使用从库来进行均衡读负载,可以将从库的操作在mysql/Slave目录,Slave目录下有一个单独的抽象类,因为从库一般用来读,所以这里只封装了find、fetchAll方法。在需要定位到从库时的地方重写相应的find、fetchAll方法就可以了。例如读取用户列表数据可以考虑从从库读取,重写\Mysql\UserModel类的fetchAll方法:
|
1
2
3
4
|
public function fetchAll($columns = null, $where = null, $order = null, $count = null, $offset = null, $group = null) { $slave = \Mysql\Slave\UserModel::getInstance(); return $slave->fetchAll($columns, $where, $order, $count, $offset, $group);} |
Tips:使用从库进行数据读取需要注意数据实时性的问题,虽然从库的数据同步一般都在毫秒级,但是在程序操作中可能出现主库已经插入数据,但是从库读取不到的问题。建议数据实时性要求不高的才从库进行读取。
多个库
有时一个项目涉及到要连接多个数据库,这时候可以考虑在mysql目录下新建目录,目录名使用数据库名进行命名。每个库内的抽象类文件可以考虑继承通用的抽象文件,重写其中的_getAdapter就可以了。
KV缓存Redis
Redis存放在:application/models/Redis目录。同mysql一样,这里也有一个抽象类文件,相应的文件继承该文件就可以了。下面讲下和mysql的不同点。
redis多库
一个redis实例总共有16个库,从db0~db15,在项目中以Db0、Db1这样的目录进行区分,每个db下的抽象类继承默认抽象类,重写$_db属性为相应的库就可以了。例如Db0这个库:
|
1
2
3
4
5
6
7
8
9
10
|
class AbstractModel extends \Redis\AbstractModel { /** * 连接的库 * * @var int */ protected $_db = 0; ....} |
在开发中不建议将所有的缓存都放在一个库下,有的时候我们需要使用keys命令来查找到相应的key,并进行数据更新。如果该库下缓存太多会导致性能很低。建议按照数据的重要性和时效性进行分布存储。
缓存设计思想
kv缓存并没有表的概念,但是为了更好的对应用的整个缓存系统进行操作,这里抽象出表的概念。这里的表相当于key中的一个前缀,通过和id组合成实际的key可以很好的避免key值出现重复。例如上面DAO层从redis读取用户数据,抽象出了一个用户表。
Tips:表名和id是通过一个分隔符号组成,这里是使用横线”-”进行拼接,可以根据实际需要进行修改,只需要保证最后组合成的key是唯一的就OK了。
远程调用Http
项目越来越多、访问量也越来越大,这时候我们考虑将通用的服务提取出来,部署到另外的服务器上。这时候就需要通过网络进行远程调用了,有一个专业术语叫RPC(Remote Procedure Call Protocol)。这里我们使用的http协议,方便在各个语言之间进行通讯, 当然也可以使用一些rpc框架来实现。
Http存放在:application/models/Http目录。抽象类封装了request请求方法。建议以不同的应用进行目录划分,例如我们将用户中心分离出来之后,用户中心的数据可以通过http进行调用。可以在http目录下新建User目录,User目录下的抽象类继承默认抽象类,重新定义host就可以了。
一般来讲一个应用的接口都有统一的数据格式定义,在实际的开发中通常会在User的抽象类中重写父类的request方法,并统一处理相应的数据格式。
小结
这里只列举了mysql、redis等库,类似文件存储、mongodb、memcache、sql server等都可以按照这样的思想进行处理。项目到后期基本上瓶颈都会在数据层上,只要在数据层方面处理妥当了,便能够很好的实施扩展以应对一些高并发场景的情况。
http://www.01happy.com/php-yaf-ext-data/
php yaf框架扩展实践五——数据层的更多相关文章
- 【开源】OSharp框架解说系列(5.2):EntityFramework数据层实现
OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...
- 【开源】OSharp框架解说系列(5.1):EntityFramework数据层设计
OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...
- JAVA 利用反射自定义数据层框架
之前的随笔一直都在介绍c#,主要公司最近的业务都是做桌面程序,那么目前c#中的WPF肯定是我做桌面程序的不二之选,做了半年的WPF,也基本摸清了c#写代码的套路和规则(本人之前是两年多的JAVA开发者 ...
- 教你50招提升ASP.NET性能(五):确保分页是在数据层完成的
(11)Make sure paging is conducted at the database layer 招数11: 确保分页是在数据层完成的 When using grid UI contro ...
- .net通用权限框架B/S (四)--DAL数据层以及数据接口
数据层以及数据接口设计如下图(以g_orga组织机构和g_role角色)为例,这几个类可以通过.tt模版生成 设计参考学习http://www.cnblogs.com/hanyinglong/arch ...
- Golang 网络爬虫框架gocolly/colly 五 获取动态数据
Golang 网络爬虫框架gocolly/colly 五 获取动态数据 gcocolly+goquery可以非常好地抓取HTML页面中的数据,但碰到页面是由Javascript动态生成时,用goque ...
- php 安装yaf扩展和yaf框架
一.安装yaf扩展(windows安装) 1.查看你电脑安装的开发环境(phpinfo()的信息),查找 "Zend Extension Build"和"PHP Exte ...
- CYQ.Data 开源数据层框架 官方下载
CYQData 数据框架 介绍: CYQ.Data 是一款操作数据库用的数据框架:安全稳定.简洁易用.功能强大.性能优越.内置支持多数据库.多语言.RSS.AOP.事务等功能. 使用本框架进行开发,入 ...
- windows下扩展yaf,并生成yaf框架文件
YAF中文文档:http://www.laruence.com/manual/index.html 1 YAF框架是用C开发的,属于PHP的扩展框架: 2 YAF的性能相对于源生PHP,性能只降低不到 ...
随机推荐
- [HTML5] Add an SVG Image to a Webpage and Get a Reference to the Internal Elements in JavaScript
We want to show an SVG avatar of the patio11bot, so we'll do that in three ways: Using an img tag - ...
- [Functional Programming ADT] Combine Multiple State ADT Based Redux Reducers
Redux provides a convenient helper for combining many reducers called combineReducer, but it focuses ...
- 我的mini_c语言文法设计
//这个文件主要是用来描述当前源语言的词法结构和语法结构 //当前语言是c语言的一个子集,因此里面所有的描述大家都很熟悉 //注意,当前语言并不支持预处理,因为c预处理比较复杂,而且楼主能力低下,因此 ...
- 解决oracle和plsql乱码问题
oracle 10g装上后,建了个表写入中文数据,发现通过工具DbVisualizer 6.5 写入/读取中文都正常,就sqlplus和PL/SQL Developer不正常. 初步怀疑是DbVisu ...
- Firefly 性能测试 通报
http://bbs.gameres.com/forum.php?mod=viewthread&tid=220516 Firefly 性能测试 主要考虑点 网络IO的并发 进程间通信压力 数据 ...
- Windows下如何安装 Composer
如何安装 Composer Windows下如何安装 Composer 下载 Composer 安装前请务必确保已经正确安装了 PHP.打开命令行窗口并执行 php -v 查看是否正确输出版本号. 打 ...
- user-defined conversion
http://en.cppreference.com/w/cpp/language/cast_operator
- 05-hibernate注解-多对一单向外键关联
多对一单向外键 1,多方持有一方的引用,比如:多个学生对应一个班级(多对一) 2,@ManyToOne(cascade={CascadeType.ALL}, fetch=FetchType.EAGE ...
- Tomcat日志、项目中的log4j日志、控制台——我的日志最后到底跑哪去了?
1.Tomcat自带日志功能,即时你的项目中有log4j也不会影响到Tomcat自己记录日志. 2.你的项目中的log4j中的日志指定打印到什么地方(控制台或者文件),便会打印到什么地方,和Tomat ...
- JMX 学习
http://blog.csdn.net/qiao000_000/article/category/763467