Redis介绍、安装以及数据结构(操作命令)

Redis介绍

什么是Redis

Redis是用C语言开发的一个开源(BSD许可)的高性能键值对key-value)内存数据库,可以用作数据库、缓存和消息中间件。它是一种NoSQL(NOT-Only Sql,泛指非关系型数据库)数据库

  • 性能优秀,数据在内存中,读写速度非常快,支持并发10W QPS
  • 单进程单线程,是线程安全的,采用IO多路复用
  • 丰富数据类型:字符串(strings),散列(hashes),列表(lists),集合(sets),有序集合(sorted sets) 等
  • 支持数据持久化,可以将内存中数据保存在磁盘中,重启时加载
  • 主从复制

Redis应用场景

  • 内存数据库(登录信息、购物车信息、用户浏览记录等)
  • 缓存服务器(商品数据、广告数据等等)(最多使用
  • 解决分布式集群架构中的 session 分离问题( session 共享)
  • 任务队列(秒杀、抢购、12306等等)
  • 分布式锁的实现
  • 支持发布订阅的消息模式
  • 应用排行榜(有序集合)
  • 网站访问统计
  • 数据过期处理(可以精确到毫秒)

Redis安装启动(单机)

Redis没有官方的Windows版本,建议在Linux系统上安装运行

Linux下安装启动

安装

Redis的官网为redis.io,在官网上可以获取最新的版本

下载解压

$ wget http://download.redis.io/releases/redis-5.0.5.tar.gz
$ tar xzf redis-5.0.5.tar.gz

进入目录、编译

$ cd redis-5.0.5
$ make

编译完成的二进制文件是在src目录下,其中redis-server为服务端程序,redis-cli为客户端程序

安装

还可以通过make install命令安装到指定目录,通过PREFIX指定安装目录

$ make install PREFIX=/usr/local/redis

命令说明

  • redis-server:启动 redis 服务
  • redis-cli:进入 redis 命令客户端
  • redis-benchmark: 性能测试的工具
  • redis-check-aof: aof 文件进行检查的工具
  • redis-check-dump: rdb 文件进行检查的工具
  • redis-sentinel: 启动哨兵监控服务

启动

启动Redis的命令为redis-server,运行安装目录下的redis-server

$ /usr/local/redis/bin/redis-server

关闭ctrl+c,这种方式启动,我们的连接窗口关闭,Redis也会关闭,我们会希望它在后台一直运行着,就需要后端启动

后端启动(守护进程启动)

1)从解压文件中redis-5.0.5复制redis.conf配置文件到安装目录下的bin目录

$ cp /root/redis-5.0.5/redis.conf /usr/local/redis/bin/ 

2)修改redis.conf配置文件

$ vim redis.conf
# 将`daemonize`由`no`改为`yes`
daemonize yes
# 默认绑定的是回环地址,默认不能被其他机器访问
# bind 127.0.0.1
# 是否开启保护模式,由yes该为no
protected-mode no

3)启动redis-server服务

./redis-server redis.conf 

4)关闭服务

./redis-cli shutdown

命令行客户端

启动客户端的命令是redis-cli,它有两个参数

  • -h:redis服务器的ip地址(默认为127.0.0.1)

  • -p:redis实例的端口号(默认为6379)

./redis-cli -h 127.0.0.1 -p 6379 

Windows安装

虽然官方并没有Windows版本,但是Microsoft有开发和维护64位的Redis,下载地址为https://github.com/microsoftarchive/redis/releases

这里下载Redis-x64-xxx.zip并解压,进入解压后的目录,以下命令是启动redis

redis-server redis.windows.conf

客户端连接为

redis-cli.exe -h 127.0.0.1 -p 6379

Redis数据结构及操作命令

Redis是通过key-value的格式来存储数据的,key是二进制安全的字符串,其中value是支持多种数据类型的,我们需要了解和掌握如下5种数据类型

  • 字符串(String):二进制安全的字符串,可以是字符串、整数或浮点数
  • 散列(Hash):一个String类型的field和value的映射表,适合存储对象
  • 列表(List):字符串列表,按插入顺序排序
  • 集合(Set):字符串无序集合,去重
  • 有序集合(Sorted Set,zset):与Set相同,不同的是根据score排序

