Redis 笔记系列(五)——redis五大数据类型概述

 

Redis  数据类型:

Redis的数据类型,其实最好的介绍文档是redis的官方文档:http://redis.io/topics/data-types-introhtml

数据类型有不少种,最经常使用的为如下5个:java

字符串String、列表List、集合Set、散列表Hash、有序集合ZSet(Sorted set)python

其余还有:golang

  • Bit arrays (or simply bitmaps): it is possible, using special commands, to handle String values like an array of bits: you can set and clear individual bits, count all the bits set to 1, find the first set or unset bit, and so forth.
  • HyperLogLogs: this is a probabilistic data structure which is used in order to estimate the cardinality of a set. Don't be scared, it is simpler than it seems... See later in the HyperLogLog section of this tutorial.

这里就不作介绍了。redis

 

 

String字符串类型

string类型是redis最基本的类型,内衣裂解成与Memcahed同样的类型,一个key对应一个value。数组

string类型是二进制安全的,意思是redis的string能够包含任何数据,好比jpg图片或者序列化对象。安全

string类型是Redis最基本的数据类型,一个redis中字符串value最多能够是512M。(这是个上限,但别犯2,真去存个value是512M的value。好吧,打个比方,格力空调说他们每晚只用一度电,秒懂?)bash

Redis之因此可以干掉mencached,一个最主要的缘由就是redis除了字符串类型,还支持其余多种数据类型。服务器

 

Redis字符串(String)
    单值单value
         set/get/del/append/strlen
        Incr/decr/incrby/decrby,必定要是数字才能进行加减
         getrange/setrange
         setex(set with expire)键秒值/setnx(set if not exist)
         mset/mget/msetnx
         getset(先get再set)网络

127.0.0.1:6379> get k1
"100"
127.0.0.1:6379> type k1
string
127.0.0.1:6379> INCR k1
(integer) 101
127.0.0.1:6379> get k1
"101"
127.0.0.1:6379> type k1
string
127.0.0.1:6379>

127.0.0.1:6379>
127.0.0.1:6379> INCR k1 2
(error) ERR wrong number of arguments for 'incr' command
127.0.0.1:6379> INCRBY k1 2
(integer) 103
127.0.0.1:6379> DECR k1
(integer) 102
127.0.0.1:6379> DECRBY k1 3
(integer) 99
127.0.0.1:6379> get k1
"99"
127.0.0.1:6379>

 

127.0.0.1:6379> set k2 'i love you'
OK
127.0.0.1:6379> get k2
"i love you"
127.0.0.1:6379> append k2 ', but have to leave'
(integer) 29
127.0.0.1:6379> get k2
"i love you, but have to leave"
127.0.0.1:6379> strlen k2
(integer) 29
127.0.0.1:6379>

 

SETRANGE key offset value

用 value 参数覆写(overwrite)给定 key 所储存的字符串值,从偏移量 offset 开始。

不存在的 key 看成空白字符串处理。

SETRANGE 命令会确保字符串足够长以便将 value 设置在指定的偏移量上,若是给定 key 原来储存的字符串长度比偏移量小(好比字符串只有 5 个字符长,但你设置的 offset 是 10 ),那么原字符和偏移量之间的空白将用零字节(zerobytes, "\x00" )来填充。

注意你能使用的最大偏移量是 2^29-1(536870911) ,由于 Redis 字符串的大小被限制在 512 兆(megabytes)之内。若是你须要使用比这更大的空间,你可使用多个 key 。

当生成一个很长的字符串时,Redis 须要分配内存空间,该操做有时候可能会形成服务器阻塞(block)。在2010年的Macbook Pro上,设置偏移量为 536870911(512MB 内存分配),耗费约 300 毫秒, 设置偏移量为 134217728(128MB 内存分配),耗费约 80 毫秒,设置偏移量 33554432(32MB 内存分配),耗费约 30 毫秒,设置偏移量为 8388608(8MB 内存分配),耗费约 8 毫秒。 注意若首次内存分配成功以后,再对同一个 key 调用 SETRANGE 操做,无须再从新内存。

127.0.0.1:6379> SETRANGE k2 7 'anyone but y'
(integer) 29
127.0.0.1:6379> get k2
"i love anyone but ye to leave"

是覆盖不是插入哦。

 

List列表

回想一下Java中的List包含了两个经常使用的List:

