zoukankan      html  css  js  c++  java
  • 从今天开始看《Redis深度历险》--基础

    emmm,注册博客之后基本就查资料的时候看看,之前开始写了两天就放弃了,太难了,得养成个好习惯,改变一下做思维导图和记笔记习惯,尝试一下写博客。

    书中的部分内容采用的是Java的方式来解释的,如果我可以的话,我可能会尝试使用python来解释一下,妈耶,看到后面才发现代码还有python的版本

    命令部分推荐大家看这个文档

    前言

      前面的部分算是前言吧,简单的介绍一下redis,顺带发出会心一击:

      redis能做什么?

      可能在之前我也只能说上一句“做数据库应该做的事”,作者在前言里也只介绍了一下对redis的基础运用(缓存和分布式锁),没错,就是那些数据库应该做的事!对各类的信息进行分类的保存,相对于其他数据库来说优点可能就是设计上带来的优势,足够快,别的,作者也暂时并没有多说。简单举了一些例子,各种数据类型会被用来做什么工作,采用一个合适的结构来做合适的事对任何数据库来说都是非常重要的。作者在书中还附加了几个链接,其中比较有价值的一个是作者自己写的redis面试刁难大全,还有几个是关于redis开发者的花边新闻。。和几个看起来就不是很重要的链接。

    关于redis的安装部分,我使用的是redis的web版和WSL中安装的用于正式项目中用于测试的部分,学习的时候web版足够使用了,但是web版的响应速度有时候。。。

    基础

      redis的数据结构都是以唯一的key字符串作为名称,然后通过这个唯一的key来查询相应的value的值。不同数据结构的差异就在于这个value的结构不一样。

      基础内容关于redis的数据结构:

    string

      string结构可能是使用的最广泛的数据结构了,毕竟简单明了。。。书中举例是将用户信息进行json序列化之后存储,取值时进行一次反序列化。

      string的value是可以修改的,内部实现结构类似Java的arrylist,采用预分配空间的方式来防止内存的频繁修改(关于这点,在python中我只能联想到关于大整数对象池和小整数对象池和intern机制),在实际分配给string的空间是大于它字符串长度的。具体机制为,当字符串长度小于1M的时候,扩容是加倍现有的空间,而在大于1M的时候,每次扩容都只会扩容1M。

      string的最大字符串长度是512M(难以想象这么长的字符串是干嘛的)。

      常用操作

      set key value 这种简单的命令我就不多做解释了

      get key 不存在将会返回 nil

      exists key 存在将会返回(integer)1

      del key 成功将会返回(integer)1

        mset key1 value1 key2 value2... 一次性给多个键设置多个值(我猜m是map?)

        mget key1 key2... 一次性获取多个值,返回的是一个列表

        expire key timeout 设置过期时间为timeout

        setex key value timeout 相当于set+expire

        setnx key value 如果key不存在就创建,如果存在将会返回(integer)0(我猜setnx=set+not exist)

      如果value是一个整数,那么则可以对value进行自增或自减操作(书中没有提到自减,其实是有自减的),其自增或自减的值不能超过signed long的最大值((-2^63)~(2^63-1))

        incr key 将键值自增1

        incrby key increment 将键值自增increment,可以为负数(可能这就是作者不介绍自减的原因?)

      另外还有一些作者没介绍的函数,我觉得可能会用到的,另外注明

        strlen key

        getrange key start end

        append key value 在key原本的value后面添加value,如果key不存在将会创建key将值赋给key,无论存在与否都返回新字符串的长度

    list

      相当于Java里的LinkedList,即链表,插入和删除时间复杂度是O(1),查找则是O(n)。

      当列表弹出最后一个元素之后,那么列表将会被回收!

      常用作异步队列。

      常用操作

        lpush value1 value 2...

        rpush value1 value2...

        lpop

        rpop

        作者还演示了一下用以上几个操作实现FIFO和FILO队列。。

        llen

        lrange listname start end 获取start和end之间的值,end可以为负值,比如-1就是最后一个元素

        lindex listname index 获取index位置的值,因为时间复杂度是O(n),建议慎用

        ltrim listname start end 对列表进行修剪,只保留start和end中间的部分,举了个例子,ltrim listname 1 0 相当于清空列表。可以使用ltrim来实现一个定长的链表。

        还有几个我觉得可以加入进来的操作

        blpop、brpop listname1 [listname2...] timeout 以阻塞的方式来获取listname中的值,直到超时,查找的顺序是1->2...(b指block)

        同样的,上述命令还有rpop的版本

        rpoplspush source destination 将source中的元素rpop再lpush到destination中,这个命令也有block版本

    还有比较重要的一点是,list的内部实现不是简单的链表结构,而是一种被称作quicklist的结构,即在列表元素较少的时候采用连续的内存空间来进行存储(ziplist),而在数据量较大的时候就会采用链表的结构,避免了在较少数据量的情况下将内存空间碎片化的状况,以及需要大量的额外存储空间来存储next和prev的情况。因此,这种就是将多个ziplist链接起来做出存储结构。

    hash

    hash的结构类似于Java中的HashMap(python的中dict,不过dict的底层结构是哈希表),无序字典。内部实现结构和Java的HashMap是一致的,都是数组+链表的二维结构,但是hash的值只能存储字符串。不过二者解决rehash问题时的方式不一样,Java的字典在HashMap很大的时候,rehash是非常耗时的,因为要一次性完成全部的rehash操作。而redis的rehash为了设计之初的目标即高性能,不能采用这种方式,因此采取了渐进式rehash的方式,渐进式rehash在rehash的过程中会同时保留新旧两个hash结构,在查询的时候会同时查询两个hash结构,并在后续的定时任务和对hash的访问指令中,逐步的将旧hash的内容迁移到新hash中。

    当hash移除了最后一个元素,那么它将会被回收。

    hash也能够用来存储用户的信息,优点在于不需要将全部信息序列化,结构会变得很清晰,但是缺点在于消耗的内存空间会大于string,因此,选择使用哪一个的时候需要慎重。

    常用操作

      hset hashname key value 如果key或者value中包含空格,要用引号括起来。如果是赋值操作,返回值是1,如果是更新操作,返回值是0

      hgetall hashname 返回值是以key和value间隔出现的形式返回的

      hlen hashname 返回该hash中的元素个数

      hmset hashname key1 value1 key2 value2... 一次性赋值多个

      hmget hashname key1 key2...

    其他我觉得会用上的操作

      hexists hashname key 判断hash中是否存在key

      hsetnx hashname key value

      hkeys hashname 获取所有key

      hvals hashname 获取所有的value

      hincrby hashname key increment 还有递减版本,格式同上

    set

      redis中的set相当于Java中的HashSet(python中的set),其内部的键值对是无序的、唯一的。相当于一个value都为NULL的字典

    set的应用场景就是那些集合才能做的事,比如保证一个用户只会中奖一次(什么鬼例子,还能有这种欧皇?!),比如共同好友,简而言之就是适用于那些需要求交集并集差集的场景下,或者是需要保证唯一性的场景。

    常用操作

      sadd setname value

      smembers setname 获取集合中的元素,顺序是随机的

      sismember setname key 查询key是不是该集合中的元素

      scard setname 获取集合中元素的数量

      spop setname 弹出一个元素

    其他操作

      sidff/sinter/sunion setname1 setname2 返回差集/交集/并集

      srandmember setname count 返回count个元素

    集合中的概念还有个让我比较迷糊的叫做 游标 ,搜了一下也没太看懂,特别注明一下

    zset

      zset类似于Java中的SortedSet和HashMap的结合体(python中比较特色的集合是frozenset),相当于一个value为score的字典。其内部实现是跳跃表(非常强大的数据结构,实现简单,高效)

      书中特别强调了,这个是面试的重点!

      注意,zset中score是可以重复的

      常用操作

      zadd zsetname score1 value1 ...  注意,redis2.4之前,zadd每次只能添加一个

      zrange zsetname start end 获取指定分数区间内的值

      zrevrange zsetname start end 上一条操作的逆序版本

      zcard zsetname 获取元素数量

      zscore zsetname key 获取指定key的score

      zrank zsetname key 获取zset中key的分数排名(升序),返回值是其排名(从0开始)

      zrange zsetname start end [withscores] 返回指定score区间的元素,可选参数表示以score排序之后返回

    ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] 这个解释很长,建议去文档瞅一眼,大概意思就是返回指定score区间内的元素,withscores表示返回时有序部分按score升序排列,limit则是限制返回值的范围和数量,在zset很大的时候,这个是必须的。

    zrem zsetname key 删除指定key

    zset的指令非常多,建议去文档看一遍有个印象,真的是很多。。。

    高级的数据结构如HyperLogLog、Geo、Pub/Sub(我之前只知道第一个!)暂时还未提到

    容器数据类型的通用规则

    list/set/hash/zset是容器数据类型,他们共享以下两条规则:

      1.create if not exists 这个从命令中应该已经很明显的可以看出来了,并没有专门用来定义一个新容器的命令

      2.drop if no elements 如果没有元素了,那么将删除该容器,释放内存

    redis所有数据类型都能够设置过期时间

      通用的指令如ttl、expire系列的

    如果其中有什么错误,请在评论区回复我,我会及时修改
  • 相关阅读:
    Linux下find命令详解
    shell if语句
    目标文件系统映像制作工具mkyaffs2image
    编译内核
    FPS含义
    linux下echo命令详解
    Mssql数据库语句综合
    string 字符串操作
    Lession 15 Good news
    Mysql使作心得(备份,还原,乱码处理)
  • 原文地址:https://www.cnblogs.com/slientbrain/p/12944531.html
Copyright © 2011-2022 走看看