Redis介绍
Redis 是一个开源的,使用C语言编写的,支持网络交互的、可基于内存也可持久化的Key-Value数据库存储系统。
Redis特点
- Redis 提供了多种数据类型,比如:字符串(strings),散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets)等;
- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中;
- Redis数据读写速度非常快,因为它把数据都读取到内存当中操作;
- Redis支持数据的备份,即master-slave模式的数据备份;
- Redis还支持事务 、持久化、LUA脚本、多种集群方案等。
Redis应用场景
- Redis用作缓存,由于内存的操作,可以减少数据库频繁访问读取的压力。
- Redis分布式锁,分布式锁的方案很多,基于Redis实现的分布式锁一般用得最多。
- Redis用于计数器 ,基于incr原理每次访问不断累加,可以统计网站访问量,阅读量,点击量等。
- Redis用于分布式限流 ,基于incr和expire原理 通过累计单位时间请求次数达到限流。
- Redis还可以用于发布订阅,类似若消息队列。
- 除此之外可以用于排行、购物车等。
Redis安装
Redis window下载地址,点击前往
选择如下图的版本:
2.Redis安装
下载Redis-x64-5.0.14.1.zip 文件,然后 把Redis-x64-5.0.14.1.zip文件解压。
解压后如下图所示:
3.Redis启动
双击 redis-server.exe 启动 Redis,如下图所示:
启动后,如下图所示:
如果想方便的话,可以把 redis 的路径加到系统的环境变量里,这样就省得再输路径了
4.连接Redis
直接双击解压之后文件中的redis-cli.exe,如下图所示:
5.测试Redis
输入ping命令,如下图所示:
能够正确响应pong,则说明redis启动成功了。
Redis可视化工具
RedisDesktopManager 是一个快速、简单、支持跨平台的 Redis 桌面管理工具,基于 Qt 5 开发,支持通过 SSH Tunnel 连接,也被称作 Redis 可视化工具。
RedisDesktopManager特点:
- 适用于 Mac OS、Windows 和 Linux 的 GUI 应用程序
- 适用于大数据量,你在 redis 中有超过一百万个 key 吗?RDM 管理不成问题
- 直接或通过 SSH 隧道连接到 Redis
- 可与 Amazon ElastiCache、Microsoft Azure Redis Cache 和 Redis Labs 配合使用
RedisDesktopManager快速预览
有很多个数据库,插入数据如果不指定数据库的话,默认使用db0
Redis配置
1.绑定的主机地址
bind 127.0.0.1
2.redis监听的端口号
port 6379
3.设置客户端空闲时间
此参数为设置客户端空闲超过timeout,服务端会断开连接,为0则服务端不会主动断开连接,不能小于0。
timeout 300
4.指定日志记录级别
Redis总共支持四个级别:debug、verbose、notice、warning,默认为 verbose。
debug:很多信息,方便开发、测试;
verbose:许多有用的信息, 但是没有debug级别信息多;
notice:适当的日志级别,适合生产环境;
warn:只有非常重要的信息;
比如:
loglevel notice
5.设置数据库的数量
databases 16
默认使用的数据库是0,可以通过 SELECT 【数据库序号】选择一个数据库。
6.是否在后台执行
daemonize yes
yes后台运行,no不是后台运行。
7.指定Redis记录日志文件
logfile /usr/local/redis/var/redis.log
8.设置同一时间最大客户端连接数
maxclients 128
9.指定 Redis 最大内存限制
maxmemory <bytes>
10.指定是否在每次更新操作后进行日志记录
//默认为0 appendonly no
11.指定更新日志文件名
appendfilename appendonly.aof
默认为 appendonly.aof。
12.指定存储至本地数据库时是否压缩数据
//默认为yes rdbcompression yes
Redis 采用 LZF 压缩,如果为了节省 CPU 时间,可以关闭该选项,但会导致数据库文件变的巨大。
13. 指定本地数据库文件名
dbfilename dump.rdb
默认为dump.rdb。
14.设置当本机为 slave 服务
slaveof <masterip> <masterport>
设置 master 服务的 IP 地址及端口,在 Redis 启动时,它会自动从 master 进行数据同步。
15.指定更新日志条件
指定更新日志条件,共有 3 个可选值:
- no:表示等操作系统进行数据缓存同步到磁盘(快);
- always:表示每次更新操作后手动调用 fsync() 将数据写到磁盘(慢,安全);
- everysec:表示每秒同步一次(折衷,默认值);
比如:
appendfsync everysec
16.Redis设置密码
1)通过命令设置密码
config set requirepass 123456
执行完毕无需重启,退出客户端,重新登录就需要输入密码了,这种方式临时有效,重启服务器后密码失效。
2)通过配置设置密码
如果配置了连接密码,客户端在连接 Redis 时需要通过 AUTH <password>命令提供密码,默认关闭。
# The requirepass is not compatable with aclfile option and the ACL LOAD # command, these will cause requirepass to be ignored. # # requirepass foobared
注释打开,设置密码,如下所示:
# The requirepass is not compatable with aclfile option and the ACL LOAD # command, these will cause requirepass to be ignored. # requirepass 123456
这种方式永久生效。
Redis数据类型
Redis支持多种类型的数据结构,最常用的5大数据类型,如下图所示:
1.Redis String数据类型
Sring是Redis最基本的数据类型,二进制安全的字符串,最大512M,可以包含任何数据,比如:字符串、整数、浮点数、图片、Json对象等。
String类型的数据结构是Key-Value(键:值),Key 是数据在Redis中的唯一标识,Value则是其具体的数据。
Redis String常用命令
命令名称 |
示例 |
描述 |
set |
set key value |
设置键值对 |
get |
get key |
获取值 |
incr |
incr key |
递增值 |
decr |
decr key |
递减值 |
strlen |
strlen key |
获取字符串长度 |
incrby |
incrby key increment |
增加指定数字 |
String应用场景
1)计数器
因为 Redis 处理命令是单线程,所以执行命令的过程是原子的,因此 String 数据类型适合计数场景,比如:计算访问次数、点赞、转发、库存数量等等;
2)共享session
分布式Session可以很方便的共享存储session。
3)分布式锁
SET 命令有个 NX 参数可以实现「key不存在才插入」,可以用它来实现分布式锁;
2.Redis List数据类型
List列表可以存储有序并且可以重复的元素,按照插入顺序排序,可以从头部或尾部向 List 列表添加元素。
List获取头部或尾部附近的记录是极快的,list的元素个数最多为2^32-1个(40亿)。
redis list常用指令:
常用命令 |
命令 |
左压栈 |
lpush key v1 v2 v3 v4… |
右压栈 |
rpush key v1 v2 … |
查看里面的元素 |
lrange key start offset |
左弹栈 |
lpop key |
右弹栈 |
rpop key |
按照索引查找 |
lindex key index |
查看长度 |
llen key |
删除几个几 |
lrem key 数量 value |
指定开始和结束的位置截取,再赋值给key |
ltrim key start offset |
右出栈左压栈,把resoure的左后一个,压倒dest的第一个 |
rpoplpush resource destination |
重置指定索引的值 |
lset key index value |
在指定元素前/后插入指定元素 |
linsert key before/after 值1 值2 |
Redis List应用场景
- 用户列表,商品列表,评论列表等;
- 消息队列;
- 栈;
3.Redis Set数据类型
Redis Set是无序的字符串集合,不存在重复的元素。
Redis Set常用命令
常用命令 |
命令 |
添加值 |
sadd key values |
查看值 |
smembers key |
检查集合是否有值 |
sismember key value |
查看set集合里面的元素个数 |
scard key |
删除集合中的指定元素 |
srem key value |
随机弹出某个元素 |
srandmember key |
随机出栈 |
spop key |
把key1中的某个值赋值给key2 |
smove SourceSet destSet membe |
Redis Set应用场景
Set 类型比较适合用来数据去重和保障数据的唯一性,还可以用来统计多个集合的交集、错集和并集等,当我们存储的数据是无序并且需要去重的情况下,比较适合使用集合类型进行存储。
比如:
- 统计网站uv;
- 统计共同好友;
4.Redis Sorted Set数据类型
sorted set也叫zset是一个有序集合,元素本身跟set一样,是不重复的。
Sorted Set常用命令
命令 |
帮助 |
描述 |
zadd |
zadd key score1 v1 score2 v2 score1v3 … scoren vn |
为有序集合添加新成员 |
zrem |
zrem key mem1 mem2 …memn |
删除有序集合中指定成员 |
zcard |
zcard key |
获得有序集合中的元素数量 |
zcount |
zcount key min max |
返回集合中score值在[min,max]区间的元素数量 |
zincrby |
zincrby key increment member |
在集合的member分值上加increment |
zscore |
zscore key member |
获得集合中member的分值 |
zrank |
zrank key member |
获得集合中member的排名(按分值从小到大) |
zrevrank |
zrevrank key member |
获得集合中member的排名(按分值从大到小) |
zrange |
zrange key start end |
获得集合中指定区间成员,按分数递增排序 |
zrevrange |
zrevrange key start end |
获得集合中指定区间成员,按分数递减排序 |
Sorted Set应用场景
有序列表被广泛使用在各种排行榜业务上:比如销量排行,用户点击率排行等
5.Redis Hash数据类型
Redis Hash是key-value对的一种集合,Hash 特别适合用于存储对象。
Redis Hash常用命令
作用 |
命令 |
添加单个 |
hset key field value |
获取单个 |
hget key field |
一次性添加多个键值 |
hmset key field1 value1 field2 value2 … |
一次性获取多个 |
hmget |
获取所有键值 |
hgetall key |
删除 |
hdel |
获取键值对的个数 |
hlen |
检查是否包含某个字段 |
hget key field |
查看所有key |
hkeys |
给某个数值类型(否则报错)的值增加指定整数值 |
hincrby key field increment |
给某个数字类型值,增加指定浮点类型值 |
hincrbyfloat key field increment |
如果不存在则添加 |
hsetnx |
Redis Hash应用场景
比如最典型的就是购物车,以用户 id 为 key,商品 id 为 field,商品数量为 value,恰好构成了购物车的3个要素,如下图所示:
涉及的命令如下:
- 添加商品:HSET cart:{用户id} {商品id} 1
- 添加数量:HINCRBY cart:{用户id} {商品id} 1
- 商品总数:HLEN cart:{用户id}
- 删除商品:HDEL cart:{用户id} {商品id}
- 获取购物车所有商品:HGETALL cart:{用户id}
当前仅仅是将商品ID存储到了Redis 中,在回显商品具体信息的时候,还需要拿着商品 id 查询一次数据库,获取完整的商品的信息。
Redis持久化
Redis的持久化机制有3种:
1.RDB(Redis Data Base) 内存快照
RDB 快照是一次全量备份,RDB快照是内存数据的二进制序列化形式,在存储上非常紧凑。
2.AOF(Append Only File) 增量日志
AOF 则是将每次执行的写命令保存到硬盘,类似于 MySQL 的 Binlog,AOF 持久化的实时性更好,即当进程意外退出时丢失的数据更少。
3.RDB AOF混合持久化
Redis4.0 后大部分的使用场景都不会单独使用 RDB 或者 AOF 来做持久化机制,而是兼顾二者的优势混合使用。
下面针对以上3种Redis持久化机制分别详解。
Redis事务
Redis事务有如下三大特性:
1.单独的隔离操作
事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
2.没有隔离级别的概念
队列中的命令没有提交之前不会被实际执行,因为事务提交前任何指令都不会被实际执行。
3.不保证原子性
事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚。
Redis提供了以下5个基本指令实现事务功能,如下图所示:
Redis Lua脚本
Redis 从 2.6 版本开始支持 Lua 脚本,客户端通过 Lua 脚本,可以将多个 Redis 命令组合成一个原子性操作在服务器上执行。
Lua脚本是一种由C编写的可嵌入的轻量级语言, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。
典型的Redis分布式锁就会涉及到Lua脚本,以下就是Redisson中RedissonLock加/解锁使用lua的示例。
1.加锁Lua脚本
// 先执行exists key1命令,判断KEYS[1]是否存在 if (redis.call('exists', KEYS[1]) == 0) then // 不存在,执行hincrby key1 field命令,将ARGV[2]的值原子加1 // 并设置KEYS[1]的过期时间为ARGV[1] // 返回nil redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; // 执行hexists key field命令,判断ARGV[2]是否存在 if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then // 存在,与上面then逻辑一致 redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; // 若key存在且key field也存在,执行pttl key命令,返回KEYS[1]的过期时间 return redis.call('pttl', KEYS[1]);
2.解锁Lua脚本
// 执行hexists key1 field命令,判断判断ARGV[3]是否存在 if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then // 不存在,返回nil return nil; end; // 执行hincrby key1 field命令,获取结果 local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); if (counter > 0) then // counter大于0,执行pexpire key1 命令,设置key过期时间为ARGV[2] redis.call('pexpire', KEYS[1], ARGV[2]); return 0; else // 否则,执行del key命令,删除KEYS[1] // 执行publish channel message命令,向KEYS[2]发送消息ARGV[1] redis.call('del', KEYS[1]); redis.call('publish', KEYS[2], ARGV[1]); return 1; end; return nil;
从这两段脚本可以看出Redis集成lua脚本的强大之处,Lua脚本可谓是Redis能力倍增器。
Redis主从模式
主从模式是Redis集群模式中最简单的,主从模式指的是使用一个Redis实例作为主机,其余的实例作为备份机,主机和从机的数据完全一致。
如下图所示:
主机支持数据的写入和读取等各项操作,而从机则只支持与主机数据的同步和读取,也就是说客户端可以将数据写入到主机,由主机自动将数据的写入操作同步到从机。
Redis主从复制工作原理
- 当slave启动后主动向master发送SYNC命令;
- master接收到SYNC命令后在后台保存快照和缓存保存快照这段时间的命令,然后将保存的快照文件和缓存的命令发送给slave;
- slave接收到快照文件和命令后加载快照文件和缓存的执行命令;
- 复制初始化后,master每次接收到的写命令都会同步发送给slave,保证主从数据一致性。
Redis哨兵模式
为什么需要哨兵模式?
刚刚上面讲到了主从模式当主服务器宕机后,需要手动把一台从服务器切换为主服务器,需要人工干预费事费力,为了解决这个问题出现了哨兵模式。
如下图所示:
哨兵模式由一个或多个Sentinel实例组成的Sentinel系统,它可以监视所有的Master节点和Slave节点,并在被监视的Master节点进入下线状态时,自动将下线Master服务器。
哨兵模式工作原理
当主节点出现故障时,由Redis Sentinel自动完成故障发现和转移,并通知应用方,实现高可用性。
如下图所示:
- 哨兵机制建立了多个哨兵节点(进程),共同监控数据节点的运行状况。
- 同时哨兵节点之间也互相通信,交换对主从节点的监控状况。
- 每隔1秒每个哨兵会向整个集群:Master主服务器+Slave从服务器+其他Sentinel(哨兵)进程,发送一次ping命令做一次心跳检测。
Redis集群模式
为什么需要Redis集群模式
哨兵模式基于主从模式,实现读写分离,它还可以自动切换,系统可用性更高。但是它每个节点存储的数据是一样的,浪费内存,因此在Redis3.0后Cluster集群应运而生。
Redis Cluster是一种服务器Sharding技术(分片和路由都是在服务端实现),采用多主多从,每一个分区都是由一个Redis主机和多个从机组成,片区和片区之间是相互平行的。
Redis集群模式原理
在Redis的每一个节点上,都有这么两个东西,一个是插槽(slot),它的的取值范围是:0-16383,还有一个就是cluster。
如下图所示:
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》