字符串(String)

命令

set/get 赋值/取值

语法

# 赋值
SET key value [EX seconds] [PX milliseconds] [NX|XX]
# 取值 
GET key
# 设置新值,返回旧值
GETSET key value
  • EX seconds:键过期时间
  • PX milliseconds:为键设置毫秒级过期时间
  • NX:键必须不存在才可以设置成功,用于添加
  • XX:键必须存在,才可以设置成功,用于更新

示例:

127.0.0.1:6379> set test 123
OK
127.0.0.1:6379> get test
"123"

incr/incrby/decr/decrby 数值增减

当value值为整数时,才可以使用数值增减命令,incr/decr为增加/减少1,incrby/decrby为增加/减少具体的数值,数值的增减是原子操作

127.0.0.1:6379> set counter 100
OK
127.0.0.1:6379> incr counter
(integer) 101
127.0.0.1:6379> incrby counter 20
(integer) 121
127.0.0.1:6379> decr counter
(integer) 120
127.0.0.1:6379> decrby counter 10
(integer) 110

mset/mget 同时设置/获取多个键值

在单个命令中设置/获取多个键值是可以减少延迟的

127.0.0.1:6379> mset k1 10 k2 20 k3 30
OK
127.0.0.1:6379> mget k1 k2 k3
1) "10"
2) "20"
3) "30"

使用场景

  • 常规的key-value缓存

  • 计数:微博数、粉丝数等

  • 应用INCR原子计数生产全局唯一id或单号

散列(Hash)

命令

hset/hget/hmset/hmget 设置/取值

# 设置一个字段值
HSET key field value 
# 设置多个字段值
HMSET key field value [field value ...]
# 字段不存在时赋值
HMSETNX key field value
# 获取一个字段值
HGET key field 
# 获取多个字段值
HMGET key field [field ...] 
# 获取所有字段值
HGETALL key
127.0.0.1:6379> hmset user name zou age 23
OK
127.0.0.1:6379> hset user location Guangzhou
(integer) 1
127.0.0.1:6379> hget user name
"zou"
127.0.0.1:6379> hgetall user
1) "name"
2) "zou"
3) "age"
4) "23"
5) "location"
6) "Guangzhou"

hincrby 增加数字

# 增加数字
HINCRBY key field increment 
127.0.0.1:6379> hincrby user age 1
(integer) 24

其他命令

# 判断字段是否存在
HEXISTS key field
# 只获取字段名
HKEYS key
# 只获取字段值
HVALS key
# 获取字段数量
HLEN key
# 获取所有字段和值
HGETALL key

String和Hash的区别

Hash类型适合存储那些对象数据,特别是对象属性经常发生【增删改】操作的数据。 String类型也可以存储对象数据,将Java对象转成json字符串或序列化进行存储,这种存储适合【查询】操作

使用场景

  • 存储结构化数据对象,如用户信息、商品信息

列表(List)

Redis的列表是链表结构的,可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素,或者获得列表的某一个片段

列表类型内部是使用双向链表(double linked list)实现的,所以向列表两端添加元素的时间复杂度为0(1) ,获取越接近两端的元素速度就越快。这意味着即使是一个有几千万个元素的列表,获取头部或尾部的10条记录也是极快的

命令

lpush/rpush 添加新元素到列表

# 列表的左端添加元素
LPUSH key value [value ...]
# 列表的右端添加元素
RPUSH key value [value ...]
127.0.0.1:6379> lpush list:1 1 2 3 
(integer) 3 
127.0.0.1:6379> rpush list:1 4 5 6 
(integer) 3 

lrange 获取列表片段

获取列表中的某一片段,返回startstop之间的所有元素(包含两端的元素),索引从0开始,索引可以是负数,表明从结尾开始计数:所以-1是最后一个元素,-2是列表的倒数第二个元素