一个是ArrayList,实际上是一个Object数组。

一个是LinkedList,是一个双向链表。在jdk1.6中,节点是一个Entry;在jdk1.7中节点是一个Node对象。

在Redis里的List是一个ArrayList呢?仍是LinkedList呢?

Redis列表是简单的字符串列表,按照插入顺序排序。你能够添加一个元素到列表的头部(左边)或者尾部(右边)。

它的底层实际是个链表。

Redis列表(List)

    单值多value
         lpush/rpush/lrange
         lpop/rpop
         lindex,按照索引下标得到元素(从上到下)
         llen
         lrem key 删N个value
         ltrim key 开始index 结束index,截取指定范围的值后再赋值给key
         rpoplpush 源列表 目的列表
         lset key index value
         linsert key  before/after 值1 值2
        性能总结

127.0.0.1:6379> lpush list1 1 2 3 4 5
(integer) 5
127.0.0.1:6379> get list1
(error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379>
127.0.0.1:6379> lrange list1 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379>
127.0.0.1:6379> rpush list2 5 4 3 2 1
(integer) 5
127.0.0.1:6379> lrange list2 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379>
127.0.0.1:6379> lpop list1
"5"
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
127.0.0.1:6379> rpop list2
"1"
127.0.0.1:6379> lrange list2 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
127.0.0.1:6379>
127.0.0.1:6379> LINDEX list1 0
"4"
127.0.0.1:6379> llen list1
(integer) 4
127.0.0.1:6379>

 

127.0.0.1:6379> rpush list3 1 1 1 2 2 2 3 3 3 4 4 4
(integer) 12
127.0.0.1:6379> LRANGE list3 0 -1
 1) "1"
 2) "1"
 3) "1"
 4) "2"
 5) "2"
 6) "2"
 7) "3"
 8) "3"
 9) "3"
10) "4"
11) "4"
12) "4"
127.0.0.1:6379> lrem list3 2 3
(integer) 2
127.0.0.1:6379> LRANGE list3 0 -1
 1) "1"
 2) "1"
 3) "1"
 4) "2"
 5) "2"
 6) "2"
 7) "3"
 8) "4"
 9) "4"
10) "4"
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> ltrim list3 2 6
OK
127.0.0.1:6379> LRANGE list3 0 -1
1) "1"
2) "2"
3) "2"
4) "2"
5) "3"
127.0.0.1:6379>

 

127.0.0.1:6379> lpush list4 java python golang
(integer) 3
127.0.0.1:6379> lrange list4 0 -1
1) "golang"
2) "python"
3) "java"
127.0.0.1:6379> linsert list4 before python x
(integer) 4
127.0.0.1:6379> linsert list4 after python y
(integer) 5
127.0.0.1:6379> lrange list4 0 -1
1) "golang"
2) "x"
3) "python"
4) "y"
5) "java"
127.0.0.1:6379> lset list4 1 y
OK
127.0.0.1:6379> lrange list4 0 -1
1) "golang"
2) "y"
3) "python"
4) "y"
5) "java"
127.0.0.1:6379> linsert list4 before y www
(integer) 6
127.0.0.1:6379> lrange list4 0 -1
1) "golang"
2) "www"
3) "y"
4) "python"
5) "y"
6) "java"
127.0.0.1:6379>

这里须要注意:linsert在插入时,若是对应的元素存在多个相同值的元素,那么只会相对于第一个符合的元素的位置进行插入。

rpoplpush是针对将一个列表中尾部的元素迅速插入到另外一个列表的头部的情景。

127.0.0.1:6379> rpush list5 aa bb cc
(integer) 3
127.0.0.1:6379> lrange list5 0 -1
1) "aa"
2) "bb"
3) "cc"
127.0.0.1:6379> rpoplpush list4 list5
"java"
127.0.0.1:6379> lrange list4 0 -1
1) "golang"
2) "www"
3) "y"
4) "python"
5) "y"
127.0.0.1:6379> lrange list5 0 -1
1) "java"
2) "aa"
3) "bb"
4) "cc"
127.0.0.1:6379>

 

性能总结:

它是一个字符串链表,left、right均可以插入添加

若是键不存在,穿件新的链表

若是键已经存在,建立新的链表

若是值所有移除,对应的键也就消失了

链表的操做不管是头和尾,效率都极高,但假如是对中间元素进行操做,效率就会很低。

 

 

