好几天没有写博客了,一直忙这写这个积分投票-兑换礼包系统.有很多血泪的教训来分享下:
之前,我一直是写手机接口的,跟前端基本上没有交集,即使有也是给内部提供管理平台,这次可以说给我上了一堂课:
1.实时性:大量的操作是建立在memcache缓存的基础上的,mysql数据库是为了提供数据持久性和记录日志的.因此查询之前会先访问缓存,如果缓存不存在或者失效,去访问数据库.
2.数据量比较大:数据库的索引没有建立到最好.
3.权限的问题,不是所有人都拥有权限可以投票,于是我把拥有权限的用户id放入了一个数组中并放在缓存,同步到数据库里面,最后发现这次投票人数特别多,每次查询一个用户的权限,需要把所有人的权限都拿出来,使用in_array(),来判断,主管发现后,果断改啊,每个用户使用独立的key来保存是否拥有权限.
4.安全性:从前端传递过来的参数要假设是不可靠的,在兑换礼包的时候,我从前端传递过来了礼包的类型和要扣除的积分,放入数据库中,哎!首先悲剧的就是要扣除的积分不能是传递过来的,而是根据礼包的类型来判断.并且要把礼包的类型做出范围配置来检查是否合法.刚写完程序的时候,主管看了看然后请求了一个url: www.example.com/?type=6&score=1,本来第六个礼包要扣除积分80个,结果现在只扣除1个积分用户就领取到了第六个礼包.然后要判断礼包只有六中type应该大于1,小于7.写成配置文件来判断如下:
/**
* @brief 将礼包对应扣除的积分写成配置,不要相信用户提交的数据,
* @return array();
*/
public function getTypes() {
return array(
11 => 5, //礼包1对应扣除的积分5,同下
12 => 10,
13 => 20,
14 => 30,
15 => 50,
16 => 80
);
}
5.防止刷积分的处理:如果用机器大量快速请求,有可能出现服务器挂掉,且出现一个人领取多个礼包,因此将用户id:uid和礼包类型:type做唯一索引:
UNIQUE KEY unique_uid_type
(uid
,type
),
在memcache中存入一个1s过期的key,保证一个uid每秒只能领取一次礼包.
6.一些非实时的数据,采用数据查询时从缓存中读取,不存在再从数据库读取;增删改时清除该key的缓存.下次从数据库读取.结果由于只改变了查询的时候的缓存的key,没有改 增删改 数据时缓存的key,导致数据全部从数据库中读取..因此一定要保证,写入缓存和读取缓存的key保持一致.否则...
7.由于有很多页面,需要共享用户的信息,而用户信息需要经过处理,就把用户的信息放到了__construct()里面,也就是说所有的页面都会处理用户信息,结果有几个页面是不使用用户信息的...
8.命名的规范:对缓存命名时必须遵循团队规范,否则可能会和其他开发人员发生缓存key冲突.
9.特殊字符的编码处理:用户名是utf-8编码的,而程序中是gbk编码的,结果转码后发现,用户名凌乱了.处理办法:copy到txt文档中使用记事本打开,重新复制一遍,很多的用户名中会出现特殊字符比如双引号等,使用:htmlspecialchars();
10.数据表中增加一个create_time,用来记录时间排除bug
11.缓存设置的时间要根据具体的业务逻辑来设计,比如下面的场景:用户投票和兑换积分一般时间不会超过十分钟,因此,一些非实时的缓存的过期时间设置成10分钟就够了
12.将所有权限的检测封装到一个函数中统一处理,是代码更简洁方便
13.json_encode()不能处理gbk编码:json_encode('gbk','utf-8',$array);
这次的任务做的太失败了,太凌乱了,写出来的总结感觉也很凌乱,心情不爽,以后慢慢改吧!记录下来做日志,防止再犯同样的错误
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。