Redis 的特性:

  • 更丰富的数据类型

  • 进程内与跨进程;单机与分布式

  • 功能丰富:持久化机制、过期策略

  • 支持多种编程语言

  • 高可用,集群

Redis 一共有几种数据类型?(注意是数据类型不是数据结构)

String、Hash、Set、List、Zset、Hyperloglog、Geo、Streams

Redis 基本数据类型

  • String 字符串 (可以用来存储字符串、整数、浮点数 )

    • 操作命令

      设置多个值(批量操作,原子性)

      mset qingshan 2673 jack 666
      

      设置值,如果 key 存在,则不成功

      setnx qingshan
      

      基于此可实现分布式锁。用 del key 释放锁。 但如果释放锁的操作失败了,导致其他节点永远获取不到锁,怎么办? 加过期时间。单独用 expire 加过期,也失败了,无法保证原子性,怎么办?多参数

      set key value [expiration EX seconds|PX milliseconds][NX|XX]
      

      使用参数的方式

      set lock1 1 EX 10 NX
      

      (整数)值递增

      incr qingshan
      incrby qingshan 100
      

      (整数)值递减

      decr qingshan
      decrby qingshan 100
      

      浮点数增量

      set f 2.6
      incrbyfloat f 7.3
      

      获取多个值

      mget qingshan jack
      

      获取值长度

      strlen qingshan
      

      字符串追加内容

      append qingshan good
      

      获取指定范围的字符

      getrange qingshan 0 8
      
    • 存储(实现)原理

      数据模型

      set hello word 为例,因为 Redis 是 KV 的数据库,它是通过 hashtable 实现的(我 们把这个叫做外层的哈希)。所以每个键值对都会有一个 dictEntry(源码位置:dict.h), 里面指向了 key 和 value 的指针。next 指向下一个 dictEntry

      typedef struct dictEntry {void *key; /* key 关键字定义 */union {void *val; uint64_t u64; /* value 定义 */int64_t s64; double d;} v;struct dictEntry *next; /* 指向下一个键值对节点 */
      } dictEntry;
      

      key 是字符串,但是 Redis 没有直接使用 C 的字符数组,而是存储在自定义的 SDS 中。 value 既不是直接作为字符串存储,也不是直接存储在 SDS 中,而是存储在 redisObject 中。实际上五种常用的数据类型的任何一种,都是通过 redisObject 来存储 的。

      redisObject

      redisObject 定义在 src/server.h 文件中

      typedef struct redisObject {unsigned type:4; /* 对象的类型,包括:OBJ_STRING、OBJ_LIST、OBJ_HASH、OBJ_SET、OBJ_ZSET */unsigned encoding:4; /* 具体的数据结构 */unsigned lru:LRU_BITS; /* 24 位,对象最后一次被命令程序访问的时间,与内存回收有关 */int refcount; /* 引用计数。当 refcount 为 0 的时候,表示该对象已经不被任何对象引用,则可以进行垃圾回收了*/void *ptr; /* 指向对象实际的数据结构 */
      } robj;
      
    • 应用场景

      • 缓存

        String 类型

        热点数据缓存(例如报表,明星出轨),对象缓存,全页缓存。 可以提升热点数据的访问速度。

      • 数据共享分布式

        String 类型,因为 Redis 是分布式的独立服务,可以在多个应用之间共享 ,

        例如:分布式 Session ,只需要引入spring-session-data-redis的依赖即可使用

        <dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId>
        </dependency>
        
      • 分布式锁

        String 类型 setnx 方法,只有不存在时才能添加成功,返回 true。

        http://redisdoc.com/string/set.html 建议用参数的形式

        SET key value [EX seconds] [PX milliseconds] [NX|XX]
        
        • EX seconds : 将键的过期时间设置为 seconds 秒。 执行 SET key value EX seconds 的效果等同于执行 SETEX key seconds value 。
        • PX milliseconds : 将键的过期时间设置为 milliseconds 毫秒。 执行 SET key value PX milliseconds 的效果等同于执行 PSETEX key milliseconds value 。
        • NX : 只在键不存在时, 才对键进行设置操作。 执行 SET key value NX 的效果等同于执行 SETNX key value 。
        • XX : 只在键已经存在时, 才对键进行设置操作。
        //基于Jedis实现分布式锁,使用带参数的那种
        public Boolean getLock(Object lockObject){jedisUtil = getJedisConnetion();//只用当设置成功后,才可以获取锁boolean flag = jedisUtil.setNX(lockObj, 1);if(flag){expire(locakObj,10);}return flag;
        }
        public void releaseLock(Object lockObject){del(lockObj);
        }
        
      • 全局 ID

        INT 类型,INCRBY,利用原子性

        incrby userid 1000
        
      • 计数器

        int 类型,INCR 方法

        incr onclick
        

        例如:文章的阅读量,微博点赞数,允许一定的延迟,先写入 Redis 再定时同步到 数据库。

      • 限流

        INT 类型,INCR 方法

        以访问者的 IP 和其他信息作为 key,访问一次增加一次计数,超过次数则返回 false。

      • 位统计

        String 类型的 BITCOUNT(1.6.6 的 bitmap 数据结构介绍)。 字符是以 8 位二进制存储的。

        set k1 a
        setbit k1 6 1
        setbit k1 7 0
        get k1
        

        a 对应的 ASCII 码是 97,转换为二进制数据是 01100001

        b 对应的 ASCII 码是 98,转换为二进制数据是 01100010

        因为 bit 非常节省空间(1 MB=8388608 bit)大约830万,可以用来做大数据量的统计。

        例如:在线用户统计,留存用户统计

        setbit onlineusers 0 1
        setbit onlineusers 1 1
        setbit onlineusers 2 0
        

        支持按位与、按位或等等操作。

        BITOP AND destkey key [key ...] ,对一个或多个 key 求逻辑并,并将结果保存到 destkey 。
        BITOP OR destkey key [key ...] ,对一个或多个 key 求逻辑或,并将结果保存到 destkey 。
        BITOP XOR destkey key [key ...] ,对一个或多个 key 求逻辑异或,并将结果保存到 destkey 。
        BITOP NOT destkey key ,对给定 key 求逻辑非,并将结果保存到 destkey 。
        

        计算出 7 天都在线的用户

        BITOP "AND" "7_days_both_online_users" "day_1_online_users" "day_2_online_users" ... "day_7_online_users"
        

        如果一个对象的 value 有多个值的时候,怎么存储? 例如用一个 key 存储一张表的数据。

        序列化?例如 JSON/Protobuf/XML,会增加序列化和反序列化的开销,并且不能 单独获取、修改一个值。

        可以通过 key 分层的方式来实现,例如:

        mset student:1:sno GP16666 student:1:sname 沐风 student:1:company 腾讯
        

        获取值的时候一次获取多个值:

        mget student:1:sno student:1:sname student:1:company
        

        缺点:key 太长,占用的空间太多。有没有更好的方式?

  • Hash 哈希(包含键值对的无序散列表。value 只能是字符串,不能嵌套其他类型 )