Set集合

在Java中,HashSet的底层实现实际上是一个HashMap。

Redis的Set是string类型的无须集合。它是经过HashTable实现的。

Redis集合(Set)
    经常使用
    单值多value
    案例
         sadd/smembers/sismember  添加元素、输出set的全部成员、判断一个元素是不是set的成员
         scard,获取集合里面的元素个数
         srem key value 删除集合中元素
         srandmember key 某个整数(随机出几个数)
         spop key 随机出栈
         smove key1 key2 在key1里某个值      做用是将key1里的某个值赋给key2
         数学集合类
            差集:sdiff
            交集:sinter
            并集:sunion

127.0.0.1:6379> sadd set01 1 1 2 2 3 3 3
(integer) 3
127.0.0.1:6379> SMEMBERS set01
1) "1"
2) "2"
3) "3"
127.0.0.1:6379>
127.0.0.1:6379> SISMEMBER set01 1
(integer) 1
127.0.0.1:6379> SISMEMBER set01 2
(integer) 1
127.0.0.1:6379> SISMEMBER set01 3
(integer) 1
127.0.0.1:6379> SISMEMBER set01 4
(integer) 0

 

127.0.0.1:6379> keys *
1) "set01"
127.0.0.1:6379>
127.0.0.1:6379> SCARD set01
(integer) 3
127.0.0.1:6379> SCARD set02
(integer) 0

删除元素

127.0.0.1:6379> SREM set01 2
(integer) 1
127.0.0.1:6379> SMEMBERS set01
1) "1"
2) "3"
127.0.0.1:6379>

随机取数

127.0.0.1:6379> sadd set02 1 2 3 4 5 6 7 8 9
(integer) 9
127.0.0.1:6379> SRANDMEMBER set02 3
1) "3"
2) "7"
3) "4"
127.0.0.1:6379>
127.0.0.1:6379> SRANDMEMBER set02 3
1) "3"
2) "8"
3) "2"
127.0.0.1:6379> SRANDMEMBER set02 3
1) "1"
2) "6"
3) "2"
127.0.0.1:6379>
127.0.0.1:6379> SRANDMEMBER set02
"4"
127.0.0.1:6379> SRANDMEMBER set02
"5"
127.0.0.1:6379> SRANDMEMBER set02
"5"
127.0.0.1:6379> SRANDMEMBER set02
"1"
127.0.0.1:6379>

随机出栈

127.0.0.1:6379> spop set02
"2"
127.0.0.1:6379> spop set02
"5"
127.0.0.1:6379> SMEMBERS set02
1) "1"
2) "3"
3) "4"
4) "6"
5) "7"
6) "8"
7) "9"
127.0.0.1:6379> spop set02 2
1) "4"
2) "7"
127.0.0.1:6379> spop set02 3
1) "1"
2) "9"
3) "3"
127.0.0.1:6379> SMEMBERS set02
1) "6"
2) "8"
127.0.0.1:6379>

smove key1 key2 在key1里某个值      做用是将key1里的某个值赋给key2

127.0.0.1:6379> keys *
1) "set02"
2) "set01"
127.0.0.1:6379> SMEMBERS set01
1) "1"
2) "3"
127.0.0.1:6379> SMEMBERS set02
1) "6"
2) "8"
127.0.0.1:6379> SMOVE set01 set02 3
(integer) 1
127.0.0.1:6379> SMEMBERS set01
1) "1"
127.0.0.1:6379> SMEMBERS set02
1) "3"
2) "6"
3) "8"
127.0.0.1:6379> SMOVE set01 set02 7
(integer) 0
127.0.0.1:6379>

删除键

127.0.0.1:6379> del set01
(integer) 1
127.0.0.1:6379> del set02
(integer) 1
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379>
127.0.0.1:6379> SADD set01 1 2 3 4 5
(integer) 5
127.0.0.1:6379> SADD set02 1 2 3 a b
(integer) 5

 差集:sdiff

127.0.0.1:6379> SDIFF set01 set02
1) "4"
2) "5"


交集:sinter

127.0.0.1:6379> SINTER set01 set02
1) "1"
2) "2"
3) "3"


 并集:sunion

127.0.0.1:6379> SUNION set01 set02
1) "4"
2) "1"
3) "2"
4) "b"
5) "a"
6) "5"
7) "3"

 

