Redis

标签(空格分隔): 一文总结


目录

学习资料:

《赠送:2015年-某播客Redis3.0新特性、主从复制、集群视频教程》

《赠送:小象学院-Redis从入门到精通》

《Redis 3.0 中文版 - v1.1.epub》

手册

http://www.runoob.com/redis/redis-tutorial.html

http://www.redis.cn/commands.html#

当前学习进度:D:\学习资料\Redis\赠送:小象学院-Redis从入门到精通\第4章:Redis 服务器的配置与管理—完整\第2节:RDB 持久化

目标

常用数据结构的基本命令

分布式部署

使用Redis与第三方工具管理Redis

了解Redis的实现原理

在应用程序中使用Redis

Redis简介

什么是Redis

Redis是基于BSD许可的,开源、高级键值缓存和存储系统
键包括:string,hash,list,set,sorted set,bitmap 和 hyperloglog 可以在这些类型上面运行原子操作,例如,追加字符串,增加哈希中的值,
加入一个元素到列表,计算集合的交集、并集和差集,或者是从有序集合中获取最高排名的元素。 为了满足高性能,Redis 采用内存 (in-memory) 数据集 (dataset)。
根据你的使用场景,你可以通过每隔一段时间转储数据集到磁盘,或者追加每条命令到日志来持久化。
持久化也可以被禁用,如果你只是需要一个功能丰富,网络化的内存缓存。

诞生过程

刚开始出现的时候,是为了解决LLOOGG.com网站的负载问题,MySQL扛不住,于是作者开发了Redis

特性

支持主从异步复制,非常快的非阻塞初次同步、网络断开时自动重连局部重同步。

相比于其他数据库的特色

  • 独特的键值对模型:SQL-表格,Memcached-字符串键值对,MongoDB-JSON文档,Redis虽然也是键值对数据库,但是支持多种类型的值。通过不同类型的值处理不同的问题

  • 内存数据库,读写数据不受I/O影响,速度极快

  • 持久化功能:支持将内存中的数据保存到硬盘中,方便快速备份和恢复

  • 发布与订阅:将消息同时分发给多个客户端,用于构建广播系统

  • 过期键功能:为键设置过期时间,过期后自动删除

  • 事务功能:原子地执行多个操作,并提供乐观锁,保证处理数据时的安全性

  • 脚本功能

  • 复制:为指定的Redis服务器创建一个或多个复制品,用于提升数据安全性,并分担读请求的负载

  • Sentinel:监控Redis服务器的状态,并在服务器发生故障时,自动故障迁移

  • 集群:创建分布式数据库,为每个服务器分别执行一部分写操作和读操作

Redis当前应用情况

  • Twitter使用Redis存储用户时间线
  • StackOverflow使用Redis进行缓存和消息分发
  • Pinterest使用Redis构建关注模型和兴趣图谱
  • Flicker使用Redis构建队列
  • Github使用Redis作为持久化的键值对数据库,并使用Resque来实现消息队列
  • 新浪微博使用Redis来实现计数器、反向索引、排行榜、消息队列、存储客户关系
  • 知乎使用Redis来进行计数、缓存、消息分发和任务调度

安装

从dashboard下载安装Docker镜像

docker pull daocloud.io/library/redis:3.2.9

直接使用Docker的Redis镜像

docker run --name redis -d daocloud.io/library/redis:3.2.9

初期,为了演示方便,直接进入容器进行访问,对于Redis的高级配置,后续详细说明

docker exec -it 1c8a9884a7d2 bash

这个镜像包含EXPOSE 6379 (Redis默认端口),所以可以通过link容器的方式访问Redis

基本使用

  • 登陆
root@1c8a9884a7d2:/# redis-cli
127.0.0.1:6379>

redis-cli是客户端登陆命令,默认登陆本机的6379端口

更多登陆选项参见 redis-cli -h

  • set and get
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> get k1
"v1"

Redis是一个键值对数据库服务器,每当我们调研命令创建一个键的时候。这个键值对都会被存放到Redis的某个数据库里

