Redis的基本数据类型

Redis共五种基本数据类型:string、list、hash、set和zset

一、string

Redis的字符串是动态字符串,采用预分配冗余空间的方式来减少内存的频繁分配。当字符串长度小于1M时,扩容方式为翻倍空间,如果超过1M,扩容时一次只会多扩1M的空间。需要注意的是:字符串最大长度为512M。

set ireader helloworld //初始化字符串
get ireader //获取字符串内容
strlen ireader //获取字符串长度
getrange ireader 3 6 //获取字符串子串
setrange ireader 4 aaa //覆盖子串,长度为替换的字符串长度
append ireader hhhh //追加子串

//若字符串内容为整数,可以当计算器来使用,计数器是有范围的,它不能超过Long.Max,不能低于Long.MIN
incrby ireader 100
decrby ireader 100
incr ireader //等价于 incrby ireader 1
decr ireader //等价于 decrby ireader 1

expire ireader 60 //60秒后过期删除,返回1表示设置成功,返回0表示ireader不存在
ttl ireader //返回剩余过期时间,返回-2表示ireader不存在,返回-1表示没有设置过期时间

二、list

Redis中的list为双向链表,所以随机定位性能较弱,首位插入删除性能较优。

负下标 链表元素的位置使用自然数0,1,2,....n-1表示,还可以使用负数-1,-2,...-n来表示,-1表示「倒数第一」,-2表示「倒数第二」,那么-n就表示第一个元素,对应的下标为0。

队列/堆栈 链表可以从表头和表尾追加和移除元素,结合使用rpush/rpop/lpush/lpop四条指令,可以将链表作为队列或堆栈使用,左向右向进行都可以

rpush ireader java
lpush ireader go python
lpop ireader
rpop ireader

llen ireader //获取链表长度
lindex ireader 1 //读取指定位置元素
lrange ireader 0 2 //读取下标0-2的元素
lrange ireader 0 -1 //读取所有元素

lset ireader 1 javascript //修改指定位置元素
lrem ireader 1 java //需要指定删除的最大个数以及元素的值

ltrim ireader 1 5 //获取定长列表

补充:如果再深入一点,你会发现Redis底层存储的还不是一个简单的linkedlist,而是称之为快速链表quicklist的一个结构。首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也即是压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成quicklist。因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是int类型的数据,结构上还需要两个额外的指针prev和next。所以Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。

三、hash

Redis中的hash结构等价于Java中的HashMap结构,实现结构上为二维结构,第一维是数组,第二维是链表,hash的key和value存放在链表中,数组存放的是链表的头指针,链表的作用是串联【hash碰撞】


hash结构图.png
hset ireader go fast //增加元素
hmset ireader java fast python small //增加多个元素
hget ireader go //获取单个元素
hmget ireader java python //获取多个元素
hgetall ireader //获取全部元素
hkeys ireader //获取所有key
hvals ireader //获取所有value
hdel iredaer java go //删除多个元素
hexists ireader go //判断元素是否存在

//hash结构还可以当计数器使用,若value不是整数,调用hincrby指令会出错
hincrby ireader java 1

扩容 当hash内部的元素比较拥挤时(hash碰撞比较频繁),就需要进行扩容。扩容需要申请新的两倍大小的数组,然后将所有的键值对重新分配到新的数组下标对应的链表中(rehash)。如果hash结构很大,比如有上百万个键值对,那么一次完整rehash的过程就会耗时很长。这对于单线程的Redis里来说有点压力山大。所以Redis采用了渐进式rehash的方案。它会同时保留两个新旧hash结构,在后续的定时任务以及hash结构的读写指令中将旧结构的元素逐渐迁移到新的结构中。这样就可以避免因扩容导致的线程卡顿现象。

缩容 Redis的hash结构不但有扩容还有缩容,从这一点出发,它要比Java的HashMap要厉害一些,Java的HashMap只有扩容。缩容的原理和扩容是一致的,只不过新的数组大小要比旧数组小一倍。

四、set

Java程序员都知道HashSet的内部实现使用的是HashMap,只不过所有的value都指向同一个对象。Redis的set结构也是一样,它的内部也使用hash结构,所有的value都指向同一个内部值。

sadd ireader go java python //增加元素(可多个)
smembers ireader //获取所有元素
scard ireader //获取集合长度
srandmember ireader //随机获取count个元素,默认个数为1

srem ireader go java //删除一个到多个元素
spop ireader //spop删除一个随机元素

sismember ireader java //判断单个元素是否存在

五、zset

zset是Redis提供的一个非常特别的数据结构,一方面它等价于Java的数据结构Map<String, Double>,可以给每一个元素value赋予一个权重score,另一方面它又类似于TreeSet,内部的元素会按照权重score进行排序,可以得到每个元素的名次,还可以通过score的范围来获取元素的列表。
zset底层实现使用了两个数据结构,第一个是hash,第二个是跳跃列表,hash的作用就是关联元素value和权重score,保障元素value的唯一性,可以通过元素value找到相应的score值。跳跃列表的目的在于给元素value排序,根据score的范围获取元素列表。

跳表结构.png
zadd ireader 4 python 1 java 2 go //添加元素
zcard ireader //通过指令zcard可以得到zset的元素个数
zrem ireader go java //删除元素y
zincrby ireader 1 python //计数器
zscore ireader python //获取分数
zrank ireader java //获取排名

zrange ireader 0 -1 //获取所有元素
zrange ireader 0 -1 withscores //获取所有元素和分数,按分数从小到大
zrevrange ireader 0 -1 withscores //按分数从大到小

zrangebyscore ireader 0 5 //通过zrangebyscore指令指定score范围获取对应的元素列表。
zrangebyscore ireader -inf +inf withscores //正向是由小到大,负向是由大到小。参数-inf表示负无穷,+inf表示正无穷。
zrevrangebyscore ireader -inf +inf withscores

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