Hash哈希

redis hash是一个键值对的集合。

redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象,相似Java里的map<String,Object>

Redis哈希(Hash)
    KV模式不变,但V是一个键值对

  经常使用命令以下:红色的必定牢记
         hset/hget/hmset/hmget/hgetall/hdel
         hlen
         hexists key 在key里面的某个值的key
         hkeys/hvals
         hincrby/hincrbyfloat
         hsetnx

127.0.0.1:6379> hset personA name happybks
(integer) 1
127.0.0.1:6379> hget personA name
"happybks"

127.0.0.1:6379> hmset personA gender male age 18 score 100.0
OK
127.0.0.1:6379> hget personA age
"18"
127.0.0.1:6379> hmget personA name score
1) "happybks"
2) "100.0"

127.0.0.1:6379> hgetall personA
1) "name"
2) "happybks"
3) "gender"
4) "male"
5) "age"
6) "18"
7) "score"
8) "100.0"
127.0.0.1:6379>

127.0.0.1:6379> HDEL personA gender
(integer) 1
127.0.0.1:6379> HGET personA gender
(nil)
127.0.0.1:6379>

 

127.0.0.1:6379> HLEN personA
(integer) 3
127.0.0.1:6379> HKEYS personA
1) "name"
2) "age"
3) "score"
127.0.0.1:6379> HVALS personA
1) "happybks"
2) "18"
3) "100.0"
127.0.0.1:6379>

这里自增注意的是:即便原先的值是整型或者浮点数,两种自增方式均可以使用;自增若补偿为负值即为自减。

127.0.0.1:6379> HINCRBY personA age 1
(integer) 19
127.0.0.1:6379> HINCRBY personA age 2
(integer) 21
127.0.0.1:6379> HINCRBYFLOAT personA score -1.5
"98.5"
127.0.0.1:6379> HINCRBYFLOAT personA score 1.5
"100"
127.0.0.1:6379> HINCRBYFLOAT personA age 1.5
"22.5"
127.0.0.1:6379> HINCRBYFLOAT personA age -1.5
"21"
127.0.0.1:6379> HINCRBY personA score 50
(integer) 150
127.0.0.1:6379>

hsetnx value中的键值对有此键则失败,无则成功设置键-键的值。

127.0.0.1:6379> HSETNX personA age 24
(integer) 0
127.0.0.1:6379>
127.0.0.1:6379> HSETNX personA email happybks@123.com
(integer) 1
127.0.0.1:6379>
127.0.0.1:6379> HGETALL personA
1) "name"
2) "happybks"
3) "age"
4) "21"
5) "score"
6) "150"
7) "email"
8) "happybks@123.com"
127.0.0.1:6379>

 

Zset(sorted set)有序集合

Hash是无须的。Redis zset和set同样也是string类型元素的集合,且不容许重复的元素。

不一样的是每一个元素会关联一个double类型的份数。

redis正式经过这个分数来为集合中的成员进行从小到大的排序。

zset成员是惟一的,但分数能够重复。

能够联想一下网络游戏中的多人在线的分数更新等等。

Redis有序集合Zset(sorted set)
    在set基础上,加一个score值。
以前set是k1 v1 v2 v3,
如今zset是k1 score1 v1 score2 v2
    经常使用命令以下:
         zadd/zrange【withscores】
         zrangebyscore key 开始score 结束score
             withscores
             (   不包含
            limit 做用是返回限制
                 limit 开始下标步 多少步
         zrem key 某score下对应的value值,做用是删除元素
         zcard/zcount key score区间

         /zrank key values值,做用是得到下标值

         /zscore key 对应值,得到分数
         zrevrank key values值,做用是逆序得到下标值
         zrevrange
         zrevrangebyscore  key 结束score 开始score

 

首先咱们须要注意的是zset在添加新元素以后,它默认是按照分数进行排序的。不管你是先添加仍是后添加。

127.0.0.1:6379> ZADD zset1 2000 L1
(integer) 1
127.0.0.1:6379> ZADD zset1 4000 L2 6000 L3
(integer) 2
127.0.0.1:6379> ZADD zset1 8000 L4 100000 L5 12000 L6 0 L0
(integer) 4
127.0.0.1:6379> ZRANGE zset1 0 -1
1) "L0"
2) "L1"
3) "L2"
4) "L3"
5) "L4"
6) "L6"
7) "L5"
127.0.0.1:6379> ZRANGE zset1 0 -1 withscores
 1) "L0"
 2) "0"
 3) "L1"
 4) "2000"
 5) "L2"
 6) "4000"
 7) "L3"
 8) "6000"
 9) "L4"