在设计Redis键的时候,最好遵循以下原则

  • 不要使用太长的键

    占用更大的内存,查找也会变慢
  • 不要使用太短的键

    太短的键不具备可读性
  • 坚持使用一种模式

    例如:obj-type:id,user:1000
  • 最大大小512M

exists判断键存在性、del删除键、type键类型

127.0.0.1:6379> exists k1
(integer) 1
127.0.0.1:6379> del k1
(integer) 1
127.0.0.1:6379> exists k1
(integer) 0
127.0.0.1:6379> type k2
string

expire key的时效性设置

可以为key设置时效,超时后key被删除,好像调用了del命令一样

如下,设置key的时效性为5秒

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> expire k1 5
(integer) 1
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k1
(nil)

检查时效: ttl key

127.0.0.1:6379> expire k1 100
(integer) 1
127.0.0.1:6379> ttl k1
(integer) 98
127.0.0.1:6379> ttl k1
(integer) 97
127.0.0.1:6379> ttl k1
(integer) 94

如果想要用毫秒作为单位的话,pexpire和pttl

可以在set的时候直接指定时效性

set key 100 ex 10,使用ex参数指定时效性

基本数据类型操作

string 字符串

二进制安全 (binary-safe) 的字符串

字符串是Redis最基本的类型,可以存储文字、数字(整型、浮点型)、还可以存储二进制数据

Redis字符串是二进制安全的,就是说一个Redis字符串可以包含任意类型的数据,

如:JPGE图像,序列化对象

字符串最大限制512M

set/get、getset、mset/mget

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> get k1
"v1"

set执行的是赋值操作,如果键已存在,会发生覆盖,哪怕这个键关联的是一个非字符串值

要求键不存在:set k1 v1 nx,当k1作为键存在的时候,set执行失败

要求键存在:set k1 v1 xx,当k1作为键不存在的时候,set执行失败

默认情况下,键存在就覆盖,不存在就创建

getset:给键设置一个新值,同时返回旧值

127.0.0.1:6379> getset k1 kk1
"v1"
127.0.0.1:6379> get k1
"kk1"

mset:同时设置多个键值对

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 k4 v4
OK
127.0.0.1:6379> mget k1 k2 k3 k4
1) "v1"
2) "v2"
3) "v3"
4) "v4"

incr、incrby、decr、decrby原子性增长/下降

127.0.0.1:6379> set counter 1
OK
127.0.0.1:6379> incr counter
(integer) 2
127.0.0.1:6379> incr counter
(integer) 3
127.0.0.1:6379> incr counter
(integer) 4

incr会将获取到的字符串值解析为整数,并+1,把结果赋值给counter

127.0.0.1:6379> get counter
"4"

incrby:按照指定间隔增加

decr-1

decrby:按照指定间隔下降

127.0.0.1:6379> incrby counter 2
(integer) 5
127.0.0.1:6379> incrby counter 2
(integer) 7
127.0.0.1:6379> decr counter
(integer) 6
127.0.0.1:6379> decrby counter 2
(integer) 4
127.0.0.1:6379> decrby counter 2
(integer) 2

这几个命令都具有原子性,就是说即使有多个客户端对同一个key进行操作,也不会造成竞争条件

list 列表

按照插入顺序排序的字符串元素 (element) 的集合 (collection)。链表数据结构实现

Redis的列表仅仅是按照插入顺序排序的字符串列表

列表最大长度2^23-1

访问列表两端非常快,但是访问一个大列表的中间非常慢

适合存储需要快速插入,访问收尾的情形;如果需要快速访问中间部分的集合元素,推荐使用sorted set

lpush/rpush、lrange、rpop 存取、查看

  • 从头部添加元素到列表 lpush
127.0.0.1:6379> lpush list1 1 2 3
(integer) 3
127.0.0.1:6379> lpush list1 4
(integer) 4
  • 从尾部添加元素到列表 rpush