同样是存储字符串,Hash 与 String 的主要区别?

  1. 把所有相关的值聚集到一个 key 中,节省内存空间
  2. 只使用一个 key,减少 key 冲突
  3. 当需要批量获取值的时候,只需要使用一个命令,减少内存/IO/CPU 的消耗

Hash 不适合的场景:

  1. Field 不能单独设置过期时间
  2. 没有 bit 操作
  3. 需要考虑数据量分布的问题(value 值非常大的时候,无法分布到多个节点)
  • 操作命令

hset h1 f 6
hset h1 e 5
hmset h1 a 1 b 2 c 3 d 4
hget h1 a
hmget h1 a b c d
hkeys h1
hvals h1
hgetall h1

key 操作

hget exists h1
hdel h1
hlen h1
  • 存储(实现)原理

    Redis 的 Hash 本身也是一个 KV 的结构,类似于 Java 中的 HashMap。 外层的哈希(Redis KV 的实现)只用到了 hashtable。当存储 hash 数据类型时, 我们把它叫做内层的哈希。内层的哈希底层可以使用两种数据结构实现: ziplist:OBJ_ENCODING_ZIPLIST(压缩列表) hashtable:OBJ_ENCODING_HT(哈希表)

    ziplist 压缩列表

    ziplist 是一个经过特殊编码的双向链表,它不存储指向上一个链表节点和指向下一 个链表节点的指针,而是存储上一个节点长度和当前节点长度,通过牺牲部分读写性能, 来换取高效的内存空间利用率,是一种时间换空间的思想。只用在字段个数少,字段值 小的场景里面

    问题:什么时候使用 ziplist 存储?

    • 所有的键值对的健和值的字符串长度都小于等于 64byte(一个英文字母 一个字节);
    • 哈希对象保存的键值对数量小于 512 个。
  • 应用场景

    • String

      String 可以做的事情,Hash 都可以做。

    • 存储对象类型的数据

      比如对象或者一张表的数据,比 String 节省了更多 key 的空间,也更加便于集中管 理。

    • 购物车

      key:用户 id;field:商品 id;value:商品数量。

      hset userId:0001 shopId:99999 5
      
  • List 列表

    • 存储类型

      存储有序的字符串(从左到右),元素可以重复。可以充当队列和栈的角色。

    • 操作命令

      元素增减:

      lpush queue a  //从左开始添加元素
      lpush queue b c
      rpush queue d e  //从右边开始添加元素
      lpop queue  //从左边弹出元素
      rpop queue // 从右边弹出元素
      blpop queue //阻塞式左边的弹出元素  发布订阅模式 如果当前队列中没有了元素,就会阻塞
      brpop queue //阻塞式的右边弹出元素
      

      取值

      lindex queue 0
      lrange queue 0 -1
      

    • 存储(实现)原理

      在早期的版本中,数据量较小时用 ziplist 存储,达到临界值时转换为 linkedlist 进 行存储,分别对应 OBJ_ENCODING_ZIPLIST 和 OBJ_ENCODING_LINKEDLIST 。 3.2 版本之后,统一用 quicklist 来存储。quicklist 存储了一个双向链表,每个节点 都是一个 ziplist

      quicklist :

      quicklist(快速列表)是 ziplist 和 linkedlist 的结合体。

      quicklist中的head 和 tail 指向双向列表的表头和表尾

      typedef struct quicklist {quicklistNode *head; /* 指向双向列表的表头 */quicklistNode *tail; /* 指向双向列表的表尾 */unsigned long count; /* 所有的 ziplist 中一共存了多少个元素 */unsigned long len; /* 双向链表的长度,node 的数量 */int fill : 16; /* fill factor for individual nodes */unsigned int compress : 16; /* 压缩深度,0:不压缩; */
      } quicklist;
      
    • 应用场景

      • 用户消息时间线 timeline

        因为 List 是有序的,可以用来做用户时间线

      • 消息队列

        List 提供了两个阻塞的弹出操作:BLPOP/BRPOP,可以设置超时时间。

        BLPOP:BLPOP key1 timeout 移出并获取列表的第一个元素, 如果列表没有元素 会阻塞列表直到等待超时或发现可弹出元素为止。

        BRPOP:BRPOP key1 timeout 移出并获取列表的最后一个元素, 如果列表没有元 素会阻塞列表直到等待超时或发现可弹出元素为止。

        队列:先进先出:rpush blpop,左头右尾,右边进入队列,左边出队列。 右边进左边出

        栈:先进后出:rpush brpop 右边近右边出

        tip: 左边是链表的头部

  • Set集合

    • 存储类型

      String 类型的无序集合,最大存储数量 2^32-1(40 亿左右)。

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QzGFJauR-1603368961704)(https://i.loli.net/2020/05/25/dlP8pwyEbjseLfS.png)]

    • 操作命令

      添加一个或者多个元素

      sadd myset a b c d e f g
      

      获取所有元素

      smembers myset
      

      统计元素个数

      scard myset
      

      随机获取一个元素

      srandmember key
      

      随机弹出一个元素

      spop myset
      

      移除一个或者多个元素

      srem myset d e f
      

      查看元素是否存在

      sismember myset a
      
    • 存储(实现)原理

      Redis 用 intset 或 hashtable 存储 set。如果元素都是整数类型,就用 inset 存储如果不是整数类型,就用 hashtable(数组+链表的存来储结构)。 问题:KV 怎么存储 set 的元素?key 就是元素的值,value 为 null。 如果元素个数超过 512 个,也会用 hashtable 存储。

    • 应用场景

      • 抽奖

        随机获取元素

         spop myset
        
      • 点赞、签到、打卡

        这条微博的 ID 是 t1001,用户 ID 是 u3001。

        用 like:t1001 来维护 t1001 这条微博的所有点赞用户。

        点赞了这条微博:sadd like:t1001 u3001

        取消点赞:srem like:t1001 u3001

        是否点赞:sismember like:t1001 u3001

        点赞的所有用户:smembers like:t1001

        点赞数:scard like:t1001 比关系型数据库简单许多。

      • 商品标签

        用 tags:i5001 来维护商品所有的标签。

        sadd tags:i5001 画面清晰细腻

        sadd tags:i5001 真彩清晰显示屏

        sadd tags:i5001 流畅至极

      • 商品筛选

        获取差集

        sdiff set1 set2
        

        获取交集(intersection )

        sinter set1 set2
        

        获取并集

        sunion set1 set2
        

        iPhone11 上市了。

        sadd brand:apple iPhone11

        sadd brand:ios iPhone11

        sad screensize:6.0-6.24 iPhone11

        sad screentype:lcd iPhone11

        筛选商品,苹果的,iOS 的,屏幕在 6.0-6.24 之间的,屏幕材质是 LCD 屏幕

        sinter brand:apple brand:ios screensize:6.0-6.24 screentype:lcd
        
      • 用户关注、推荐模型

        并集:A中有B中也有,去除重复的,

        交集:A和B共同的部分才是交集

        全集U={1,2,3,4,5} A={1,3,5} B={1,2,5} 。那么因为A和B中都有1,5,所以交集A∩B={1,5} 。再来看看,他们两个中含有1,2,3,5这些个元素,不管多少,反正不是你有,就是我有。那么说并集A∪B={1,2,3,5}

        1. 相互关注? (取并集)

          sunion set1 set2
          
        2. 我(A)关注的人,他(B)也关注了?(取交集)

        sinter set1 set2
        
        1. 可能认识的人? (取差集 SET1中有的 而set2中没有的)

          sdiff set1 set2
          
        2. 共同关注/共同好友的人

          sinterstore set5 set1 set2127.0.0.1:6379> smembers set1  //我关注了one
          1) "two"
          2) "one"
          127.0.0.1:6379> smembers set2  //他也关注了one
          1) "ghy"
          2) "one"
          127.0.0.1:6379> sinterstore set5 set1 set2 //我们两共同的共同关注的人
          (integer) 1
          127.0.0.1:6379> smembers set5
          1) "one"  //one
          
      • Redis实现关注关系

        最近使用关系型数据库实现了用户之间的关注,于是思考换一种思路,使用Redis实现用户之间的关注关系。
        综合考虑了一下Redis的几种数据结构后,觉得可以用集合实现一下。

        假设“我”的ID是1,“别人”的ID是2。

        一、添加关注

        添加关注分为两步:1、将对方id添加到自己的关注列表中;2、将自己的id添加到对方的粉丝列表中:

        SADD 1:follow 2
        SADD 2:fans 1
        

        二、取消关注

        取消关注同样分为两步:1、将对方id从自己的关注列表中移除;2、将自己的id从对方的粉丝列表中移除:

        SREM 1:follow 2
        SREM 2:fans 1
        

        三、关注列表

        查看我的关注列表:

        SMEMBERS 1:follow
        

        查看别人的把id换掉就可以

        四、粉丝列表

        查看我的粉丝列表:

        SMEMBERS 2:fans
        

        查看别人的把id换掉就可以

        五、人物关系

        5.1 我单向关注他

        我单向关注他,要同时满足两个条件:1、我的关注列表中他(或他的粉丝列表中我);2、我的粉丝列表中没有他(或他的关注列表中没有我)。

        SISMEMBER 1:follow 2  #true
        SISMEMBER 1:fans 2    #false
        

        5.2 他单向关注我

        他单向关注我,要同时满足两个条件:1、我的关注列表中没有他(或他的粉丝列表中没有我);2、我的粉丝列表中他(或他的关注列表中我)。

        SISMEMBER 1:follow 2  #false
        SISMEMBER 1:fans 2    #true
        

        5.3 我和某人是否互粉

        我和某人是否互粉,要同时满足两个条件:1、我的关注列表中有他(或他的粉丝列表中有我);2、我的粉丝列表中有他(或他的关注列表中有我)。同时成立才为互粉。

        SISMEMBER 1:follow 2  #true
        SISMEMBER 1:fans 2    #true
        

        互粉的关系是互相的,也可以反过来查。

        六、我的互粉

        查询和我互粉的人,实际是对我的关注和我的粉丝求交集

        SINTER 1:follow 1:fans
        

        七、共同关注

        查询1和2的共同关注,实际是1的关注和2的关注求交集

        SINTER 1:follow 2:follow
        

        八、数量相关

        8.1 我的关注数

        SCARD 1:follow
        

        8.2 我的粉丝数

        SCARD 1:fans
        

        九、问题

        目前存在的问题是,我的关注列表 & 我的粉丝列表,无法做到按关注时间排序,终端下显示是结果按ID正序排列的。
        考虑的解决方案是添加关注时同时存一份有序集合,关注时的时间戳是score。

        ZADD 1:follow 1457871625 2
        ZADD 2:fans 1457871625 1
        

        那么我的关注列表是:

        ZREVRANGE 1:follow 0 -1
        

        同时,ZREVRANGE查询时的索引可以作为分页游标,基本解决目前的问题。

        粉丝列表同理。

  • ZSet有序集合

    • 存储类型

      sorted set,有序的 set,每个元素有个 score。

      score 相同时,按照 key 的 ASCII 码排序。

      数据结构对比:

      数据结构 是否允许重复元素 是否有序 有序实现方式
      列表list 索引下标
      集合set
      有序集合zset 分值score
    • 操作命令

      添加元素

      zadd myzset 10 java 20 php 30 ruby 40 cpp 50 python
      

      获取全部元素

      zrange myzset 0 -1 withscores
      zrevrange myzset 0 -1 withscores
      

      根据分值区间获取元素

      zrangebyscore myzset 20 30
      

      移除元素 也可以根据 score rank 删除

      zrem myzset php cpp
      

      统计元素个数

      zcard myzset
      

      分值递增

      zincrby myzset 5 python
      

      根据分值统计个数

      zcount myzset 20 60
      

      获取元素 rank

      zrank myzset java
      

      获取元素 score

      zsocre myzset java
      
    • 存储(实现)原理

      同时满足以下条件时使用 ziplist 编码:

      1. 元素数量小于 128 个

      2. 所有 member 的长度都小于 64 字节

      在 ziplist 的内部,按照 score 排序递增来存储。插入的时候要移动之后的数据。

      超过阈值之后,使用 skiplist+dict 存储。

      什么是 skiplist?

      我们先来看一下有序链表: 在这样一个链表中,如果我们要查找某个数据,那么需要从头开始逐个进行比较, 直到找到包含数据的那个节点,或者找到第一个比给定数据大的节点为止(没找到)。 也就是说,时间复杂度为 O(n)。同样,当我们要插入新数据的时候,也要经历同样的查 找过程,从而确定插入位置。

      而二分查找法只适用于有序数组,不适用于链表。

      假如我们每相邻两个节点增加一个指针(或者理解为有三个元素进入了第二层), 让指针指向下下个节点。

      这样所有新增加的指针连成了一个新的链表,但它包含的节点个数只有原来的一半 (上图中是 7, 19, 26)。在插入一个数据的时候,决定要放到那一层,取决于一个算法 (在 redis 中 t_zset.c 有一个 zslRandomLevel 这个方法)。

      现在当我们想查找数据的时候,可以先沿着这个新链表进行查找。当碰到比待查数 据大的节点时,再回到原来的链表中的下一层进行查找

      在这个查找过程中,由于新增加的指针,我们不再需要与链表中每个节点逐个进行 比较了。需要比较的节点数大概只有原来的一半。这就是跳跃表。

      为什么不用 AVL 树或者红黑树?因为 skiplist 更加简洁

    • 应用场景

      • 排行榜

        id 为 6001 的新闻点击数加 1:zincrby hotNews:20190926 1 n6001

        获取今天点击最多的 15 条:zrevrange hotNews:20190926 0 15 withscores

  • BitMaps

    Bitmaps 是在字符串类型上面定义的位操作。一个字节由 8 个二进制位组成。

    应用场景: 用户访问统计 在线用户统计

  • Hyperloglogs

    Hyperloglogs:提供了一种不太准确的基数统计方法,比如统计网站的 UV,存在 一定的误差。

  • Streams

    支持多播1->N的可持久化的消息队列,用于实现发布订阅功能,借 鉴了 kafka 的设计。

 **这样所有新增加的指针连成了一个新的链表**,但它包含的节点个数只有原来的一半 (上图中是 7, 19, 26)。在插入一个数据的时候,决定要放到那一层,取决于一个算法 (在 redis 中 t_zset.c 有一个 zslRandomLevel 这个方法)。 现在当我们想查找数据的时候,可以先沿着这个新链表进行查找。当碰到比待查数 据大的节点时,再回到原来的链表中的下一层进行查找 在这个查找过程中,由于新增加的指针,我们不再需要与链表中每个节点逐个进行 比较了。需要比较的节点数大概只有原来的一半。这就是跳跃表。 为什么不用 AVL 树或者红黑树?因为 skiplist 更加简洁
  • 应用场景

    • 排行榜

      id 为 6001 的新闻点击数加 1:zincrby hotNews:20190926 1 n6001

      获取今天点击最多的 15 条:zrevrange hotNews:20190926 0 15 withscores

