知识积累-redis使用

需求:网站对登陆的手机号,发短信的次数进行限制(比如说10次),时间限制1天。

想法:redis记录次数(Memcached也可以,但是基于项目中本来已有redis的客户端,就不想费事使用Memcached)

设计:key=“XXX_手机号” ,value="次数",过期用redis客户端带的过期的方法

环境:JQuery+SpringMVC+redis(redis 用的是非集群),

           redis客户端用的是ShardedJedis


问题:使用客户端设置的过期时间各种不起效,如下几种方式

//key,seconds,value
jedis.setex("name",30,"xiaohua");
//key,seconds
jedis.expire("name",20);
//key,value,xx,EX = seconds; PX = milliseconds,过期时间
jedis.set("name","xiaohua","XX","EX",60l);
//key,seconds,value
jedis.setex("name",30,"xiaohua");

 解决思路:用linux上的redis-cli的命令看看设置过期时间是否有效,用到的命令如下:

x.x.x.x 上有redis客户端。                   --(x.x.x.xredis客户端所在机器) 
cd /app/redis/bin/
./redis-cli -c -h D.D.D.D -p 6379       --(D.D.D.Dredis服务器) 

 实际操作命令如下:

 

 

命令解释:ttl key (以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)

1.当前key没有设置过期时间,所以会返回-1.
2.当前key有设置过期时间,而且key已经过期,所以会返回-2.
3.当前key有设置过期时间,且key还没有过期,故会返回key的正常剩余时间.

所以按照这个解释的话,返回0肯定是不对的,有时候也返回-1,但是也不对,应该返回-2的,过期了key肯定要不在的。所以问题出在哪??

找了另外一个组的redis,看了他们的过期时间的使用,跟我的一样,所以肯定不是代码问题,我就用redis-cli连他们的机器,同样执行上面的操作,结果如图:



 

同样的操作,这个redis的服务器就可以,说明是机器的事情,然后我就找专门负责redis机器的同事看了下,我一直以为是redis安装的问题,但是最后才发现,其实不是,问题的根源在于,我的用的是redis的非集群,而另外一组的同事的用的是集群的redis。查了谷歌发现有如下描述



 

查看下我使用的redis的服务器如下图:



 

 

其中slaveof的意思如下:

对一个从属服务器执行命令 SLAVEOF NO ONE 将使得这个从属服务器关闭复制功能,并从从属服务器转变回主服务器,原来同步所得的数据集不会被丢弃。
利用『 SLAVEOF NO ONE 不会丢弃同步所得数据集』这个特性,可以在主服务器失败的时候,将从属服务器用作新的主服务器,从而实现无间断运行。

几经周折,终于问题得到定位,那么回归到我本身的需求来说,本来是想通过redis客户端自身的设置过期的时间来做1天的限定的,现在不可能为了这个而去吧redis的服务器部署方式给改了,所以只得另想办法。



策略:key依然不变,但是value的更改下设计,原来放的是一个单纯的数字,记录的次数,现在改成一个对象(当然存放到redis中我肯定会序列化成json格式的字符串的),对象里面有两个字段(时间和次数,其中时间精确到天就可以了),要这个时间字段的用处是我每次根据key取redis数据的时候,获取的对象的时间和当前的时间做对比,如果是同一天就说明没过期,然后只用次数+1就可以了,如果不是同一天说明已经过期了,然后直接更新这个对象的时间和初始化次数,然后重新放入redis就可以了。

总结:一开始一直想着是服务器的问题,要从服务器角度出发,但是最终想到解决办法的时候,又觉得自己过于死板,客户端解决不了的问题,完全可以自己用代码去设计然后解决。所以以后在使用和设计上应该多些自己的想法......

~~~~~~~~纯个人项目遇到的问题总结,如能帮上您,我很开心,如有错误或者不严谨的地方,还望指教!~~~

猜你喜欢

转载自anbolihua.iteye.com/blog/2337907