127.0.0.1:6379> rpush list1 5
(integer) 5
  • 查看集合中的元素 lrange

    索引从0开始,-1表示最后一个元素,-2表示倒数第二个元素

    所以[0,-1]就是全部元素的索引
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
5) "5"
  • 取出最后一个元素 rpop
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
5) "5"
127.0.0.1:6379> rpop list1
"5"
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "3"
3) "2"
4) "1"

ltrim 列表上限限定

限制列表中保存的元素数目,将的元素剔除出列表

127.0.0.1:6379> lrange list1 0 -1
1) "7"
2) "6"
3) "5"
4) "4"
5) "3"
6) "2"
7) "1"
8) "4"
9) "3"
10) "2"
11) "1"
127.0.0.1:6379> ltrim list1 0 4
OK
127.0.0.1:6379> lrange list1 0 -1
1) "7"
2) "6"
3) "5"
4) "4"
5) "3"

brpop、blpop 列表的阻塞操作

当列表为空的时候,rpop操作返回null

brpop和blpop,会让列表为空的时候进入阻塞状态,仅当新元素添加到列表的时候,或者超时了才返回

127.0.0.1:6379> brpop list1 20
(nil)
(20.08s)

如果在brpop空的列表的过程中,往列表中lpush了新数据,且未超时,则blpop会返回这个新增加的元素

rpop不同,blpop返回的是数组,其中包括键(列表)的名字,因为可以阻塞等待多个列表的数据

list的典型应用场景

  • 最近提交(rpop获取)
  • 生产者消费者之间通讯

    生产者lpush,消费者rpop

set 集合

唯一的,无序的字符串元素集合

Redis集合是没有顺序的字符串集合

不允许重复数据

集合与列表的一个区别在于,集合可以计算集合之间的关系

sadd、smembers、sismember、smember

127.0.0.1:6379> sadd myset 1 2 3
(integer) 3
127.0.0.1:6379> smembers myset
1) "1"
2) "2"
3) "3"

sismember:检查元素是否存在

127.0.0.1:6379> sismember myset 3
(integer) 1
127.0.0.1:6379> sismember myset 30
(integer) 0

smember 返回一个随机元素

127.0.0.1:6379> srandmember myset
"2"

sinter/交集、spop/随机返回并删除、sunionstore/交集并赋值

sinter

127.0.0.1:6379> sadd tag:1:news 1000
(integer) 1
127.0.0.1:6379> sadd tag:2:news 1000
(integer) 1
127.0.0.1:6379> sadd tag:5:news 1000
(integer) 1
127.0.0.1:6379> sadd tag:77:news 1000
(integer) 1
127.0.0.1:6379> sinter tag:1:news tag:2:news tag:10:news tag:27:news
(empty list or set)
127.0.0.1:6379> sinter tag:1:news tag:2:news tag:77:news
1) "1000"

spop

127.0.0.1:6379> spop news:1000:tags
"2"
127.0.0.1:6379> spop news:1000:tags
"77"
127.0.0.1:6379> spop news:1000:tags
"1"
127.0.0.1:6379> spop news:1000:tags
"5"
127.0.0.1:6379> spop news:1000:tags
(nil)

sunionstore取交集,并赋值给新的集合,单个集合的交易就是其本身,所以这个命令也有集合复制的功能

127.0.0.1:6379> sunionstore myset1(dest) myset
(integer) 1

scard 集合中元素数目

127.0.0.1:6379> scard myset
(integer) 1

sorted set 有序集合

和集合类似,但是每个字符串元素关联了一个称为分数 (score) 的浮点数。元素总是按照分数排序,所以可以检索一个范围的元素 (例如,给我前 10,或者后 10 个元素)

与Redis的set类似,但是每个元素都对应一个分数

按照分数高低排序

元素是唯一的,但是分数是可以重复的

zadd、zrang、zrevrange

zadd 有序集合名 分数 集合元素

127.0.0.1:6379> zadd hacker 1 v1
(integer) 1
127.0.0.1:6379> zadd hacker 2 v2
(integer) 1
127.0.0.1:6379> zrange hacker 0 -1
1) "v1"
2) "v2"