1.redis常用的数据类型及应用相关推荐

  1. 一文带你详解Redis常用的数据类型以及面试常碰到的数据持久化机制原理

    前言 关于Redis的知识点总结了一个思维导图分享给大家: 简介 Redis是一种面向"key-value"类型数据的分布式NoSQL数据库系统,支持五种数据类型格式:** Str ...

  2. Redis常用五大数据类型

    1.String(字符串) string类型是二进制安全的.意思是redis的string可以包含任何数据.比如jpg图片或者序列化的对象 . string类型是Redis最基本的数据类型,一个red ...

  3. Redis 学习笔记-NoSQL数据库 常用五大数据类型 Redis配置文件介绍 Redis的发布和订阅 Redis_事务_锁机制_秒杀 Redis应用问题解决 分布式锁

    1.NoSQL数据库 1.1 NoSQL数据库概述 NoSQL(NosQL = Not Only sQL ),意即"不仅仅是sQL",泛指非关系型的数据库.NoSQL不依赖业务逻辑 ...

  4. redis常用数据类型的场景,你真的用对了么?

    关注微信公众号"虾米聊吧",每天更新一篇技术文章,文章内容涵盖架构师成长必经之路应掌握的技术,一起学习,一起交流. redis常用数据类型的场景,你真的用对了么? redis常用数 ...

  5. Redis面试常问-- Redis常用数据类型

    Redis常用数据类型 http://www.redis.cn/

  6. 解析Redis操作五大数据类型常用命令

    摘要:分享经常用到一些命令和使用场景总结,以及对Redis中五大数据类型如何使用cmd命令行的形式进行操作的方法. 本文分享自华为云社区<Redis操作五大数据类型常用命令解析>,作者:灰 ...

  7. Redis常用数据类型和事物以及并发

    Redis数据类型 基本类型(String int): 如 set key value .get key 等 所有命令都是按照 key value keys * 可以将全部数据列出,其中后面的 &qu ...

  8. 【用户画像】Redis的常用五大数据类型和配置文件介绍

    文章目录 一 常用五大数据类型简介 1 Redis键(key) 2 Redis字符串(String) 3 Redis列表(List) 4 Redis集合(Set) 5 Redis哈希(Hash) 6 ...

  9. Redis常用数据类型及使用场景

    String(字符串) 常用命令 SET key value GET key GETRANGE key start end #返回[start, end]区间的字符串,key不存在时返回空字符串 MG ...

