Redis 常用5大数据类型及应用场景

Redis最为常用的数据类型:

  • 字符串(String)

  • 哈希(hash)

  • 字符串列表(list)

  • 字符串集合(set)

  • 有序的字符串集合(sorted set)

String(字符串)

  • redis中最为基础的数据类型,在redis中是以二进制的方式来存储的,所以存入和获取数据相同。

  • value 最多可以容纳的数据长度是 512M。

  • _ 存储String常用的命令:

            1. 赋值:set 、get 、getset(先设置这个键的值再获取这个键的值)


    image.png

            2. 删除:del


    image.png

            3. 数值增减 : incr、decr


    image.png

            4. 扩展命令:
                    incrby、decrby :增加或者减少指定的值
                    append:追加值,返回字符串长度


    image.png
  • 应用场景 : 最常用的一种数据类型, 普通的key - value 存储都可以归为此类。value也可以为数字。

    如:常规计数:微博关注数、粉丝数
    
    如:计数器:使用 INCRBY 完成统计“点击数”,由于单线程,可以避免并发问题。
    

Hash(哈希)

  • 可以看成一个具有String key 和 String value 的类型,也就是键值对类型。所以适合存储 值对象的信息,如用户名、密码、年龄等等

  • 每一个hash可以存储4294967295个键值对。


    image.png
  • 存储Hash常用的命令:

    1. 赋值:hset:设置一个key - value
                 hmset:设置多个key - value


      image.png
    2. 取值:hget:获取一个属性的值
                 hmget:获取多个属性的值
                 hgetall:获取所有的属性和属性的值


      image.png
    3. 删除:hdel:删除具体值
                  del:删除整个集合


      image.png
    4. 增加数字:hincrby:增加指定定的数字


      image.png
    5. 扩展命令:hexists:判断指定key中的某个属性是否存在,存在返回1
                         hlen:获取属性的数量
                         keys:获得所有的key
                         hvalues:获取所有的value


      image.png
  • 使用场景:

     1. 存储部分变更的数据,如用户数据
    
image.png
  2. 验证前端请求是否重复,可以通过redis进行过滤:每次请求将requset Ip、参数、接口等 
  hash作为key存储,当用户请求过来的时候现在redis中检索有没有这个key,进而验证是不
  是一定时间内过来的重复提交。

List(列表)

  • 简单的字符串列表,可以从 头部 或 尾部 向redis列表添加元素。

  • 列表最大的长度为 2^32-1 ,即每个列表支持超过40亿个元素。

  • -列表类型的两个特性:
             1. 列表中的元素是有序的,这就意味着可以通过下标获取某个元素或者某个范围内的元素列表。

              2. 列表中的元素是可以重复的。

  • 从插入和删除角度:如果是在链表的两头插入和删除元素,这是非常高效的。如果插入和删除的操作是作用在链表的中间,那么效率就会比较低了。
  • -存储数据的方式:

            1. arraylist(数组的方式):所以根据”索引“去”查询“是比较快的,但是“新增”和“删除”比较慢,因为涉及到“位移”操作。

            2. LinkedList方式(双向链表的方式):对每个元素都记录了前后的“指针”,“插入”和“删除”的时候只是改变元素的“指针”指向即可,所以速度“快”。

            3. 双向链表添加数据

            4. 双向链表删除数据

  • -存储List常用的命令:

          1. 两端添加:lpush、rpush

image.png

          2. 查看列表:lrange

image.png

          3. 两端弹出:lpop、rpop

image.png

          4. 获取列表元素个数:llen

image.png

          5. 扩展命令

   <1> pushx :当指定的参数中 key “存在”的时候,可以向关联的list头
            部插入一个具体的值,如果”不存在”,就不会进行插入
image.png
   <2> lrem(lremove):
                    正数:从头开始删除
                    负数:从尾部、开始   0 : 删除所有
image.png
   <3> lset : 设置链表中某个index的角标的元素的值   
               lset mylist 3 mmm : 在第三个角标的时候给他设置值为 mmm
image.png
   <4> insert:插入元素
               linsert mylist before b 11: 在 b 元素之前插入 11
               linsert mylist after b 22 : 在 b 元素之后插入 22
image.png
   <5> rpoplpush:完成插入和弹出操作
image.png
    <6> rpoplpush 使用场景:list列表经常用于一些消息队列的一些服务,多个程序间消息
    的交互。