LRANGE key start stop
127.0.0.1:6379> lrange  list:1 0 2 
1) "2" 
2) "1" 
3) "4"

lpop/rpop 从列表两端弹出元素

从列表两端弹出一个元素,会分两步完成:

  • 第一步是将列表左边的元素从列表中移除
  • 第二步是返回被移除的元素值
LPOP key
RPOP key
127.0.0.1:6379>lpop list:1 
"3“ 
127.0.0.1:6379>rpop list:1 
"6“

其他命令

# 获取列表中元素的个数
LLEN key
# 删除列表中指定个数的值
# - 当count>0时, LREM会从列表左边开始删除。
# - 当count<0时, LREM会从列表后边开始删除。
# - 当count=0时, LREM删除所有值为value的元素
LREM key count value
# 获取指定索引的元素值
LINDEX key index
# 只保留列表指定片段,指定范围和lrange一致
LTRIM key start stop
# 向列表中插入元素
LINSERT key BEFORE|AFTER pivot value
# 将元素从一个列表转移到另一个列表中
RPOPLPUSH source destination

使用场景

  • 各种列表:关注列表、粉丝列表、评论
  • 消息队列,可以利用Lists的PUSH操作,将任务存在Lists中,然后工作线程再用POP操作将任务取出执行
  • 利用LRANGE可以很方便的实现list内容分页的功能
  • 取最新N个数据的操作

集合(Set)

Set是字符串的无序集合,其中的数据是不重复没有顺序,集合类型的常用操作是向集合中加入或删除元素、判断某个元素是否存在等,由于集合类型的Redis内部是使用值为空的散列表实现,所有这些操作的时间复杂度都为 0(1),Redis 还提供了多个集合之间的交集、并集、差集的运算

命令

sadd/srem 添加/删除元素

SADD key member [member ...]
SREM key member [member ...]
127.0.0.1:6379> sadd set a b c 
(integer) 3 
127.0.0.1:6379> sadd set a 
(integer) 0 
127.0.0.1:6379> srem set c d 
(integer) 1 

smembers 获取所有元素

SMEMBERS key 
127.0.0.1:6379> smembers set 
1)  "b" 
2)  "a”

sismember 判断元素是否在集合中

# 判断元素是否在集合中, 返回1为在,0为不在
SISMEMBER key member
127.0.0.1:6379>sismember set a 
(integer)  1 
127.0.0.1:6379>sismember set h 
(integer)  0 

sdiff/sinter/sunion 差集/交集/并集运算命令

  • SDIFF - 集合的差集运算 A-B:属于A并且不属于B的元素构成的集合

    SDIFF key [key ...] 
    
    127.0.0.1:6379> sadd setA 1 2 3
    (integer) 3
    127.0.0.1:6379> sadd setB 2 3 4
    (integer) 3
    127.0.0.1:6379> sdiff setA setB
    1) "1"
    127.0.0.1:6379> sdiff setB setA
    1) "4"
    
  • SINTER - 集合的交集运算 A ∩ B:属于A且属于B的元素构成的集合

    SINTER key [key ...]
    
    127.0.0.1:6379> sinter setA setB
    1) "2"
    2) "3"
    
  • SUNION - 集合的并集运算 A ∪ B:属于A或者属于B的元素构成的集合

    SUNION key [key ...]
    
    127.0.0.1:6379> sunion setA setB
    1) "1"
    2) "2"
    3) "3"
    4) "4"
    

其它命令

# 获得集合中元素的个数
SCARD key
# 从集合中随机弹出一个元素
SPOP key

使用场景

  • 需要去重的列表
  • 提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能

有序集合(Sorted Set,zset)

有序集合(Sorted Set,zset)在Set集合类型的基础上,有序集合类型为集合中的每个元素都关联一个分数(score) ,这使得我们不仅可以完成插入、删除和判断元素是否存在在集合中,还能够获得分数最高或最低的前N个元素、获取指定分数范围内的元素等与分数有关
的操作

SortedSet和List的区别