最新文章

  1. python进度条 pyqt_Python高级进阶#015 pyqt5进度条QProgressBar结合使用qbasictimer
  2. 瞄准千亿个护市场,纸业龙头们下半场战役已经打响
  3. 阿里云安全组——添加安全组规则(开放端口)
  4. 如何在Firefox 3中重新启用about:config警告消息
  5. 广度优先遍历_LeetCode | 广度优先遍历
  6. 动态规划经典题目_动态规划经典题目:鸡蛋掉落(附视频讲解)
  7. 小牛电动京东众筹活动中的违约行为记录
  8. Ubuntu下pycharm无法输入中文
  9. mysql省市区递归查询_mysql 递归查询
  10. Vue实现仿豆瓣电影
  11. qq for android 4.6能视频吗,安卓qq4.6使用评测
  12. Docker部署rabbitmq遇到的两个问题
  13. Unity Text字体花屏
  14. Facebook成为美国四大电视台争夺观众阵地
  15. 根椐图片,请猜一四字成语!有一点难度喔:)
  16. 六面蚂蚁金服,唬住了面试官要了 30K;其实 Java 面试也没那么难
  17. 从零开始之驱动发开、linux驱动(二十九、mmap原理)
  18. SQLite 使用问题记录(一)
  19. python爬取智联招聘_【原创源码】python 爬取智联招聘
  20. 美妆界现在是“李佳琦们”的内容营销时代

热门文章

  1. Zabbix4.0安装文档
  2. 性能工具gperftools使用说明
  3. 从防御者视角来看APT攻击
  4. 【宫水三叶的刷题日记】961. 在长度 2N 的数组中找出重复 N 次的元素
  5. tigase服务器推送消息,tigase,消息中心,概要设计(25页)-原创力文档
  6. h5调用本地摄像头和麦克风一
  7. 地表最强系列之Sqoop安装以及使用
  8. android图片资源加密解密,Android下资源图片的加密和解密
  9. libsodium linux,Linux安装libsodium失败解决办法~
  10. 如何在CentOS 6.7上配置和安装ZeroMQ(libsodium)?