如: 此时假设一个应用程序正在执行 “lpush” 向链表中去添加新的元素,将这样的程序称为'生
产者' ,另外一个程序正在执行 “rpop” 操作,从链表中取出元素,称为'消费者'与此同时 “消费
者” 元素在取出元素后立刻“崩溃”,由于该消息已经被取出但是没有被正常处理,此时可以认为该
消息已经丢失了,可能会导致业务数据丢失或者业务数据的不一致等现象发生,此时我们可以使用
 “rpoplpush” 命令使消费者在主消息队列中取出元素之后再将它插入到一个 “备份”的队列中,
直到消费者完成正常的逻辑处理之后再将消息从备份中删除,这样可以提供一个守护的线程。当备
份中的消息过期之后,可以将消息重新放回到主消息队列当中,以便其他的消费者可以继续去使用。

  • - 应用场景

           1. twitter 的关注列表、粉丝列表等都可以用 Redis 的 list结构来实现

           2. 抢购:使用redis的原子操作来实现这个“单线程”,首先我们把库存存在good_things:1这个列表中,如果有10件库存,就往列表中push10个数。抢购开始后,每来一个用户,就或从good_things:1中pop一个数,表示抢购成功,列表为空时,表示商品已经被抢完。pop操作是原子性的,此时如果有很多用户同时到达,也是依次执行的。

           3. 最新列表:获取前N个最新登录的用户列表

      // 获取当前登录人
      ret = r.lpush("login:last_login_times", uid)
      //限制列表中输在的数据数量
      ret = redis.ltrim("login:last_login_times", 0, N-1)
      // 获取前N个最新登录的用户Id列表
      last_login_list = r.range("login:last_login_times", 0, N-1)

Set(字符集合)

  • - 与list集合的不同:

    • Set集合不允许出现重复的元素,也就是说重复添加多个相同的元素只会保留该元素的一份copy。

    • 功能上: 在服务器端可以完成多个set之间的聚合计算操作,如 unions,difference,这些都是需要在服务器端完成的,因此可以省掉大量的开销。

    • Set包含的最大元素数量是 4294967295

  • - 存储Set常用的命令:

    • 添加/删除元素:sadd 、srem
image.png
  • 获得指定元素:

      smembers:获取set中的数据
      sismember:判断参数中有没有指定的元素在set里面
    
image.png
  • 集合中的差集运算:

      sdiff:返回集合当中相差的成员(与key的顺序有关系)
      sinter:返回交集(都有的数据)
      sunion:返回并集
    
image.png
  • 扩展命令:

      scard :获取具体数量
      srandmember : 随机返回 set中的成员
      sdiffstore:将相差的值存到一个新的集合上
      sinterstore:两个集合的交集将他们存到新的集合
      sunion: 两个并集的交集将他们存到新的集合
    
image.png
  • - 使用场景:

    • 使用redis的set类型去跟踪一些具有唯一性的数据,

      1. 如:访问某一博客的唯一IP地址的信息,我们只需要在每次访问者访问该博客的时候,将访问者的IP存入到redis当中,然后set类型 会自动的保证IP地址的唯一性

      2. 如:set查询该用户名是否被注册,效率极高

      3. 如:投票系统中,如果在限制用户一天只能只能投票一次,可以将今天日期作为 set 的key,存取用户额投票行为,从而保证投票唯一。

    • 用于维护数据之间的关联关系(利用set类型的服务端聚合)

      1. 如:所有购买某一个电子设备的ID被存储到一个指定的set当中,而购买另外一个电子产品的客户的ID被存储到另外的一个set当中,而如果此时我们想获取由哪些客户同事购买了这两种产品,那么就可以使用它的一个“交集”的操作来完成。
      2. 如:将关注人 和 粉丝 存在不同的集合中。redis为集合提供求交集、并集、差集等操作,可方便实现如共同关注、共同喜好等功能,对上面的所有集合操作,还可使用不同命令结果返回给客户端或者存集到一个新的集合中。

Sorted-set(有序的set集合):

  • 和set集合共同点:都不允许重复的成员出现在set当中
  • -和set集合的主要区别:

    • Sorted-Set 中的每一个成员都会有一个“分数”进行关联,而redis正是通过了这个分数来为集合中的成员进行从小到大的排序
    • 尽管 Sorted-Set中的成员必须是唯一的,但是分数是可以重复的,那么在 Sorted - Set中“添加、删除、更新”一个成员都是非常快速的操作。
  • 实践复杂度:由成员中的个数到对数。由于Sorted-Set集合中一个位置是有序的,因此访问集合“中部”的这些成员也是非常高效的。redis这一特征在其他很多数据库中都是很难实现的,也就是说在该“点”要想达到和redis一样的高效,在其他数据库中进行“建模”是非常困难的。

  • 添加:

        zadd : 返回添加的元素的个数  ,如果存在了再添加此元素,会执行“覆盖”。
    