倒序

127.0.0.1:6379> zrevrange  hacker 0 -1
1) "v2"
2) "v1"

连带分数一起返回

127.0.0.1:6379> zrange hacker 0 -1 withscores
1) "v1"
2) "1"
3) "v2"
4) "2"

zrangebyscore/获取指定分数、zremrangebyscore/删除指定分数

小于指定分数的元素

127.0.0.1:6379> zrangebyscore hacker -inf 2
1) "v1"
2) "v2"
127.0.0.1:6379> zrangebyscore hacker -inf 1
1) "v1"

删除指定分数范围的元素

127.0.0.1:6379> zremrangebyscore hacker 1 2
(integer) 2
127.0.0.1:6379> zrange hacker 0 -1
(empty list or set)

zrank 获取元素位置

从0开始计数

127.0.0.1:6379> zadd hacker 1 v1
(integer) 1
127.0.0.1:6379> zadd hacker 2 v2
(integer) 1
127.0.0.1:6379> zadd hacker 3 v3
(integer) 1
127.0.0.1:6379> zrank hacker 2
(nil)
127.0.0.1:6379> zrank hacker v2
(integer) 1
127.0.0.1:6379> zrank hacker v3
(integer) 2
127.0.0.1:6379> zrank hacker v1
(integer) 0

hash 散列

由字段 (field) 及其关联的值组成的映射。字段和值都是字符串类型。这非常类似于 Ruby 或 Python 中的哈希 / 散列

Redis哈希字符串字段与字符串之间的映射

哈希主要用来存储对象

hmset、hget、hgetall、hmget

127.0.0.1:6379> hmset user:1000 username antirez birthyear 1977 verified 1
OK
127.0.0.1:6379> hget user:1000 username
"antirez"
127.0.0.1:6379> hget user:1000 birthyear
"1977"
127.0.0.1:6379> hgetall user:1000
1) "username"
2) "antirez"
3) "birthyear"
4) "1977"
5) "verified"
6) "1"

hmget用于返回数组

127.0.0.1:6379> hmget user:1000 username birthyear
1) "antirez"
2) "1977"

hincrby 增加单个字段值

127.0.0.1:6379> hincrby user:1000 birthyear 10
(integer) 1987
127.0.0.1:6379> hincrby user:1000 birthyear 10
(integer) 1997
127.0.0.1:6379> hmget user:1000 birthyear
1) "1997"

bitmaps 位图

**使用特殊的命令,把字符串当做位数组来处理:你可以设置或者清除单个位值,统计全部置位为 1 的位个数,寻找第一个复位或者置位的位,等等 **

hyperloglogs 超重对数

使用常量空间估算大量元素的积数

这是一个用于估算集合的基数 (cardinality,也称势) 的概率性数据结构

问题:怎样记录网站每天获得的独立IP数量

第一种:用集合(set)数据结构实现,每次访问都将ip记录set数据结构,set数据结构中的每个数据都是不想同的,再调用scard命令统计集合中的元素数据即可

在设计key的时候,要注意和“每天”关联上

第一种方案的问题:随着时间的增加,消耗的内存越来越大,如果存储的是IPv6的地址,消耗更大

HyperLogLogs可以接收多个元素作为输入,并给出元素的积数估算值

基数:集合中不同元素的数量

估算值:算法给出的基数并不精确,但会控制在合理范围之内

HyperLogLogs的优点是,即使输入元素的数量或体积非常非常大,计算基数所需的空间总是固定的,并且非常小

在Redis中,每个HyperLogLogs键只需要花费12KB内存,就可以计算接近2^64个不同元素的基数

但是,HyperLogLogs只会根据输入的元素来计算基数,而不会存储元素本身,所以无法返回各个元素

sort排序

在Redis中,只有列表和有序集合是有顺序的

通过sort命令,可以对列表、集合以及有序集合,按照新的排序方式,进行重新排序

小结

