redis在分布式系统中的应用

Posted by Hsz on April 13, 2019

redis在分布式系统中的应用

redis作为一个key-value内存数据库,因为其附带有性能优越的多种数据结构,在应用上带来了很多附加功能呢.在分布式系统中redis常作为一些特殊的中间件存在而非单纯的内存数据库.本文将总结这些特殊用法.

全局计数器

redis可以使用$2^64$ 而pg序列最大只能到$2^31$虽然都已经是天文数字了但依然有巨大的差异.而一般数据库一旦做分表,那系统给的自增id,无论是pg的series,还是mysql的AUTO_INCREMENT都无法简单扩展,像我之前用pg就没有考虑到这点,因此后来设计按天分表后不得不去掉主键约束.

如果使用redis的自增就可以一定程度上解决这个问题.

  • INCR <key>自增,每次加1
  • INCRBY <key> <amount>自增,每次加amount

注意做全局计数器的机器最好做好主备集群.防止有机器蹦了后信息消失

扩展–在线用户查询

如果用户数量又超大那我们要查看某个用户在不在线就成了问题,如果刚好我们的用户id是整型,比如是用全局计数器生成用户id,那还有一个扩展应用就是可以快速查找用户是否在线,原理很简单,使用setbit <key> <offset> <value>

使用redis的用户id作为offset,如果用户登录了就为这个offset的value置1,下线了就为其置0,这样我们要知道一个用户是否在线只要用它的id作为offset使用命令GETBIT <key> <offset>查询即可,是1就在线是0就不在线,而如果要统计在线人数只需要使用BITCOUNT <key>就可以查出来.

分布式锁

有时候页面卡我们会习惯性的连续点击提交,这就会造成重复请求,尤其在还有负载均衡的情况下,这些请求还可能给发给不同的服务器.如何避免呢?我们可以用请求的ip+url+request做hash作为key,设置setnx <key> <value>

这个命令会在没有key时设置key的值为value且返回1,当已经有key时无论怎么用setnx设置这个key的value都会返回0通常我们会给它设置一个过期时间,比如3s

setnx <key> <value>
EXPIRE <key> <seconds>

这样就达到了一定时间内无法重复提交请求的效果

扩展–限流

限流其实也算一种分布式锁了,我们可以固定一些接口的访问流量防止被恶意攻击,我们可以使用redis插件redis-cell,安装好插件的redis镜像我已经发布在hsz1273327/redis-cell,使用上可以去镜像站查看用法

快速排序

Redis的有序集合(sorted set)可以快速进行排序,比如做搜索引擎,我们就可以将权重计算做成一个分布式任务,然后将url的权重按命令ZADD <key> <weight> <url>放入redis,需要取值时使用ZRANGE <key> <from> <to> WITHSCORES就可以取出范围内的url了