zoukankan      html  css  js  c++  java
  • Redis数据类型

    今天来学习redis的基础数据类型,redis中一共有五种数据类型,分别是:string,hash,list,set,zset。下面分别进行介绍。

    一、string(字符串)

    字符串类型是redis最基础的数据类型,它能存储任何形式的字符串,包括二进制数据。一个字符串类型允许存储的数据最大容量是512M。字符串是其他4种数据类型的基础。

    1 字符串相关命令

    1)GET/SET命令

    SET key value    #给key赋值
    GET key          #获取key的值
    127.0.0.1:6379> SET str 'hello,world'
    OK
    127.0.0.1:6379> GET str
    "hello,world"

    当键不存在时返回空值。

    2)INCR递增命令

    字符串类型可以存储任何形式的字符串,当存储的字符串是整数形式时,可以用incr命令让它自动递增。

    INCR key
    127.0.0.1:6379> INCR bar
    (integer) 2
    127.0.0.1:6379> INCR bar
    (integer) 3

    当键不存在时,会自动创建该键并从0开始递增。

    2 字符串实践

    1)文章访问量统计

    博客常见的一个功能就是统计文章的访问量,这里我们可以为每篇文章使用名为post:id:page.view的键来记录文章的访问量,每次有人访问的时候用incr命令为该键递增。

    键的命名规则:对象类型:对象id:对象属性

    如:user:1:friends 表示id为1的用户的好友列表,增加易读性和可维护性。

    2)生成自增ID

    怎么为每篇文章标示一个唯一ID呢?在关系型数据库中可以用auto_increment,但是在redis中可以通过另一种模式实现:对每一类对象使用名为对象类型(复数形式):count的键来存储当前对象类型的数量,没增加一个新对象就对该值进行递增。

    3)存储文章数据

    文章数据包括标题、内容、发布时间等字段,而我们知道一个字符串类型只能存储一个字符串,那么如何存储文章数据呢?因为字符串类型可以存储二进制数据,可以采用MessagePack进行序列化,速度更快,占用空间更小。下面是伪代码:

    #获得新文章ID
    $postid = INCR posts:count 
    #将博客文章诸多字段序列化成字符串
    $serialpost = serialize($posttitle,$content,$author,$time)
    #将序列化后的文章存储到字符串中
    SET post:$postid:data = $serialpost
    
    #从redis中读取id=42的文章数据
    $serialpost = GET post:42:data
    #将文章反序列化成各个字段
    $posttitle,$content,$author,$time=unserialize($serialpost)
    #获取文章的访问数量
    $count = INCR post:42:page.view

    3 字符串相关扩展命令

    1)增加指定整数

    INCRBY key increment
    
    127.0.0.1:6379> GET goo
    "2"
    127.0.0.1:6379> INCRBY goo 3
    (integer) 5

    2)减少指定整数

    DECR key
    DECRBY key value
    127.0.0.1:6379> GET goo
    "5"
    127.0.0.1:6379> DECR goo
    (integer) 4
    127.0.0.1:6379> DECRBY goo 2
    (integer) 2

    3)向尾部追加值

    APPEND key value,如果该键不存在则将该value设为键的值,返回值是追加后的长度。

    127.0.0.1:6379> GET str
    "hello,world"
    127.0.0.1:6379> APPEND str ',zhao'
    (integer) 16
    127.0.0.1:6379> GET str
    "hello,world,zhao"

    4)获取字符串长度

    STRLEN key

    127.0.0.1:6379> STRLEN str
    (integer) 16

    5)同时设置/获取多个键值

    MGET/MSET key1 key2 ....

    127.0.0.1:6379> MGET str goo bar
    1) "hello,world,zhao"
    2) "2"
    3) "3"

    二、hash(散列类型)

     1、简介

    hash类型的键值是字典结构,其存储了字段和字段值的映射,但是字段值只能是字符串,不支持其他类型,也就是说,hash类型不支持类型的嵌套,一个hash类型键最多包括2的32次方-1个字段(除了hash,其他类型也不支持类型嵌套)。

    hash类型最适合存储对象了,我们一般使用对象类别:ID表示键名,使用字段表示对象的属性,而字段值存储属性值,下面具体例子:要存储电脑ID为5的对象,可以分别使用名为color,name和price的3个字段来存储该电脑的颜色、名称和价格,存储结构如下图所示:

    我们回想下如果用关系型数据库来存储该数据,存储结构应该这样:

    这种以二维表的形式存储关系型数据,所有的对象都要有相同的属性,试想,如果我想为ID为1的电脑添加一个保修期限,是不是所有的都需要添加这个属性,那么对于其他的就属于冗余了。而采用redis的hash类型可以自由地为不同对象添加不同的字段和属性。

    2、相关命令

     1)赋值与取值

    HSET key field value
    HGET key field
    HMSET key field value [field value ...]
    HMGET key field [field...]
    HGETALL key

    HSET用来给字段赋值,它不区分是更新还是插入操作,这意味如果着修改数据时无需考虑该字段是否存在,插入操作返回1,更新返回0;HGET获取字段的值,

    127.0.0.1:6379> HSET car:1 color red
    (integer) 1
    127.0.0.1:6379> HSET car:1 name BMW
    (integer) 1
    127.0.0.1:6379> HSET car:1 price 1200000
    (integer) 1
    127.0.0.1:6379> HGET car:1 color
    "red"
    127.0.0.1:6379> HGET car:1 name
    "BMW"
    127.0.0.1:6379> HGET car:1 price 
    "1200000"
    127.0.0.1:6379> HGETALL car:1
    1) "color"
    2) "red"
    3) "name"
    4) "BMW"
    5) "price"
    6) "1200000"
    127.0.0.1:6379> HSET car:1 color yellow   #该字段已存在,故返回状态0
    (integer) 0

    2)判断字段是否存在

    HEXISTS key field  #判断字段是否存在,存在返回1,否则返回0,键不存在也返回0
    127.0.0.1:6379> hexists car color #键car不存在返回0
    (integer) 0
    127.0.0.1:6379> hexists car:1 color
    (integer) 1
    127.0.0.1:6379> hexists car:1 color1 #字段color1不存在返回0
    (integer) 0

    3)当字段不存在时赋值

    HSETNX key field value#当字段不存在赋值,返回1;如存在不执行任何操作,返回0;属于原子操作,不会发生竞态条件
    127.0.0.1:6379> hsetnx car:1 price 150000
    (integer) 0
    127.0.0.1:6379> hget car:1 price
    "1200000"
    127.0.0.1:6379> hsetnx car:1 date '2015'
    (integer) 1
    127.0.0.1:6379> hget car:1 date
    "2015"

    4)增加数字

    HINCRBY key field increment  #与字符串的incrby相似
    127.0.0.1:6379> hincrby car:1 price 1000000
    (integer) 2200000

    5)删除字段

    HDEL key field
    127.0.0.1:6379> hgetall car:1
    1) "color"
    2) "yellow"
    3) "name"
    4) "BMW"
    5) "price"
    6) "2200000"
    7) "date"
    8) "2015"
    127.0.0.1:6379> hdel car:1 date
    (integer) 1
    127.0.0.1:6379> hgetall car:1
    1) "color"
    2) "yellow"
    3) "name"
    4) "BMW"
    5) "price"
    6) "2200000"

    6)只获取字段名或字段值

    hkeys key
    hvals key
    127.0.0.1:6379> hkeys car:1  #获取字段名
    1) "color"
    2) "name"
    3) "price"
    127.0.0.1:6379> hvals car:1   #获取字段值
    1) "yellow"
    2) "BMW"
    3) "2200000"

    7)获得字段的数量

    hlen key
    127.0.0.1:6379> hlen car:1
    (integer) 3

    三、List(列表类型)

    1、介绍

    列表可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素,或者获取列表的一个片段。

    redis的列表的内部是用双向链表实现的,故向列表两端添加元素的时间复杂度是O(1),获取越靠近两端的数据速度越快。这意味着即使有一个几千万的列表,获取它的头10条或者尾部10数据也是极快的。不过使用链表的代价是通过索引访问列表元素是很慢的,试想:有3000个人在排队买iphone 6s,这时苹果想找到编号为1699的人,工作人员是不是需要从头或者尾部一个一个数过去啊。但无论队伍有多长,新来的顾客直接加入到队尾就可以了,与队长多少没有任何关系。

    这种的特性很好的应用在以下场景:如社交网站的新鲜事,我们只关心最新的内容,使用列表存储,即使它有几千万条,获取前100条也是很快的。同时列表也适合记录日志,可以保证加入新日志的速度不受列表的长度影响。

    一个列表类型键最多有2的32次方-1个元素。

    2、命令操作

    1)向列表两端添加元素

    lpush key value [value ...]#向列表左边添加元素,返回列表个数
    rpush key value [value...]#向列表右边添加元素,返回列表个数
    127.0.0.1:6379> lpush numbers 0
    (integer) 1
    127.0.0.1:6379> lpush numbers -1 -2 -3
    (integer) 4
    127.0.0.1:6379> rpush numbers 1 2 3
    (integer) 7

    2)获取列表片段

    lrange key start stop  #获取列表一个片段,列表索引是从0开始,包含两边
    127.0.0.1:6379> lrange numbers 0 6
    1) "-3"
    2) "-2"
    3) "-1"
    4) "0"
    5) "1"
    6) "2"
    7) "3"
    #lrange支持负索引,0表示最左元素,-1表示从最右面第一个元素
    127.0.0.1:6379> lrange numbers -2 -1 #从最右面开始,取两个
    1) "2"
    2) "3"
    127.0.0.1:6379> lrange numbers 0 -1  #取所有元素
    1) "-3"
    2) "-2"
    3) "-1"
    4) "0"
    5) "1"
    6) "2"
    7) "3"

    3)从列表两端弹出元素

    lpop key  #从最左面移除元素,返回被移除的元素值
    rpop key  #从最右面移除元素,返回被移除的元素值
    127.0.0.1:6379> lpop numbers
    "-3"
    127.0.0.1:6379> rpop numbers
    "3"

    4)获取列表中元素的个数

    llen key
    127.0.0.1:6379> llen numbers
    (integer) 5

    5)删除列表中指定的值

    lrem key count value

    删除列表中前count个值为value的元素,返回值是删除的个数,根据count的不同,执行有所差异:

    当count=0时,删除列表中所有值是value的元素

    当count>0时,删除从最左边开始,前count个值为value的元素

    当count<0时,删除从最右边开始,前|count|个值为value的元素

    6)获取/设置指定索引的元素值

    lindex key index
    lset key index value
    127.0.0.1:6379> lindex numbers 0
    "-2"
    127.0.0.1:6379> lset numbers 0 1
    OK
    127.0.0.1:6379> lindex numbers 0
    "1"

    7)只保留列表指定片段的元素(也就是删除指定片段之外所有元素)

    ltrim key start stop
    127.0.0.1:6379> lrange numbers 0 -1
    1) "1"
    2) "-1"
    3) "0"
    4) "1"
    5) "2"
    127.0.0.1:6379> ltrim numbers 1 3
    OK
    127.0.0.1:6379> lrange numbers 0 -1
    1) "-1"
    2) "0"
    3) "1"

    这个很有用,与lpush结合可以只显示最新的100个日志数量,如:

    lpush logs $logs
    ltrim logs 0 99

    8)向列表中插入一个元素值

    linsert key before/after pvior value#从左到右查找值为pvior,然后根据第二个参数决定在前面还是后面插入,返回元素个数
    127.0.0.1:6379> lrange numbers 0 -1
    1) "-1"
    2) "0"
    3) "1"
    127.0.0.1:6379> linsert numbers before 0 2
    (integer) 4
    127.0.0.1:6379> lrange numbers 0 -1
    1) "-1"
    2) "2"
    3) "0"
    4) "1"

    9)将元素从一个列表转到另一个列表

    rpoplpush source  destinion #先执行source列表的rpop,然后向新列表中lpush,返回元素值,整个过程原子操作

    四、set(集合类型)

     1、介绍

    集合是一组不重复没有顺序限制的元素,每个集合最多存储2的32次方减1个元素。

    集合的常用操作是向集合中加入或删除元素、判断某个元素是否存在。同时不同集合之间还可以进行并集、交集等操作。

    2、命令操作

    1)增加/删除元素:sadd key member [member...]  /srem key member [member...]

    127.0.0.1:6379> sadd s1 1 2 3
    (integer) 3
    127.0.0.1:6379> srem s1 3
    (integer) 1
    127.0.0.1:6379> smembers s1  #列出集合中所有元素
    1) "1"
    2) "2"

    2)判断元素是否在集合中

    #判断元素是否在集合中,如果在返回1,否则返回0
    sismember key member
    127.0.0.1:6379> sismember s1 1
    (integer) 1 
    127.0.0.1:6379> sismember s1 0
    (integer) 0

    3)集合间运算

    sdiff    key1 key2 [key...]  #差集
    sinter   key1 key2 [key...]  #交集
    sunion   key1 key2 [key...]  #并集

    4)取得集合元素的个数:scard key

    5)进行集合运算并将结果存储

    sdiffstore    key1 key2 [key...]  #差集
    sinterstore   key1 key2 [key...]  #交集
    sunionstore   key1 key2 [key...]  #并集

    一般用在需要进行多步运算时,可以先把部分结果存储起来再进行下一步运算。

    6)随机取得集合元素

    srandomember key [count]  #count表示多个元素,根据count值不同取得值也不一样
    #当count为正数,取得count个不同的元素
    #当count为负数,取得|count|个元素,有可能重复

    7)弹出一个元素:spop key 随机选择一个元素弹出

    五、zset(有序集合类型)

     1、介绍

    有序集合是在集合基础上为每个元素添加一个关联分数,从而通过获得元素分数的高低进行排序,集合元素是不同的,但是关联的分数却可以相同。

    有序集合在某些方面跟列表有些相似:

    相同点:

    • 二者都是有序的
    • 二者都可以获得某个范围内元素

    不同点:

    • 列表是用链表实现的,越靠近两端访问越快,随着元素的增加,访问中间元素变得很慢,这种比较适合如新鲜事、日志类的场景。
    • 有序集合是通过散列或跳跃表实现的,读取中间元素也很快
    • 有序集合更耗费内存
    • 列表不能简单的调整两个元素的位置,但是有序集合可以(通过调整关联的分数)

    2、命令操作

    1)增加元素

    zadd key score member[score member]#如果元素已存在,则用新的分数更新它的分数,返回添加的元素个数
    127.0.0.1:6379> zadd sort 50 tom 60 darren 70 helen
    (integer) 3

    分数不仅支持正数,还支持小数。

    2)获得元素的分数

    zscore key member
    127.0.0.1:6379> zscore sort tom
    "50"

    3)获得/删除排名在某个范围内的元素

    zrange key start stop [withscores]
    zrerange key start stop [withscores]

    zrange表示先按分数从小到大排序后,取得索引从start到stop之间所有的元素,包括两端。加上withscores表示把分数也取得。

    4)获得指定分数范围内的元素

    zrangebyscore key min max [withscores] [limit offset count]
    
    表示先按分数从小到大排序后,取得分数从min到max之间所有的元素,包括两端。如果不希望加上两端的话,只需要在前面加上(,withscores表示把分数也取得。min和max还支持无穷大。后面的 [limit offset count]跟sql中功能一样。

    5)增加某个元素的分数

    zincrby key increment member #返回值是增加后的分数

    6)获得有序集合元素个数:zcard key

    7)获得指定分数范围内的元素个数:zcount key min max

    8)删除有序集合中的元素:zrem key member [member...]

    9)按照排名范围删除元素:zremrangebyrank key start stop

    10)按照分数范围删除元素:zremrangebyscore key min max

    11)获得元素的排名:zrank key member(从小到大) zrevrank key member(从大到小)

    redis中五大数据类型到这里就都说完了,有些命令还是多敲敲才能记住。

  • 相关阅读:
    线程的终止pthread_exit和返回为什么终止的原因
    临界区互斥使用之使用自旋锁
    临界区的同步操作-------------使用信号量 实现
    常用解压操作
    group compare vs pair compare
    两个总体的参数关系
    纳伪|去真
    Ho|H1|p-value|p值与U值|单侧检验
    统计分布近似转化
    样本均值的标准误差|样本均值的标准差|总体标准差|样本标准差|简单随机抽样|样本均值估计|样本方差估计|
  • 原文地址:https://www.cnblogs.com/mysql-dba/p/4993144.html
Copyright © 2011-2022 走看看