五大数据类型

string

一个key对应一个value(和Memcached一样),字符串是一种最基本的Redis值类型。Redis字符串是二进制安全的,这意味着一个Redis字符串能包含任意类型的数据,例如: 一张JPEG格式的图片或者一个序列化的Ruby对象,一个字符串类型的值最多能存储512M字节的内容。

基础命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 常见增删改
1.get set
2.append k1 12345
3.strlen k1 获取长度
4.incr k2 (set k2 2)增加整数的值比如浏览量加放在redis
5.decr k2 减
6.incrby k2 3 加3
7.decrby k2 2 减2(封装原子操作,一个线程加,一个减)

8.getrange # 获取区间范围的值类似与between and
 getrange k1 0 -1 # 获取0到-1的值
 getrange k1 0 3 # 和切片一样
 
9.setrange修改开始位置的值
 setrange k1 0 xxx 把前三个数设置为xxx
 get k1
 
10.setex(set with expire)键秒值/setnx(set if not exists)
  setex k1 10 v4设置10秒过期
  setnx k1 v100返回0表示已存在无法设置
  
11.mset/mget/msetnx
 d多个设置,获取
 mset k1 v1 k2 v2 k3 v3
 msetnx k1 v1 k5 v5 只要有一个存在就翻车
 
12.getset
 getset k1 v100(获取原来的值,赋予新的值)

应用场景

  • 作为邮件开关,点击开关
  • 计数器,粉丝数、购买人数、浏览人数、限流(incr,decr)
  • 使用setbit/getbit实现bloom过滤器

这里需要注意的是,redis本身是单线程的,所以做计数器不用考虑并发带来的影响,且redis内存存储并支持集群、持久化的特性,使得redis高效快速,适合做高并发系统的计数器。bloom是解决缓存穿透的有效方法(请求进来先用bloom判断是否存在,存在再去那数据不存在直接返回),也是过滤一些特定大数据的解决方案(比如几亿的用户,需要看进来的用户是否是新用户

内部源码

list

redis的list底层是双向链表的结构,其底层实现有三种linkdlist、ziplist和quicklist。

  • redis 3.2之前
    默认使用linklist和ziplist
    linklist作为基础的朴素双向链表。
    ziplist作为基本存储的压缩双向链表,ziplist所有信息保存在连续的内存中,每次修改都需要realloc或者memmove,所以效率比较低,是为了节省内存设计的。
    ziplist要求单个节点小于64bytes,总数量小于512个,当数据量超出标准就会使用linkedlist,最大为2**32-1个值
  • redis 3.2 之后
    使用quicklist作为默认底层

基础命令

1
2
3
4
5
6
7
8
9
10
11
lpush/rpush k v
lrange k start end
lpushx/rpushx k v(当k不存在不会创建)
lpop/rpop k
lrem k count v 移除指定个数的值为v的元素,count=0移除所有
ltrim k start end 截取并保留范围值
lindex k idx 索引
llen k
linsert k after|before v value 在固定的某个元素前或者后插入元素
rpoplpush k v
lset k idx v

应用场景

  • 消息队列(celery)安全消息队列复制一份进行操作避免消费者异常
  • 排行榜(每隔一段时间更新一次)
  • 最新列表(点赞列表、评论列表)(固定条数左进右出)

内部源码

ziplist源码分析

ziplist是一种特殊编码的节省内存空间的双链表,能以O(1)的时间复杂度在两端push和pop数据,具有如下结构:

  • zlbytes是一个unsigned integer,保存ziplist占用的总内存空间,在重新分配内存时,借助这个字段可以不用遍历整个ziplist;
  • zltail是指向最后一个entry的偏移量,这样对于尾部的操作不用去遍历所有entry;
  • zllen固定两个字节长度,表示entry的数量,最大能表示2^16-2个entry,如果超过了,则其值为2^16-1,需要遍历entry才能知道具体的数量;
  • zlend固定一个字节,值固定为255,表示ziplist的结尾。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # ziplist.c
    /* Create a new empty ziplist. */
    unsigned char *ziplistNew(void) {
    unsigned int bytes = ZIPLIST_HEADER_SIZE+1;
    unsigned char *zl = zmalloc(bytes);
    ZIPLIST_BYTES(zl) = intrev32ifbe(bytes);
    ZIPLIST_TAIL_OFFSET(zl) = intrev32ifbe(ZIPLIST_HEADER_SIZE);
    ZIPLIST_LENGTH(zl) = 0;
    zl[bytes-1] = ZIP_END;
    return zl;
    }

    hash

    KV模式不变,但v是一个键值对,理论最大为2^32-1个键值对

基础命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1.hset/hget/hmset/hmget/hgetall/hdel
hset user id 11
hget user id
hmset cutomer name z3 id 2 age 26
hmget customer id name age
hgetall customer
hdel user name
2.hlen user
3.hexists key
hexists customer id
4.hkeys/hvals
hkeys customer 获取所有的键/值
5.hincrby/hincrbyfloat
hincrby customer age 1
hset customer score 91.5
hincrby customer score 1.5
6.hsetnx

应用场景

  • 用户信息存储,如果用string存储用户信息打包,内容修改时需要取出全部信息,使用hash只需要取出该字段即可。
  • 购物车数据,未登录用cookie存储购物车数据,登录使用redis的hash存储数据。

内部源码

set

基础命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1.sadd/smembers/sismember
sadd set01 1 1 2 2 3 3会把重复的数去掉并构建set
smembers set01 查看set01的元素
sismember set01 x 是成员返回1不是0
2.scard
scard set01 获取set01元素个数
3.srem key vlaue 删除集合中的元素
srem set01 3
4.srandmember set02 3从集合中随机取出3个
(就像什么抽红包,从100个里面随机抽10个)
5.spop key 随机出栈
spop set01
6.smove key1 key2 val在key1里的某个值 赋给key2
smove set02 set01 7
smembers set01
7.数学集合类
差集:sdiff
sdiff set01 set02 在第一个里面不在第二个里面的
sdiff set02 set01
交集:sinter
sinter set01 set02相交部分
并集:sunion set01 set02

应用场景

  • 共同好友、共同关注、相似关注、共同喜好
  • 可以将一个用户的所有关注存在一个集合,粉丝存在一个集合
  • 去重
  • 内部源码

    zset和set一样也是string类型元素的集合,且不允许重复的成员不同的是(在set的基础上加)每个元素都会关联一个double类型的分数,redis正是通过分数来为集合中的成员来进行大小排序,zset的成员是唯一的,但分数score可以重复。

zset(sorted set)

基础命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1.zadd/zrange
zadd zset01 60 v1 70 v2 80 v3 90 v4 100 v5
zrange zset01 0 -1
zadd 60 v9
zrange zset01 0 -1 withscores
2.zrangebyscore key
zrangebyscore zset 60 90 60到90分的
3.zrangebyscore zset01 (60 (90
大于60小于90不包含
4. zrangebyscore key 60 90 limit 2 2
从第二个开始截取两个
5.zrem zseto1 v5
删除v5
6.zcard 统计个数
zcard zset01
7.zcount + key + score区间
zcount zset01 60 80统计60到80的数量
8.zrank zset04 v4获取下标的值(索引值)
9.zscore zset01 v4获取v4的得分
10.zrevrank key values 逆序获得下标
11.zrevrange zset01 0 -1逆序遍历
12.zrevrangebyscore key

应用场景

  • 排行榜
  • 带权重的消息队列

内部源码

分享到