image.png
  • 获得元素:

      zscore:获取某一元素
      zcard:获取具体成员数量
    
image.png
  • 删除元素:

      zrem :删除某一元素
    
image.png
  • 范围查询:

      zrange:withsscores 参数:表示将分数也显示出来
      zrevrange (更改排序方式):大 ->小
    
image.png
  • 排序:

      zremrangebyrank : 根据范围删除
      zremrangebyscore:根据分数范围删除元素
    
image.png
  • 扩展命令:

      zrangebyscore : 查找某一分数范围内的元素,withscores表示同时也显示分数。
      zincrby:设置指定成员增加多少分数
      zcount:获取分数在某个区间的个数
    
  • - 应用场景

    • 排行榜:以“登录次数”为权重,获取登录次数最多的用户将登录次数和用户统一存储在一个sorted set里

                     zadd login:login_times 5 1
                     zadd login:login_times 1 2
      
                     //当用户登录时,对该用户的登录次数自增1
                     ret = r.zincrby("login:login_times", 1, uid)
                     //那么如何获得登录次数最多的用户呢,逆序排列取得排名前N的用户
                     ret = r.zrevrange("login:login_times", 0, N-1)
      
    • 游戏排行榜:获取前100名高分用户,或者获取用户全球排名等

        // 将分数写入数据库中    
        ZADD leaderboard <score> <username>   
        // 实现分数从高到低排名,然后获取0-99,也就是100名游戏玩家         
        ZREVRANGE leaderboard 0 99  
        // 获取某用户的全球排名
        ZRANK leaderboard <username>  
      

Keys的通用操作

  • -命令:

    • 获得所有的keys:keys *

    • 以 ”my“ 开头的keys:keys my?

    • 删除某个指定的keys :del key1 key2

    • 判断某key是否存在:exists my1

    • 获取key : get my1

    • 重命名:rename my1 my2

    • 设置过期时间 : expire my2 1000 (秒)

    • 查看某key过期时间:ttl my1

    • 查看key类型: type my1


      image.png

redis特性

  • -多数据库:

    • 一个redis实例可以包含多个数据库,可以指定连接某个数据库

    • 一个redis实例最多可提供16个数据库,0-15 默认连接:0

    • 命令:切换“1”号数据库:select 1

        将1号数据库中的“myset”key移动到“0”数据库:
                                            move myset 0
      
image.png
  • -事物:

    • 事物中所有命令都将会被串行化顺序执行,在执行过程中,redis不会再对其他客户端提供任何服务,从而保证事物的“原子性”

      • - 命令:

        1. 开启事物:mutli,此后的命令都会被存放到一个队列当中,直到执行 exec,这些命令都会被原子化执行了
        2. 提交:exec,相当于关系型数据库中的commit
        3. discard:回滚,相当于关系型数据库中的roll-back
  • -注意:

    1. 如果在开启事物之前,如果客户端和服务端出现通讯故障导致服务器断开,那么执行的这些语句都将不会被服务器提交。
    2. 而如果网络中断是发生在exec(执行)之后的,那个这个十五中的所有命令都会被服务器提交。
  • 演示一:开启两个窗口


    image.png
  • 演示二:回滚


    image.png

redis持久化:

  • redis的高性能是由于所有的数据都存储在内存当中,要是保证在重启之后数据不丢失,就需要将数据从内存同步到硬盘上,这个过程就是redis的持久化操作。

  • 持久化方式:

      -- RDB方式
      -- AOF方式
    
  • - 持久化的使用方式:

    • RDB持久化:默认支持,无需配置

    指的是在指定的时间间隔内将内存中数据集快照写入到磁盘,即:指定多少s可将数据写入到磁盘一次。

    • AOF方式:以日志的形式记录服务器所处理的每一个操作。在redis服务器启动之初,他会读取该文件来重新去构建我们的数据库,从而来保证我们数据库中的数据是完整的。

    • 无持久化:通过配置来禁用redis服务器的持久化功能。这样我们将可以认为redis就是一个“缓存”的机制。

    • 同时使用RDB和AOF

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

推荐阅读更多精彩内容