10) "8000"
11) "L6"
12) "12000"
13) "L5"
14) "100000"
127.0.0.1:6379>

127.0.0.1:6379> ZADD zset1 -1000 L7
(integer) 1
127.0.0.1:6379> ZRANGE zset1 0 -1 withscores
 1) "L7"
 2) "-1000"
 3) "L0"
 4) "0"
 5) "L1"
 6) "2000"
 7) "L2"
 8) "4000"
 9) "L3"
10) "6000"
11) "L4"
12) "8000"
13) "L6"
14) "12000"
15) "L5"
16) "100000"
127.0.0.1:6379>

 

127.0.0.1:6379> ZRANGEBYSCORE zset1 2000 12000
1) "L1"
2) "L2"
3) "L3"
4) "L4"
5) "L6"
127.0.0.1:6379> ZRANGEBYSCORE zset1 2000 (12000
1) "L1"
2) "L2"
3) "L3"
4) "L4"
127.0.0.1:6379> ZRANGEBYSCORE zset1 (2000 (12000
1) "L2"
2) "L3"
3) "L4"
127.0.0.1:6379> ZRANGEBYSCORE zset1 2000 12000 limit 2 3
1) "L3"
2) "L4"
3) "L6"
127.0.0.1:6379> ZRANGEBYSCORE zset1 2000 12000 limit 3 2
1) "L4"
2) "L6"
127.0.0.1:6379>

删除zset中的某个value,注意删除的是value(附带删除score),而不是删除score(附带删除value)

127.0.0.1:6379> ZREM zset1 100000
(integer) 0
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> ZREM zset1 L5
(integer) 1
127.0.0.1:6379>

注意,按照区间查询符合分数区间的值个数,区间的分数能够不存在与已有的值分数中,且一样能够支持不包含操做(。

127.0.0.1:6379> ZCARD zset1
(integer) 7

127.0.0.1:6379>
127.0.0.1:6379> ZCOUNT zset1 3000 9000
(integer) 3
127.0.0.1:6379>
127.0.0.1:6379> ZCOUNT zset1 3000 12000
(integer) 4
127.0.0.1:6379> ZCOUNT zset1 3000 (12000
(integer) 3
127.0.0.1:6379>

反馈下标,第几个。分正序和倒序。从0开始。

127.0.0.1:6379> ZRANK zset1 L4
(integer) 5

127.0.0.1:6379> ZREVRANK zset1 L4
(integer) 1
127.0.0.1:6379>

一样,查询也能够正序倒序,也能够附带分数。

127.0.0.1:6379> ZRANGE zset1 0 -1
1) "L7"
2) "L0"
3) "L1"
4) "L2"
5) "L3"
6) "L4"
7) "L6"
127.0.0.1:6379> ZREVRANGE zset1 0 -1
1) "L6"
2) "L4"
3) "L3"
4) "L2"
5) "L1"
6) "L0"
7) "L7"
127.0.0.1:6379> ZREVRANGE zset1 0 -1 withscores
 1) "L6"
 2) "12000"
 3) "L4"
 4) "8000"
 5) "L3"
 6) "6000"
 7) "L2"
 8) "4000"
 9) "L1"
10) "2000"
11) "L0"
12) "0"
13) "L7"
14) "-1000"
127.0.0.1:6379>

还能够经过指定分数范围来显示值。可是请必定注意:与以前经过下标指定范围查询不一样,按照分数的倒序查询时,分数的左右区间也是从大到小 倒过来的!!!

127.0.0.1:6379> ZRANGEBYSCORE zset1 4000 9000
1) "L2"
2) "L3"
3) "L4"
127.0.0.1:6379> ZREVRANGEBYSCORE zset1 4000 (12000
(empty list or set)
127.0.0.1:6379> ZREVRANGEBYSCORE zset1 (12000 4000
1) "L4"
2) "L3"
3) "L2"
127.0.0.1:6379>

 

另外介绍一个方便查找的在线文档:http://redisdoc.com/

关于每一个类型的具体redis命令将在下面的几篇文章中接收

相关文章
相关标签/搜索