redis 实践—— sorted set, hash set
在这里就不谈redis的安装与启动啦,网上太多人写这个了。
从最近的一个项目【钻石夺宝】说起,如果大家有玩过一元夺宝或者全名夺宝的话,大概会知道如果参与人数多的话,每隔几秒、快的话每隔一秒都会新生成一期,虽然app的流量不多,但还要先确定好如何生成期数。
第一个问题来了,那怎样生成期数呢,自己想到的方法就是根据年月日时分秒毫秒 如果是在2016年08月21日11时57分30秒123毫秒生成的话,则把这些数字拼接在一起,
20160821115730123
看样子感觉不错,但是这样子真的好吗?期数肯定要是独一无二的(原子性),第二个问题来了,如果刚好有两期同时生成呢?
不要怀疑这个可能,这样子就会造成串期了。而且涉及到钱,不可以这样子马虎。思考啊思考啊,这个时候想到redis。。。
好吧,写到这里,终于和标题有一点联系了。
老实说,一开始就只想到redis的字符串命令,incr , 看到 incr这个命令,我觉得你也知道要怎样做了,利用redis 的原子性(原子意味着操作的不可再分,要么执行要么不执行),用当前日期作为键,值得话从1递增。 比如今天是2016年8月21日 一开始是长这样子的,生成299期
201608211,201608212,201608213,201608214,···,2016082110 ,```,20160821299
但是期数越多的话,就感觉越难看了,201608211,20160821299放到一起,位数都不一样。
给你们看一个数字, 86400,会不会很熟悉,这个是一天的秒数,考虑到实际上一秒一期也至少能满足目前的需求,决定除了基本的日期,再拼接5位的期数:如2016082100001。
// js
let str = '0000' + 1
str = str.slice(str.length - 4)
console.log(str)
// 输出 00001
当然,在redis里面的话,还是1,2,3···的啦。
写到这里,正常来说应该是结束的了,但总是感觉有地方不对,如果其他同事也用了日期作为键呢,如果在这个夺宝项目中其他地方也有类似的需求呢(有的同学会说加个项目前缀不就可以了吗,虽然可以!!!),但这个时候,【sorted set】出场了,它长得帅!
语法:
ZINCRBY key increment member
以 夺宝项目【treasure】为【sorted set】的key, 以当前时间年月日为 member (成员), 每次递增1
ZINCRBY 'treasure',1,'20160821'
如果要查看最近10天的成员以及生成的期数:
ZRANGE treasure 0 10 WithScores
为什么用sorted set 的原因不是因为帅,实际上,运营人员希望拿到了期数生成最多的日期及期数,ZREVRANGE 命令就可以做到了
语法:
ZREVRANGE key start stop [WITHSCORES]
//返回有序集中指定区间内的成员,通过索引,分数从高到底
实例:
ZREVRANGE treasure 0 10 WITHSCORES
当然还有很多理由用sorted set的!!!!
sorted set 更多用法可参见:
http://www.runoob.com/redis/redis-sorted-sets.html
实际项目中,是用 hash set 实现的,在一个key上新增field(日期),然后递增field的值,今天写这文章的时候,一边查阅资料,一边在思考采取哪种redis的数据类型才是正确的,最终决定用sorted set替换原本的 hash set。
【hash set】 更适合 存储对象 比如 新增key
HMSET key field value [field value ...]
结合实际:
HMSET treasure_user:001 name "xiaochi" age "26"
HMSET treasure_user:002 name "zhaomei" age "25"
夺宝项目中还用到redis的【锁】,找个时间的话,也写一下为什么要用到锁,怎样用锁。