用redis实现社交产品中计数器

社交产品业务里有很多统计计数的功能,比如:

统计计数的特点

    实时性要求高 写的频率很高 写的性能对MySQL是一个挑战

可以采用redis来优化高频率写入的性能要求。

redis优化方案一

对于每一个实体的计数,设计一个hash结构的counter:

redis相关的命令

缺点:

这样设计,如果要批量查询多个用户的数据,就比较麻烦,例如一次要查指定20个userID的计数器?只能循环执行 HGETALL counter:user:{userID}。

优点:

以实体聚合数据,方便数据管理

redis优化方案二

方案二是用来解决方案一的缺点的,依然是采用hash,结构设计是这样的:

counter:user:praiseCnt
						->  userID_1001: 100
						->  userID_1002: 200
						->  userID_1003: 332
						->  userID_1004: 123
								.......
						->  userID_9999: 213



counter:user:hostCnt
						->  userID_1001: 10
						->  userID_1002: 290
						->  userID_1003: 322
						->  userID_1004: 143
								.......
						->  userID_9999: 213


counter:user:followCnt
						->  userID_1001: 21
						->  userID_1002: 10
						->  userID_1003: 32
						->  userID_1004: 203
								.......
						->  userID_9999: 130
HMGET counter:user:praiseCnt userID_1001 userID_1002

优点:

解决了批量操作的问题

缺点:

当要获取多个计数器,比如同时需要praiseCnt,hostCnt时,要读多次,不过要比第一种方案读的次数要少。 一个hash里的字段将会非常宠大,HMGET也许会有性能瓶颈。

用redis管道(Pipelining)来优化方案一

对于第一种方案的缺点,可以通过redis管道来优化,一次性发送多个命令给redis执行:

$userIDArray = array(1001, 1002, 1003, 1009);

$pipe = $redis->multi(Redis::PIPELINE);
foreach ($userIDArray as $userID) {
	$pipe->hGetAll(counter:user: . $userID);
}

$replies = $pipe->exec();
print_r($replies);

还有一种方式是在redis上执行lua脚本,前提是你必须要学会写lua。

社交产品业务里有很多统计计数的功能,比如: 统计计数的特点 实时性要求高 写的频率很高 写的性能对MySQL是一个挑战 可以采用redis来优化高频率写入的性能要求。 redis优化方案一 对于每一个实体的计数,设计一个hash结构的counter: redis相关的命令 缺点: 这样设计,如果要批量查询多个用户的数据,就比较麻烦,例如一次要查指定20个userID的计数器?只能循环执行 HGETALL counter:user:{userID}。 优点: 以实体聚合数据,方便数据管理 redis优化方案二 方案二是用来解决方案一的缺点的,依然是采用hash,结构设计是这样的: counter:user:praiseCnt -> userID_1001: 100 -> userID_1002: 200 -> userID_1003: 332 -> userID_1004: 123 ....... -> userID_9999: 213 counter:user:hostCnt -> userID_1001: 10 -> userID_1002: 290 -> userID_1003: 322 -> userID_1004: 143 ....... -> userID_9999: 213 counter:user:followCnt -> userID_1001: 21 -> userID_1002: 10 -> userID_1003: 32 -> userID_1004: 203 ....... -> userID_9999: 130 HMGET counter:user:praiseCnt userID_1001 userID_1002 优点: 解决了批量操作的问题 缺点: 当要获取多个计数器,比如同时需要praiseCnt,hostCnt时,要读多次,不过要比第一种方案读的次数要少。 一个hash里的字段将会非常宠大,HMGET也许会有性能瓶颈。 用redis管道(Pipelining)来优化方案一 对于第一种方案的缺点,可以通过redis管道来优化,一次性发送多个命令给redis执行: $userIDArray = array(1001, 1002, 1003, 1009); $pipe = $redis->multi(Redis::PIPELINE); foreach ($userIDArray as $userID) { $pipe->hGetAll(counter:user: . $userID); } $replies = $pipe->exec(); print_r($replies); 还有一种方式是在redis上执行lua脚本,前提是你必须要学会写lua。
经验分享 程序员 微信小程序 职场和发展