相似点

  • 二者都是有序的,List是按数据插入顺序,SortedSet是根据score自然排序
  • 二者都可以获得某一范围的元素

区别

  • 列表类型是通过链表实现的,获取靠近两端的数据速度极快,而当元素增多后,访问中间数据的速度会变慢
  • 有序集合类型使用散列表实现,所有即使读取位于中间部分的数据也很快
  • 列表中不能简单的调整某个元素的位置,但是有序集合可以(通过更改分数实现)
  • 有序集合要比列表类型更耗内存

命令

zadd/zrem 添加/删除元素

ZADD key score member [score member ...]
ZREM key member [member ...] 
127.0.0.1:6379> zadd scoreboard 80 zhangsan 89 lisi 94 wangwu
(integer) 3
127.0.0.1:6379> zadd scoreboard 97 lisi
(integer) 0
127.0.0.1:6379> zrem scoreboard lisi
(integer) 1

zrange/zrevrange 获取范围元素列表

获得排名在某个范围的元素列表。

  • ZRANGE:按照元素分数从小到大的顺序返回索引从start到stop之间的所有元素(包含两端的元素)
  • ZREVRANGE:按照元素分数从大到小的顺序返回索引从start到stop之间的所有元素(包含两端的元素)
# 如果需要获得元素的分数的可以在命令尾部加上 WITHSCORES 参数
ZRANGE key start stop [WITHSCORES] 
ZREVRANGE key start stop [WITHSCORES]
127.0.0.1:6379> zrange scoreboard 0 2
1) "zhangsan"
2) "wangwu"
3) "lisi“
127.0.0.1:6379> zrevrange scoreboard 0 2
1) "lisi"
2) "wangwu"
3) "zhangsan“

zscore 获取元素的分数

ZSCORE key member
127.0.0.1:6379> zscore scoreboard lisi
"97"

其它命令

# 获得指定分数范围的元素
ZRANGEBYSCORE key min max [WITHSCORES] 
# 增加某个元素的分数
ZINCRBY key increment member
# 获得集合中元素的数量
ZCARD key
# 获得指定分数范围内的元素个数
ZCOUNT key min max
# 按照排名范围删除元素
ZREMRANGEBYRANK key start stop
# 按照分数范围删除元素
ZREMRANGEBYSCORE key min max
# 获取元素的排名 
# - ZRANK:从小到大
# - ZREVRANK:从大到小
ZRANK key member
ZREVRANK key member

使用场景

  • 存放一个有序的并且不重复的集合列表

  • 排行榜相关,取TOP N操作

通用命令

keys 返回满足规则键值

# 返回满足规则的key-value
KEYS pattern
127.0.0.1:6379> keys k*
1) "k1"
2) "k3"
3) "k2"
4) "key"

del 删除

DEL key [key ...] 
127.0.0.1:6379> del k1 k2 k3
(integer) 3

exists 是否存在

EXISTS key [key ...]
127.0.0.1:6379> exists test
(integer) 1
127.0.0.1:6379> exists mytest
(integer) 0

expires 生存时间设置(重要)

Redis在实际的使用过程中,更多的是作为缓存,而缓存的数据一般都是要设置生存时间的,到期后数据自动销毁

# 设置过期时间(单位:秒)
EXPIRES key seconds  
# 设置过期时间(单位:毫秒)
PEXPIRES key milliseconds 
# 查看key剩余的生存时间
TTL key
PTTL key
# 清除生存时间
PERSIST key
127.0.0.1:6379> expire test 5
(integer) 1
127.0.0.1:6379> ttl test
(integer) 2
127.0.0.1:6379> ttl test
(integer) -2
127.0.0.1:6379> get test
(nil)

rename 重命名

RENAME key newkey
127.0.0.1:6379> keys *
1) "counter"
127.0.0.1:6379> rename counter coounter_new
OK
127.0.0.1:6379> keys *
1) "coounter_new"

type 查看数据类型

TYPE key
redis 127.0.0.1:6379> type addr
string
redis 127.0.0.1:6379> type myzset2
zset
redis 127.0.0.1:6379> type mylist
list
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容