Skip to content

简介

Redis是一个高性能的key-value数据库。Redis对数据的操作都是原子性的。

优缺点

优点:

  1. 基于内存操作,内存读写速度快。
  2. Redis是单线程的,避免线程切换开销及多线程的竞争问题。单线程是指在处理网络请求(一个或多个redis客户端连接)的时候只有一个线程来处理,redis运行时不只有一个 线程,数据持久化或者向slave同步aof时会另起线程。
  3. 支持多种数据类型,包括String、Hash、List、Set、ZSet等。
  4. 支持持久化。Redis支持RDB和AOF两种持久化机制,持久化功能有效地避免数据丢失问题。
  5. redis采用IO多路复用技术。多路指的是多个socket连接,复用指的是复用一个线程。redis使用单线程俩轮询描述符,将数据库的开、关、读、写都转换成了时间。多路复用主要有三种技术:select、poll、epoll。epoll是最新的也是目前最好的多路复用技术。

缺点:对join或其他结构化查询的支持就比较差。

io多路复用

应用场景

  1. 缓存热点数据,缓解数据库的压力
  2. 利用Redis中原子性的自增操作,可以用于实现计算器的功能,比如统计用户点赞数、用户访问数等,这类操作如果用MySQL,频繁的读写会带来相当大的压力。
  3. 简单消息队列,不要求高可靠地情况下,可以使用Redis自身的发布/订阅模式或者List来实现一个队列,实现异步操作。
  4. 好友关系,利用集合的一些命令,比如求交集、并集、差集等。可以方便搞定一些共同好友、共同爱好之类的功能。
  5. 限速器,比较典型的使用场景是限制某个用户访问某个API的频率,常用的有抢购,防止用户疯狂点击带来不必要的压力。

Redis支持五种数据类型:

  • string(字符串)
  • hash(哈希)
  • list(列表)
  • set(集合)
  • zset(sorted set)

String

String类型是二进制安全的,意思是 redis 的 string 可以包含任何数据。如数字,字符串,jpg图片或者序列化对象。

常用命令

命令简述使用
get读取存储在给定键中的值get key
set设置存储在给定键中的值set key value
del删除存储在给定键中的值del key
incr将键存储的值加1incr key
decr将键存储的值减1decr key
incrby将键存储的值加上指定整数incrby key num
decrby将键存储的值减去指定整数decrby key num
  • 赋值(set)和取值(get)

    shell
    set name gmt
    get name
  • 递增(incr)和递减(decr)

    bash
    incr num // 若键值不是整数时,会提示错误
    incrby num 3 // 增加指定整数
    decr num // 递减数字
    incrbyfloat num 12.3 // 增加指定浮点数
  • 其他

    key list* 列出所有匹配的key

    append name "123"追加值

    strlen name 获取字符串长度

    mset num 1 float 2 同时设置多个值

    mget name gender 同时获取多个值

    getbit name 0 获取0索引处二进制位的值

    flushdb 删除当前数据库所有的key

    flushall 删除所有数据库中的key

  • setnx和setex

setnx key value:当key不存在时,将key的值设为value。若给定的key已经存在,则SETNX不做任何操作。

setex key seconds value:比SET多了seconds参数,相当于SET KEY value + EXPIRE KEY seconds,而且SETEX是原子性操作。

  • expire
dart
expire key num // 设置key过期时间为num秒
ttl key // 查看键的剩余生存时间,-1为永不过期

expire时间单位是秒,pexpire时间单位是毫秒。

在键未过期前可以重新设置过期时间,过期之后键被销毁。

注意:

  • 如果key不存在或者已过期,返回-2
  • 如果key存在并且没有设置过期时间(永久有效),返回-1

实战场景

  • 缓存:经典使用场景,把常用信息,字符串,图片或者视频等信息放到redis中,redis作为缓存层,mysql作为持久化层,降低mysql的读写压力。
  • 计数器:redis是单线程模型,一个命令执行完才会执行下一个,同时数据可以一步落地到其他的数据源。
  • session:常见方案spring session + redis 实现session共享。

List

Redis中的List其实就是链表(Redis使用双端链表实现List)

常用命令

命令简述使用
rpush将给定值推入到列表右端rpush list value
lpush将给定值推入到列表左端lpush list value
rpop从列表的右端弹出一个值,并返回被弹出的值rpop list
lpop从列表的左端弹出一个值,并返回被弹出的值lpop list
lrange获取列表在给定范围上的所有值lrange list 0 -1
lindex通过索引获取列表中的元素,可以使用负数下标,-1表示最后一个,-2表示倒数第二个,以此类推lindex key index
linsert从左到右寻找职位pivot的值,向列表插入valuelinsert list after(before) pivot value 往pivot后面(前面)插入value;
ltrim删除索引begin到end以外的所有元素ltrim list begin end
llen获取列表元素个数llen list
lset修改指定索引处的值lset list index value

常用技巧

  • lpush + lpop = Stack(栈)
  • lpush + rpop = Queue(队列)
  • lpush + ltrim = Capped Collection(有限集合)
  • lpush + brpop = Message Queue(消息队列)

实战场景

  • 微博TimeLine:有人发布微博,用lpush加入时间轴,显示新的消息列表
  • 消息队列

Set

Redis 的 Set 是String类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

Redis 中集合是通过哈希表实现的,所以添加、删除、查找的时间复杂度都是O(1)

常用命令

命令简述使用
sadd向集合添加一个或多个成员sadd set value1 value2...
scard获取集合的成员数scard set
smembers返回集合中的所有成员smembers set
srem删除集合中一个或多个成员srem set value1,value2...
sismember判断元素是否在集合中sismember set value
sdiff差集运算sdiff setA setB ...
sinter交集运算sinter setA setB ...
sunion并集运算sunion setA setB ...
srandmember随机获取集合里的一个元素,count大于0,则从集合随机获取count个不重复元素,count小于0,则随机获取的count个元素有些可能相同srandmember set count

实战场景

  • 标签:给用户添加标签,或者用户给消息添加标签,这样有同一标签或者类似标签的可以给推荐关注的事或这关注的人。
  • 点赞,点踩,收藏

Hash

Redis hash 是一个string类型的field(字段)和value(值)的映射表,hash特别适合用户存储对象。

常用命令

命令简述使用
hset添加键值对hset myhash key1 value1 key2 value2 ...
hget获取指定散列键的值hget myhash key1
hgetall获取散列中包含的所有键值对hgetall myhash
hdel如果给定键存在于散列中,那么就移除这个键hdel myhash key1

实战场景

  • 缓存:能直观,相比string更节省空间

Zset

Redis 有序集合和集合一样也是string类型的元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

有序集合的成员是唯一的,但是分数(score)可以重复。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)

常用命令

命令简述使用
zadd将一个带有给定分值的成员添加到有序集合里面zadd zset key
zrange根据元素在有序集合中所处的位置,从有序集合中获取多个元素zrange zset 0 2 withscores
zrem如果给定元素成员存在于有序集合中,那么就移除这个元素zrem zset member

实战场景

  • **排行榜:**有序集合经典使用场景。例如小说视屏等网站需要对用户上传的小说视频做排行榜,榜单可以按照用户关注数、更新时间、字数等打分,做排行。