对于此部分的内容,基本上集中在各种数据类型的set和get上,以及根据值类型的特点,进行相关的运算操作

这部分也是在Redis安装配置完成后,最被常用的使用功能

由于命令众多,实际使用过程中最好先看看手册,对于我们需要的数据类型提供了哪些实用的功能

Redis手册

发布与订阅

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。

  • 创建频道 redisChat

    SUBSCRIBE redisChat
  • 重新打开一个客户端,往 redisChat 频道发送消息

    PUBLISH redisChat "Redis is a great caching technique"
  • 此时,第一个客户端,就是创建频道的那个客户端,就会收到消息

事务

它先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令:

redis 127.0.0.1:6379> MULTI
OK redis 127.0.0.1:6379> SET book-name "Mastering C++ in 21 days"
QUEUED redis 127.0.0.1:6379> GET book-name
QUEUED redis 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series"
QUEUED redis 127.0.0.1:6379> SMEMBERS tag
QUEUED redis 127.0.0.1:6379> EXEC
1) OK
2) "Mastering C++ in 21 days"
3) (integer) 3
4) 1) "Mastering Series"
2) "C++"
3) "Programming"

Lua脚本

Redis 脚本使用 Lua 解释器来执行脚本。 Reids 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常用命令为 EVAL。

Redis构建实例

微博

主要功能

  • 用户账号
  • 用户关系(关注与被关注)
  • 发微博
  • 查看微博时间线
  • 对微博点赞、评论、转发

创建账号

注册微博所需信息

  • 邮箱(不考虑手机号)
  • 密码
  • 微博名

其中,邮箱和微博名不能重复

所以,需要检查邮箱和微博名是否已被使用,检查通过的用户,注册信息需要存储起来,并且系统分配一个唯一ID

邮箱和微博名检查

所有注册过的邮箱和微博名,都存储在weibo::userd_names,和weibo::used_emails两个集合中

将需要注册的微博信息与这两个集合进行比较,看看是否是集合中的成员,

如果两者都不是集合中的成员,则校验通过,然后将信息存储到集合中。

存储用户注册信息

用Hash数据机构存储用户注册信息

HMSET weibo::user:id field1 "Hello" field2 "World"

至于id的生成,可以使用 incr key,并且处理成YYYYMMDD-ID的形式

关联email与ID的关系

使用Hash数据结构存储

HSET weibo::email_to_uid email uid

这样,当用户登录的时候,我们拿着输入的email,从 weibo::email_to_uid 散列中获取uid

127.0.0.1:6379> hmset weibo::email_to_uid nbzlnzlq@126.com 10000
OK
127.0.0.1:6379> hmget weibo::email_to_uid nbzlnzlq@126.com
1) "10000"

然后用获取到的id,去 weibo::user:id 中获取用户的注册信息,比较一下输入密码与注册密码是否一致

当然,实际情况,存储的密码都是加密过的,不会是明文

用户关系

关注集合

存储用户关注的人的id

键 weibo::user:

