Redis部署及使用
目录一、Redis概述二、Redis 安装(一)三、Redis安装部署(二)3.1、Redis下载、编译、安装3.2、启动Redis3.3、日志文件及持久化文件配置3.4、Redis客户端使用四、Redis持久化4.1、AOF持久化配置4.2、RDB持久化配置五、常用操作的命令六、Redis在项目中的使用场景七、常见问题解决——缓存穿透、缓存击穿...
目录
一、Redis概述
1、Redis是一个开源,先进的key-value存储,并用于构建高性能,可扩展的应用程序的完美解决方案。
2、Redis从它的许多竞争继承来的三个主要特点:
- 1)Redis数据库完全在内存中,使用磁盘仅用于持久性。
- 2)相比许多键值数据存储,Redis拥有一套较为丰富的数据类型。String,List, map, set, sortSet(5种)
- 3)Redis可以将数据复制到任意数量的从服务器。
优势:
- 异常快速:Redis的速度非常快,每秒能执行约11万集合,每秒约81000+条记录。
- 支持丰富的数据类型:Redis支持字符串、列表、集合、有序集合、散列数据类型,这使得它非常容易解决各种各样的问题。
- 操作都是原子性:所有Redis操作是原子的,这保证了如果两个客户端同时访问的Redis服务器将获得更新后的值。----计数器
- 多功能实用工具:Redis是一个多实用的工具,可以在多个用例如缓存,消息,队列使用(Redis原生支持发布/订阅),任何短暂的数据,应用程序,如Web应用程序会话,网页命中计数等。
二、Redis 安装(一)
1.解压缩redis-2.8.3.tar.gz
2.make
3.make install
4.启动服务redis-server redis.conf
5.测试服务安装,运行客户端:redis-cli
6.主从配置
修改从服务器的redis.conf,添加slaveof 192.168.137.18 6379
运行过程中,通过redis-cli中命令可以动态不停机切换主从
主:slaveof no one
从:slaveof 192.168.137.19 6379
7.配置从的持久化aof方式:
关闭自动snapshot:
#save 900 1
#save 300 10
#save 60 10000
开启snapshot:
appendonly yes
此处可以动态在redis-cli中不停机运行命令:CONFIG SET APPENDONLY YES
三、Redis安装部署(二)
3.1、Redis下载、编译、安装
下载redis3.0.5
wget http://download.redis.io/releases/redis-3.0.5.tar.gz
解压文件,并创建软件连接
tar -zxvf redis-3.0.5.tar.gz -C /export/servers/
ln –s redis-3.0.5/ redis
编译redis源码
cd /export/servers/redis
make(先安装gcc)
将编译后的可执行文件安装到/user/local/redis
make PREFIX=/usr/local/redis install
3.2、启动Redis
启动方式一:Redis前台默认启动
进入redis安装目录,并启动Redis服务
cd /usr/local/redis/bin/
./redis-server
启动方式二:Redis使用配置文件启动
拷贝源码中的redis.conf文件到redis的安装目录
cp /export/servers/redis/redis.conf /usr/local/redis/
修改redis.conf的属性
daemonize no è daemonize yes
启动redis服务
cd /usr/local/redis
bin/redis-server ./redis.conf
3.3、日志文件及持久化文件配置
修改生成默认日志文件位置
logfile "/usr/local/redis/logs/redis.log"
配置持久化文件存放位置
dir /usr/local/redis/data/redisData
3.4、Redis客户端使用
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
四、Redis持久化
有两种持久化方案:RDB和AOF
1) RDB方式按照一定的时间间隔对数据集创建基于时间点的快照。
2) AOF方式记录Server收到的写操作到日志文件,在Server重启时通过回放这些写操作来重建数据集。该方式类似于MySQL中基于语句格式的binlog。当日志变大时Redis可在后台重写日志。
4.1、AOF持久化配置
1)修改redis.config配置文件,找到appendonly。默认是appendonly no。改成appendonly yes
2)再找到appendfsync 。默认是 appendfsync everysec
appendfsync always
#每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
appendfsync everysec
#每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐
appendfsync no
#完全依赖os,性能最好,持久化没保证
4.2、RDB持久化配置
默认情况下,Redis保存数据集快照到磁盘,名为dump.rdb的二进制文件。可以设置让Redis在N秒内至少有M次数据集改动时保存数据集,或者你也可以手动调用SAVE或者BGSAVE命令。
例如,这个配置会让Redis在每个60秒内至少有1000次键改动时自动转储数据集到磁盘
save 60 1000
- 常用命令
连接操作相关的命令
- quit:关闭连接(connection)
- auth:简单密码认证
持久化
- save:将数据同步保存到磁盘
- bgsave:将数据异步保存到磁盘
- lastsave:返回上次成功将数据保存到磁盘的Unix时戳
- shundown:将数据同步保存到磁盘,然后关闭服务
远程服务控制
- info:提供服务器的信息和统计
- monitor:实时转储收到的请求
- slaveof:改变复制策略设置
- config:在运行时配置Redis服务器
五、常用操作的命令
对value操作的命令
- exists(key):确认一个key是否存在
- del(key):删除一个key
- type(key):返回值的类型
- keys(pattern):返回满足给定pattern的所有key
- randomkey:随机返回key空间的一个
- keyrename(oldname, newname):重命名key
- dbsize:返回当前数据库中key的数目
- expire:设定一个key的活动时间(s)
- ttl:获得一个key的活动时间(Time To Live)
- select(index):按索引查询
- move(key, dbindex):移动当前数据库中的key到dbindex数据库
- flushdb:删除当前选择数据库中的所有key
- flushall:删除所有数据库中的所有key
对String操作的命令
- set(key, value):给数据库中名称为key的string赋予值value
- get(key):返回数据库中名称为key的string的value
- getset(key, value):返回旧值,设置新值,旧值没有返回nil
- mget(key1, key2,…, key N):返回库中多个string的value
- setnx(key, value):[SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果
- setex(key, time, value):向库中添加string,设定过期时间time(秒)
- mset(key N, value N):批量设置多个string的值
- msetnx(key N, value N):如果所有名称为key i的string都不存在
- incr(key):名称为key的string增1操作
- incrby(key, integer):名称为key的string增加integer
- decr(key):名称为key的string减1操作
- decrby(key, integer):名称为key的string减少integer
- append(key, value):名称为key的string的值附加value
- substr(key, start, end):返回名称为key的string的value的子串
对List操作的命令
- rpush(key, value):在名称为key的list尾添加一个值为value的元素
- lpush(key, value):在名称为key的list头添加一个值为value的 元素
- llen(key):返回名称为key的list的长度
- lrange(key, start, end):返回名称为key的list中start至end之间的元素
- ltrim(key, start, end):截取名称为key的list
- lindex(key, index):返回名称为key的list中index位置的元素
- lset(key, index, value):给名称为key的list中index位置的元素赋值
- lrem(key, count, value):删除count个key的list中值为value的元素
- lpop(key):返回并删除名称为key的list中的首元素
- rpop(key):返回并删除名称为key的list中的尾元素
- blpop(key1, key2,… key N, timeout):lpop命令的block版本。
- brpop(key1, key2,… key N, timeout):rpop的block版本。
- rpoplpush(srckey, dstkey):返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部
对Set操作的命令
- sadd(key, member):向名称为key的set中添加元素member
- srem(key, member) :删除名称为key的set中的元素member
- spop(key) :随机返回并删除名称为key的set中一个元素
- smove(srckey, dstkey, member) :移到集合元素
- scard(key) :返回名称为key的set的基数
- sismember(key, member) :member是否是名称为key的set的元素
- sinter(key1, key2,…key N) :求交集
- sinterstore(dstkey, (keys)) :求交集并将交集保存到dstkey的集合
- sunion(key1, (keys)) :求并集
- sunionstore(dstkey, (keys)) :求并集并将并集保存到dstkey的集合
- sdiff(key1, (keys)) :求差集
- sdiffstore(dstkey, (keys)) :求差集并将差集保存到dstkey的集合
- smembers(key) :返回名称为key的set的所有元素
- srandmember(key) :随机返回名称为key的set的一个元素
对Hash操作的命令
- hset(key, field, value):向名称为key的hash中添加元素field
- hget(key, field):返回名称为key的hash中field对应的value
- hmget(key, (fields)):返回名称为key的hash中field i对应的value
- hmset(key, (fields)):向名称为key的hash中添加元素field
- hincrby(key, field, integer):将名称为key的hash中field的value增加integer
- hexists(key, field):名称为key的hash中是否存在键为field的域
- hdel(key, field):删除名称为key的hash中键为field的域
- hlen(key):返回名称为key的hash中元素个数
- hkeys(key):返回名称为key的hash中所有键
- hvals(key):返回名称为key的hash中所有键对应的value
- hgetall(key):返回名称为key的hash中所有的键(field)及其对应的value
六、Redis在项目中的使用场景
数据类型 | 使用场景 |
String | 比如说 ,我想知道什么时候封锁一个IP地址。Incrby命令 |
Hash | 存储用户信息【id,name,age】 Hset(key,field,value) Hset(userKey,id,101) Hset(userKey,name,admin) Hset(userKey,age,23) ----修改案例---- Hget(userKey,id) Hset(userKey,id,102) 为什么不使用String 类型来存储 Set(userKey,用信息的字符串) Get(userKey) 不建议使用String 类型 |
List | 实现最新消息的排行,还可以利用List的push命令,将任务存在list集合中,同时使用另一个命令,将任务从集合中取出[pop]。 Redis—list数据类型来模拟消息队列。【电商中的秒杀就可以采用这种方式来完成一个秒杀活动】 |
Set | 特殊之处:可以自动排重。比如说微博中将每个人的好友存在集合(Set)中, 这样求两个人的共通好友的操作。我们只需要求交集即可。 |
Zset | 以某一个条件为权重,进行排序。 京东:商品详情的时候,都会有一个综合排名,还可以按照价格进行排名。 |
七、常见问题解决——缓存穿透、缓存击穿、缓存雪崩
7.1、缓存穿透——常见于不规范的key
概念:访问一个不存在的key,缓存不起作用,请求会穿透到DB,流量大时DB会挂掉。
解决方案:
- 采用布隆过滤器(Bloom Filter,Redis自带),使用一个足够大的bitmap,用于存储可能访问的key,不存在的key直接被过滤;
- 访问key未在DB查询到值,也将空值写进缓存,但可以设置较短过期时间。
7.2、缓存雪崩——常见于大量的key设置相同过期时间
概念:大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。
解决方案:可以给缓存设置过期时间时加上一个随机值时间,使得每个key的过期时间分布开来,不会集中在同一时刻失效。
7.3、缓存击穿——常见于热点key
概念:一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力骤增。
解决方案:在访问key之前,采用SETNX(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。
八、查看当前连接数 & 客户端连接信息
【 redis-cli 命令行使用:info clients 可以查看当前的 redis 连接数: 】
127.0.0.1:6379> info clients
# Clients
connected_clients:4
cluster_connections:0
maxclients:6
client_recent_max_input_buffer:56
client_recent_max_output_buffer:0
blocked_clients:0
tracking_clients:0
clients_in_timeout_table:0
【 redis 查看详细连接: 】
127.0.0.1:6379> CLIENT LIST
id=3 addr=192.168.1.6:60249 laddr=192.168.1.66:6379 fd=7 name= age=1276 idle=4 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=0 omem=0 tot-mem=20504 events=r cmd=info user=default redir=-1
id=7 addr=192.168.1.6:60268 laddr=192.168.1.66:6379 fd=10 name= age=1264 idle=1264 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=0 omem=0 tot-mem=20536 events=r cmd=scan user=default redir=-1
id=8 addr=192.168.1.6:60269 laddr=192.168.1.66:6379 fd=9 name= age=1263 idle=860 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=0 omem=0 tot-mem=20528 events=r cmd=zrange user=default redir=-1
id=9 addr=127.0.0.1:45660 laddr=127.0.0.1:6379 fd=8 name= age=1133 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=40928 argv-mem=10 obl=0 oll=0 omem=0 tot-mem=61466 events=r cmd=client user=default redir=-1
【 redis-cli 命令控制行中获取客户端信息命令 】
CLIENT LIST 获取客户端列表
CLIENT SETNAME 设置当前连接点 redis 的名称
CLIENT GETNAME 查看当前连接的名称
CLIENT KILL ip:port 杀死指定连接
九、Redis三种集群模式
9.1、主从复制模式
- 主节点可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从节点。
- 从节点一般是只读的,并接受主节点同步过来的数据。
- 一个主节点可以拥有多个从节点,而一个从节点只能拥有一个主节点。
- 复制的数据流是单向的,只能由主节点复制到从节点。
- 引入主从复制机制的目的有两个:一个是读写分离,分担 “master” 的读写压力;一个是方便做容灾恢复。
主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。Redis 的策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。
主从复制优缺点:
优点
- 1、支持主从复制,主机会自动将数据同步到从机,可以进行读写分离;
- 2、为了分载 Master 的读操作压力,Slave 服务器可以为客户端提供只读操作的服务,提高负载。写服务仍然必须由Master来完成;
缺点
- 1、Redis不具备自动容错和恢复功能,主机的宕机需要等待机器重启或者手动切换前端的IP才能恢复(也就是要人工介入);
- 2、主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性;
- 3、Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂;
9.2、Sentinel(哨兵)模式
Redis的主从复制模式下,当主节点不能提供服务,需要手动将一台从节点切换为主节点,这不是一种推荐的方式。为此,Redis从2.8开始正式提供了Redis Sentinel(哨兵)架构来解决这个问题。
假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行 failover(故障转移) 过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,也就是大部分哨兵节点对主节点的下线做了同意的判定,那么这个判定就是客观的,即客观下线。接着哨兵之间就通过投票的方式选举出一个哨兵节点作为领导者,负责进行故障转移(failover)的工作(故障转移的工作只需要一个哨兵节点来完成)。具体包括:
- (1)、在从节点列表中选出一个节点作为新的主节点。
- (2)、Sentinel领导者节点会对第一步选出来的从节点执行slaveof no one命令让其成为主节点。
- (3)、Sentinel领导者节点会向剩余的从节点发送命令,让它们成为新主节点的从节点。
- (4)、Sentinel节点集合会将原来的主节点更新为从节点,并保持着对其关注。
哨兵模式的优缺点:
优点
- 1、 哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都具有。
- 2、 主从可以自动切换,系统更健壮,可用性更高(可以看作自动版的主从复制)。
缺点
- 1、Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。
9.3、Cluster 模式
Redis 的哨兵模式解决了主从不能自动故障恢复的问题,但在这种模式下 Redis 服务器都存储相同的数据,很浪费内存,所以在 redis3.0上加入了 Cluster 集群模式,实现了 Redis 的分布式存储,也就是说每台 Redis 节点上存储不同的内容。Redis Cluster是一种服务器 Sharding 技术。
集群的数据分片:Redis 集群没有使用一致性 hash,而是引入了虚拟槽分区的算法。会把Redis 集群分成16384 个槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽。集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点:
- 节点 A 包含 0 到 5460 号哈希槽
- 节点 B 包含 5461 到 10922 号哈希槽
- 节点 C 包含 10923 到 16383 号哈希槽
当客户端的请求过来,会首先通过对key进行 CRC16 的算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作,这样就实现了数据的访问更新。
- 为了保证高可用,redis-cluster集群引入了主从复制模型,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点。当其它主节点 ping 一个主节点 A 时,如果半数以上的主节点与 A 通信超时,那么认为主节点 A 宕机了。如果主节点 A 和它的从节点 A1 都宕机了,那么该集群就无法再提供服务了。
- 所有的 redis 节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
- 节点的 fail 是通过集群中超过半数的节点检测失效时才生效。
- 客户端与 Redis 节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
集群模式的优缺点
优点
- 1、集群模式是一个无中心的架构模式,将数据进行分片,分布到对应的槽中,每个节点存储不同的内容,通过路由能够找到对应的节点负责存储的槽,能够实现高效率的查询。
- 2、集群模式增加了横向和纵向的扩展能力,实现节点加入和收缩。
缺点
- 1、key批量操作支持有限。如mset、mget,目前只支持具有相同slot值的key执行批量操作。对于映射为不同slot值的key由于执行mset、mget等操作可能存在于多个节点上因此不被支持。
- 2、key事务操作支持有限。同理只支持多key在同一节点上的事务操作,当多个key分布在不同的节点上时无法使用事务功能。
- 3、key作为数据分区的最小粒度,因此不能将一个大的键值对象如hash、list等映射到不同的节点。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)