Redis的学习笔记–第一章

前言

最近闲来无事,入手了一本钱文品老师的《Redis深度历险-核心原理与应用实践》一书,于是便偶尔翻几页学习一下Redis,毕竟用了好几年了,但是一些底层的核心内容一直没有系统的了解过,借此机会也让自己对Redis有个更深得了解吧。现在把第一张的内容进行总结并且记录一下,自己也在下面使用笔记本记录了一些要点,但是笔记本总是放着放着不知道拿哪里去了,搞了在不同的笔记本上东记一些西记一些,这里写个学习笔记,算是归纳整理吧,放在网上,也能跟朋友们交流下。

1、Redis的基础结构:

Redis常用的数据结构分为:
  • string(字符串)
  • list(列表)
  • hash(字典)
  • set(集合)
  • zset(有序集合)
  • Redis特殊的数据结构:
  • HyperLogLog
  • BitMap(位图)
  • 布隆过滤器

  • 1、string的相关知识:

    1.1、string的基本概念及实现

    Redis的字符串时动态字符串,是可以修改的,Redis每次申请字符串空间的时候,是采用预分配冗余空间的方式进行分配的。
    其内部字符串分配的空间内存,一定是高于储存的字符串的。如果说字符串小于1M那么每次申请到的内存是储存内存的一倍,
    如果字符串大于1M时,那么每次申请都是以1M 进行扩容的。注意:字符串的最大空间(字符串的长度)是512M。
    而字符串的底部实现则是以位图实现的,字符串是由多个字符组成的,而一个字符则是由八个位(bit)组成的,
    所以一串字符串则是由好多个8位数组组成

    1.2、string的相关命令

    string相当于键值对,支持简单的增删改查。命令一般有:

    单个操作:

    • set key

    • get key

    批量操作:

  • mset key value key value key value
  • mget key key key key


  • > set test 牛牛
    OK
    > get test
    "牛牛"
    > mset test0 牛牛 test1 壮壮 test2 瞳瞳
    OK
    > mget test test0 test1 test2
    1) "牛牛"
    2) "牛牛"
    3) "壮壮"
    4) "瞳瞳"
    > mget test0 test1 test2
    1) "牛牛"
    2) "壮壮"
    3) "瞳瞳"
    
    

    设置过期时间:

  • expire key time
  • setex key time value

  • > expire test 1
    (integer) 1
    > get test
    (nil)
    > get test1
    "壮壮"
    > expire test1 1
    (integer) 1
    > get test1
    (nil)
    
    

    不存在就添加,但是存在就不改变(返回0/1来区分是否添加成功)

  • setnx key value

  • > setnx test2 111
    (integer) 0
    > setnx test3 111
    (integer) 1
    > get test2
    "瞳瞳"
    > get test4
    (nil)
    

    2、List(列表)的相关知识

    Redis的列表相当于java中的LinkedList
    (链表还是双向链表 //TODO:根据之前的Demo写一篇链表的博客—20220300),
    这意味着Redis中List的插入和删除操作是非常快的,
    其时间复杂度位O(1),但是索引的速度确实很慢,时间负责都为O(n)。
    Redis的列表有多种用途,
    当他从右边进并从左边出的时候,可以看做是队列。
    然当他左边进左边出(或者右进右出)的时候可以就可以看成是栈,
    而list也可以当作延时队列进行来使用。在一侧添加消息,并在另一侧对消息进行轮询弹出进行处理。

    2.1、list的相关命令

    推进和弹出

  • rpush key values
  • rpop key
  • lpush key values
  • lpop key
  • 
    > rpush listtest C#
    (integer) 1
    > rpush listtest java
    (integer) 2
    > rpush listtest php
    (integer) 3
    > rpush listtest js
    (integer) 4
    > rpop listtest
    "js"
    > lpop listtest
    "C#"
    
    > rpush tt C# java php
    (integer) 3
    > rpush tt android node go python
    (integer) 7
    
    //push 可添加多个元素
    
    

    遍历定位

  • lindex key index
  • lindex用于对列表进行遍历定位,性能消耗随着index的数值增大而增加。
    lindex listtest 0
    "java"
    > lindex listtest 5
    (nil)
    > lindex listtest -1
    "php"
    > lindex listtest 1
    "php"
    
    //之前的命令已将 C# 和js 弹出,所以此时列表里只存在两个元素,
    在坐标中,-1代表着最后一个元素。也就是最右边的元素(列表是从左到右排列)
    
    

    截取保留(修剪):该命令会保留区间内的所有元素,并且删除区间外的所有元素

    返回列表元素:返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素 如果start是0 而end是-1 则返回正向所有元素

    //返回列表元素

  • lrange key start_index end_index
  • //截取保留

  • ltrim   key   start_index ;  end_index
  • > lrange tt 0 -1
    1) "C#"
    2) "java"
    3) "php"
    4) "android"
    5) "node"
    6) "go"
    7) "python"
    
    > ltrim tt 2 5
    OK
    
    > lrange tt 0 -1
    1) "php"
    2) "android"
    3) "node"
    4) "go"
    
    //可以发现从第三个元素到第六个元素还存在于列表中,其他的已经被裁剪掉了
    
    
    2.2、注意:

    Redis的列表并不是普通的链表,而是快速链表(quicklist),首先在元素较少的情况下,列表是使用一块连续的内存进行储存的,这个结构是ziplist(压缩列表)。它将所有的元素都彼此紧挨着一起储存。当数据量比较多的时候,则会改成quicklist进行储存,因为普通的链表需要的附加指针空间太大,会浪费时间,还会加重内存的碎片化,。所以Redis将链表和ziplist结合组成了quicklist,就是将多个ziplist使用双向指针进行串联,既能满足快速的插入删除,又不会出现太大的冗余。

    3、hash(哈希表–字典)的相关知识

    Redis的hash和C#的Dictionary<,>的结构是一毛一样的。
    
    3.1、hash的命令:

    设置和获取

  • hset key hkey value
  • hget key heky

  • 获取key下的全部数据

  • hgetall key

  • 获取key下的二级键值对数量

  • hlen

  • 设置二级键值对数值计数

  • hincrby
  • 4、set(集合)的相关知识

    Redis的集合其实就是相当于C#中的List<T>具体泛型是什么类型的,需要看具体插入的值(这里泛型仅作比如,具体的类型没啥用)。当集合的最后一个元素被移除后,结构就会被自动删除。内存则会被回收,该结构具有去重的功能,所以一边可用于储存中奖结果名单之类的作用,可以确保用户不会被抽中两次。
    
    4.1、set(集合)的命令
    添加和获取元素
    <li>sadd key values </li>
    <li>smembers key</li>
    <br>
    
    判断一个元素是否存在
    <li>sismember key value</li>
    <br>
    
    查询集合中的元素数量
    <li>scard key</li>
    <br>
    
    随机弹出一个值
    <li>spop key</li>
    

    5、zset(有序集合)的相关知识

    Redis的有序集合其实和集合的区别就是它比集合多了个score(权重概念),而集合中的元素,可以根据score的变化,进行排序,
    其内部实现用的是一种叫做“跳跃列表”的数据结构。同样的有序集合中最后一个元素被移除的时候数据结构就会被删除,内存就会被回收,有序集合通常用于储存 粉丝列表,用value来保存用户Id,用score来记录关注时间(时间戳),也可储存学生的成绩,value储存学生的id,score储存成绩,个人猜测:微信的步数列表、附近的人,应该是用这个进行储存的。
    
    5.1、zset(有序集合)的命令
    添加和获取元素
    <li>zadd key score values </li>
    
    按照权重正向排出区间内的元素
    <li>zrange key start_index end_index</li>
    <br>
    
    按照权重逆向排出区间内的元素
    <li>zrevrange key start_index end_index</li>
    <br>
    
    查询集合中的元素数量
    <li>zcard key</li>
    <br>
    
    获取指定value的权重
    <li>zscore key value</li>
    <br>
    
    获取指定value的排名
    <li>zrank key value</li>
    <br>
    
    获取权重区间内的元素
    <li>zrangebyscore key start_score end_score</li>
    <br>
    
    删除一个值
    <li>zrem key</li>
    

    Redis的数据结构类型及其通用规则

    1、容器类型数据结构

    在Redis中 list、set、hash、zset 这四种数据结构属于容器行数据结构,他们均有一下两条通用规则<br>
    <li>一、如果容器不存在就创建一个,再进行操作。</li>
    <li>二、如果最后一个元素被取出或者删除了,那么容器就会消失,内存回收释放。
    

    Redis的过期时间

     Redis的所有数据结构都可以设置过期时间,时间到了,Redis会自动删除相应的对象,但是过期时间是以对象为单位的,所以hash并不能对某个二级key设置过期时间,还有就是如果一个字符串设置了过期时间,那么如果再次调用set命令的话过期时间会消失。
    
    

    位图的应用场景及使用方式

    刚听说位图的时候,觉得这是一块很难懂的玩意,又是bit又是字符串的,但是当潜下心来了解的时候发现其实一点都不难,Redids的字符串,每个英文字母是一个字节,而一个字节是八个bit,而一个字符串就是一堆以八个bit为一组的数组,每个bit不是1就是0,也可以看作非真即假,这个时候,我们可以把这个玩意儿用于储存比如内日签到记录,或者每日登记之类的场景,因为是否签到,就是非真即假,签到了我们就存个1,没签到我们就存个0。这样一年的签到记录也就是个45个字的字符串。。。。
    位图的命令也很简单

    • setbit key offset value
    • getbit key offset
    > set h h
    OK
    > getbit h 0
    0
    > getbit h 1
    1
    > getbit h 2
    1
    > getbit h 3
    0
    > getbit h 4
    1
    > getbit h 5
    0
    > getbit h 6
    0
    > getbit h 7
    0
    
    // 01101000
    
    /*
    使用py解析下h的二进制编码
    >>> bin(ord('h'))
    '01101000'
    >>>
    */
    
    可以发现一毛一样,不过!!
    正常的二进制是从高位到地位的, 也就是说py解析出来的八个数字。其实是
    76543210以这样排列,但是Redis中位图则是从低到高进行排列的。
    所以跟正常的二进制刚好是相反的01234567
    接下来我们可以通过位图添加出一个字符
    
    setbit t 0 0
    0
    > setbit t 1 1
    0
    > setbit t 2 1
    0
    > setbit t 3 0
    0
    > setbit t 4 1
    0
    > setbit t 5 0
    0
    > setbit t 6 0
    0
    > setbit t 7 0
    0
    > get t
    "h"
    
    > bitcount h
    3
    //上面这个命令则是统计这个Key的位图里有几个1,意味着位图如果使用到签到场景的话,可以统计整个记录里面签到多少次。如果指定了参数范围,则可以查看这个范围内的签到次数,但是注意,指定的范围,只能是8的倍数,而不能任意指定。
    
    

    思考:

    常用的数据存储中,我们针对一个完整的结构,是直接存储json还是分开存储属性?比如用户信息。我们是把整个用户信息进行存储还是以用户id为命名空间,下面存储各个信息的单独属性。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值