一文总结之Redis的更多相关文章

  1. 一文了解:Redis的RDB持久化

    一文了解:Redis的RDB持久化 Redis是内存数据库,为了保证数据不在故障后丢失,Redis需要将数据持久化到硬盘上. Redis持久化有两种方式:一种是快照,全量备份.一种是AOF方式,连续增 ...

  2. 一文彻底理解Redis序列化协议,你也可以编写Redis客户端

    前提 最近学习Netty的时候想做一个基于Redis服务协议的编码解码模块,过程中顺便阅读了Redis服务序列化协议RESP,结合自己的理解对文档进行了翻译并且简单实现了RESP基于Java语言的解析 ...

  3. 一文读懂Redis的四种模式,单机、主从、哨兵、集群

    少点代码,多点头发 本文已经被GitHub收录,欢迎大家踊跃star 和 issues. https://github.com/midou-tech/articles 入职第一周,我被坑了 最近刚入职 ...

  4. 一文搞定Redis五大数据类型及应用场景

    本文学习知识点 redis五大数据类型数据类型:string.hash.list.set.sorted_set 五大类型各自的应用场景 @TOC 1. string类型 1-1 string类型数据的 ...

  5. 一文读懂Redis持久化

    Redis 是一个开源( BSD 许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件.它支持的数据类型很丰富,如字符串.链表.集合.以及散列等,并且还支持多种排序功能. 什么叫持久 ...

  6. 一文搞定 Redis 复制(全会的举个手看看)

    阅读本文大概需要 5 分钟. 本文大纲 复制过程 数据间的同步 全量复制 部分复制 心跳 异步复制 总结 一.复制过程 Step 1:从节点执行 slaveof 命令. Step 2:从节点只是保存了 ...

  7. 一文了解:Redis基础类型

    Redis基础类型 Redis特点 开源的,BSD许可高级的key-value存储系统 可以用来存储字符串,哈希结构,链表,集合 安装 windows:https://github.com/micro ...

  8. 一文了解:Redis事务

    Redis事务 事务提供了一种"将多个命令打包,一次性提交并按顺序执行"的机制,提交后在事务执行中不会中断.只有在执行完所有命令后才会继续执行来自其他客户的消息. Redis中的使 ...

  9. 一文了解:Redis的AOF持久化

    Redis的AOF持久化 每当Redis-Server接收到写数据时,就把命令以文本形式追加到AOF文件里,当重启Redis服务时,AOF文件里的命令会被重新执行一次,重新恢复数据.当AOF过大时将重 ...

随机推荐

  1. Eclipse中Applet程序运行时Applet小程序大小的设置

       最近在跟斯坦福的CS106A,里面的java代码都是Applet程序,而我运行程序的时候发现,Applet小程序窗口大小总是固定的,但是我画的图却越来越大,所以怎么在Eclipse中run的时候 ...

  2. UWP 记一次WTS 和 UCT翻车经历

    这次翻车,真的,在网上绝对找不到回答的. 只有在WTS的Issues讨论中才找到,哈哈 不过这个应该比较少遇到吧,据我所知,提出Issue那个大胸弟和我都遇到了... 翻车具备的条件如下: 1. 使用 ...

  3. hdu1232畅通工程(并查集,简单题)

    传送门 最少好要修多少条路太能使全部城镇连通.只要用并查集算可以连通的城市的组数,修的路就是组数减1 #include<bits/stdc++.h> using namespace std ...

  4. 设置JFrame背景图片

    这里我就放上改写的代码吧,不做多的解释,推荐一个好的博文 https://blog.csdn.net/jdsjlzx/article/details/16831815 public void ini_ ...

  5. jenkins 多任务串行执行

    摘要 今天在新创建自动化部署项目的时候遇到了一个问题:我们的项目是maven聚合的所以在构建maven项目的时候要从parent开始build,但是这样会造成一个问题,我每次添加此parent项目下的 ...

  6. Android Service(下)

    阅读本文需要先阅读Android Service(上) 一 为什么需要bindService() 绑定服务就是为了和服务进行通讯 可以调用服务里面的方法 二 bindService()调用服务里面方法 ...

  7. Memached、Redis、Mongodb的区别

    性能 ​ • 性能都很高,redis和memached差不多 > Mongodb 操作 ​ • Memached:数据结构单一,只有key/value数据结构 ​ • Redis有五种数据类型 ...

  8. python图像处理(2)图像水印和PIL模式转化

    模式转化: PIL模式转化:将图片转化成其他模式 # 我们将image图像转化为灰度图像(python) from PIL import Image img = Image.open('c:\\1.J ...

  9. phpcmsv9广告版位调用方法

    <div class="ya"> <?php // pc:get 使用sql语句获取指定条件的广告版位! ?> {pc:get sql="SELE ...

  10. JSBridge实现示例

    前言 参考来源 前人栽树,后台乘凉,本文参考了以下来源 Hybrid APP架构设计思路 marcuswestin/WebViewJavascriptBridge 楔子 本文介绍JSBridge的完整 ...