一文总结之Redis
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的更多相关文章
- 一文了解:Redis的RDB持久化
一文了解:Redis的RDB持久化 Redis是内存数据库,为了保证数据不在故障后丢失,Redis需要将数据持久化到硬盘上. Redis持久化有两种方式:一种是快照,全量备份.一种是AOF方式,连续增 ...
- 一文彻底理解Redis序列化协议,你也可以编写Redis客户端
前提 最近学习Netty的时候想做一个基于Redis服务协议的编码解码模块,过程中顺便阅读了Redis服务序列化协议RESP,结合自己的理解对文档进行了翻译并且简单实现了RESP基于Java语言的解析 ...
- 一文读懂Redis的四种模式,单机、主从、哨兵、集群
少点代码,多点头发 本文已经被GitHub收录,欢迎大家踊跃star 和 issues. https://github.com/midou-tech/articles 入职第一周,我被坑了 最近刚入职 ...
- 一文搞定Redis五大数据类型及应用场景
本文学习知识点 redis五大数据类型数据类型:string.hash.list.set.sorted_set 五大类型各自的应用场景 @TOC 1. string类型 1-1 string类型数据的 ...
- 一文读懂Redis持久化
Redis 是一个开源( BSD 许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件.它支持的数据类型很丰富,如字符串.链表.集合.以及散列等,并且还支持多种排序功能. 什么叫持久 ...
- 一文搞定 Redis 复制(全会的举个手看看)
阅读本文大概需要 5 分钟. 本文大纲 复制过程 数据间的同步 全量复制 部分复制 心跳 异步复制 总结 一.复制过程 Step 1:从节点执行 slaveof 命令. Step 2:从节点只是保存了 ...
- 一文了解:Redis基础类型
Redis基础类型 Redis特点 开源的,BSD许可高级的key-value存储系统 可以用来存储字符串,哈希结构,链表,集合 安装 windows:https://github.com/micro ...
- 一文了解:Redis事务
Redis事务 事务提供了一种"将多个命令打包,一次性提交并按顺序执行"的机制,提交后在事务执行中不会中断.只有在执行完所有命令后才会继续执行来自其他客户的消息. Redis中的使 ...
- 一文了解:Redis的AOF持久化
Redis的AOF持久化 每当Redis-Server接收到写数据时,就把命令以文本形式追加到AOF文件里,当重启Redis服务时,AOF文件里的命令会被重新执行一次,重新恢复数据.当AOF过大时将重 ...
随机推荐
- 手动搭建openstack的痛苦经历
openstack真的是一个十分痛苦的东西,好在有自动部署工具,虽然有自动部署工具可以方便我们部署使用,但是学习的话,第一次最好手动部署,因为手动部署更能我们了解openstack的工作流程和各组建之 ...
- requests.get()解析
1.requests.get(url, params=None, headers=None, cookies=None, auth=None, timeout=None) Sends a GET re ...
- AutomaticInteger中CAS运用分析
摘要 在接触CAS的时候虽然对它流程了解了但是对其如何解决并发问题还是一直有疑问的,所以在就选择了java中典型线程安全的AtomicInteger类进行了源码的分析. CAS简介 CAS的全称为co ...
- 【转】Linux系统下的ssh使用
Linux系统下的ssh使用(依据个人经验总结) 对于linux运维工作者而言,使用ssh远程远程服务器是再熟悉不过的了!对于ssh的一些严格设置也关系到服务器的安全维护,今天在此,就本人工作中使 ...
- git push失败
不知道弄错了什么上传项目到github上失败 git commit的时候提示 On branch masternothing to commit, working tree clean git pus ...
- Python创建虚拟环境
用于创建和管理虚拟环境的模块称为 venv.venv 通常会安装你可用的最新版本的 Python.如果您的系统上有多个版本的 Python,您可以通过运行 python3 或您想要的任何版本来选择特定 ...
- java事务 深入Java事务的原理与应用
一.什么是JAVA事务 通常的观念认为,事务仅与数据库相关. 事务必须服从ISO/IEC所制定的ACID原则.ACID是原子性(atomicity).一致性(consistency).隔离性 (iso ...
- kali vmtools 不能复制粘贴解决方法(绝对实用)
朋友问起怎么vm kali 2019怎么不能复制了,而且网上的方法大多不适合.我就在这儿记录一笔吧,方便大家. 之前发现最新kali复制粘贴不能用,后来发现一个奇妙的套路,不是共享文件夹.只需要把文件 ...
- 多线程分段下载研究的python实现(一)
我一直对下载文件比较感兴趣.现在我下载文件大部分是用迅雷,但迅雷也有一些不如意的地方,内存占用大,一些不必要的功能太多,不可定制.尤其是最后一点.现在有些下载对useragent,cookie,aut ...
- Final阶段版本控制报告
版本控制代码及文档要求 在coding.net版本控制; 公开项目,教师.专家.其他同学可以不注册源代码.在此公布git地址. 报告beta阶段2周中,项目的版本控制情况,不包括未在coding.ne ...