你真的了解Redis忙?(一)

redis的基础数据结构

1.String

常见命令:set get incry decr

2. hash

常见命令:hmset hmget hkeys

3. set(集合)

常见命令:sadd smembers

4. list

常见命令:lpush lpop

5. zset (有序集合)

常见命令:zadd
zcard (获取有序集合的成员数)
zremrangebyscore (命令用于移除有序集中,指定分数(score)区间内的所有成员)
zrange (通过索引区间返回有序集合指定区间内的成员)

6.HyperLogLog

作用:是用来做基数统计的算法,每个key只需要花费 12 KB 内存 标准误差在0.81%
常见命令;pfadd pfcount
使用场合:用于统计UV 和PV

7.GeoHash

简单介绍:如果利用数据库来算"附近的人"?如果使用关系型数据库,如何存储?大家都用过摩拜单车 ,就会查看附近的车辆。Redis 提供了Geo 指令 一共有6个
常见命令:
geoadd 指令携带集合名称和经纬度以及三元组
geoadd company 118.2901 39.0909 alibaba
geoadd company 209.2102 39.9028 jd
geolist 指令计算两个元素之间的距离,携带集合名称,距离单位。
geolist company alibaba jd km
geohash 获取元素的hash 值
geohash company jd 返回的是base32位编码。
georadiusbymember 指令用来查询指定元素附近其他的元素。
georadiusbymember company jd km count 3 asc 范围20公里以内最多3个元素按照距离正序排列。

8.布隆过滤器

应用场景:我们在使用新闻客户端看新闻时,他会给我们推荐新的内容,他每次推荐都会去重,去掉那些看过的内容。如果历史记录存再关系型数据库里,需要频繁的exists查询,当系统并发量很高时,数据库是很难抗拒压力的。
常见命令:bf.add bf.exists (bf.madd和bf.mexists)
缺点:不是特别精确,会误判,也不是特别不准确,只要参数设置合理,它的准确的可以很高。

9.位图

开发场景:平时开发中,我们都需要对一些bool 类型的数据进行存取,比如用户一年签到的数据。签了为1 没签到就是0 。如果有普通的key/value 那么当用户上亿 需要的存储空间 是惊人的。
为了解决这个问题我们可以使用redis提供的位图这种数据结构。每个签到就占一个位,365天就365个位。
常用命令:getbit setbit bitcount bitpop bitfield
Key的格式为u:sign:uid:yyyyMM

# 用户2月17号签到
setbit u:sign:1234:201802 16 1  # 偏移量是从0开始,所以要把17减1
# 检查2月17号是否签到
getbit u:sign:1234:201802 16
# 统计2月份的签到次数
bitcount u:sign:1000:201902
 获取2月份前28天的签到数据
bitfield u:sign:1000:201902 get u28 0
# 获取2月份首次签到的日期
bitpos u:sign:1000:201902 0 # 返回的首次签到的偏移量,加上1即为当月的某一天

redis的分布式锁

redis除了上述 应用 还可以用于做分布式锁。举个栗子
redis中缓存了一个int值 现在有两个客户端需要同时读取这个数,然后+20,次数就会出现并发问题 如下图


redis分布式锁.png

redis的分布式锁 其实就是占坑,当别的进程进来的时候,发现已经有人了,那么就会放弃或者稍后再试。
命令

setnx  //命令 
setnx lock:user:123 true
do something
del lock:user:123

那么就会出现问题,如果do something 出现异常了,锁就没有释放,这样就会永远陷入死锁,永远不会释放。

解决方案1. 给锁设置失效时间
setnx lock:user:123 true
expire lock:user:123 5
//do something
del lock:user:123

此时也会有问题 ,如果在加锁和设置锁超时之间服务器挂掉了,那么锁也不会得到释放,究其原因是因为:加锁和设置时间不是原子指令。如果这两条指令一起执行就不会有问题。
redis2.8 版本以上加入了set 指令的扩展,是的setnx 和expire一起执行,

set lock:user:123 true ex 5 nx ok
//do something
del lock:user:123

缺陷:
1.不能解决超时问题:如果加锁或者释放锁的执行时间过长,超出了锁的时间限制,就会出现问题。

利用redis做简单限流:

案例:如果有几片文章,我们限制这个用户几分钟内只能回复几次,就可以用redis来做简单限制
方案:我们使用zset 结构,score为时间戳,value唯一就行。可以把zset中的score看做一个窗口 ,我们只维护窗口以内的数据。

  /**
    userId:用户编号
    userAction:用户事件,比如点赞,回复评论。
     provit:限制事件,单位为秒
     maxcount:次数
    **/
    public boolean isAllowAction(int userId,String userAction,int provit,int maxCount) throws IOException {
        String key = String.format("userAction:%d:%d",userId,userAction);
        Jedis jedis = new Jedis();
        long systemTime = System.currentTimeMillis();
        Pipeline pipeline = jedis.pipelined();
        pipeline.multi();
        pipeline.zadd(key,systemTime,systemTime+"");
        pipeline.zremrangeByScore(key,0,systemTime - provit * 1000);
        Response<Long> userAccount = pipeline.scard(key);
        pipeline.expire(key,provit+1);
        pipeline.exec();
        pipeline.close();
        return userAccount.get() > maxCount;
    }

如何查询redis中的某个Key呢?

1.简单暴力用keys 和正则表达式 keys * ;如果redis中有成千上百万的key 这样会不会太慢了?而且keys 命令是遍历所有的Keys,如果在线上环境,使用改命令,则会造成redis卡顿,redis 为单线程。keys 命令的时间复杂度为O(n).
2.使用Scan命令 同keys 一样 他也提供了匹配的功能,提供了limit参数 返回结果可多可少。
命令:scan 0 match user_* count 1000; 一共有三个参数,第一个是cursor 整数值,第二个key则为正则表达式,第三个则为limit him (limit 1000 不是限定返回结果的数量,而是限定单次服务器遍历的字典槽位数量)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • Redis是啥 Redis是一个开源的key-value存储系统,由于拥有丰富的数据结构,又被其作者戏称为数据结构...
    一凡呀阅读 1,170评论 0 5
  • 使用缓存是系统性能优化的第一黄金法则。 缓存的设计和使用对一个系统的性能至关重要,平时接触到项目无论多少也都会在某...
    刀刃丿阅读 1,328评论 0 6
  • 1.1 资料 ,最好的入门小册子,可以先于一切文档之前看,免费。 作者Antirez的博客,Antirez维护的R...
    JefferyLcm阅读 17,030评论 1 51
  • 五种数据结构简介 Redis是使用C编写的,内部实现了一个struct结构体redisObject对象,通过结构体...
    彦帧阅读 6,931评论 0 14
  • 在原生家庭说里,对于影响孩子未来人格性格品格三格确立的最大的成因,就是父母和家庭这个结论,有着详尽的解释,我本人有...
    花园里的皮皮阅读 1,338评论 0 2