Redis 命令相关命令
官方文档:https://redis.io/commands
参考链接:
http://redisdoc.com/
http://doc.redisfans.com/
info显示当前节点redis运行状态信息
[root@xyy7 etc]# redis-cli
127.0.0.1:6379> info
# Server
redis_version:5.0.7
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:4cfb0d4404f1c1f8
redis_mode:standalone
os:Linux 3.10.0-693.el7.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:4.8.5
process_id:27632
run_id:6430d3259e0be115a3fc40338d9c60b8add8164f
tcp_port:6379
uptime_in_seconds:23561
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:9324582
executable:/apps/redis/bin/redis-server
config_file:/apps/redis/etc/redis.conf
SELECT 切换数据库,相当于在MySQL的 USE DBNAME 指令
127.0.0.1:6379> INFO cluster
# Cluster
cluster_enabled:0
127.0.0.1:6379> SELECT 0
OK
127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]>
#在 redis cluster 模式下不支持多个数据库,会出现下面错误
MSTE 一次性设置多个key
127.0.0.1:6379> MSET one 1 two 2 three 3 four 4
BGSAVE 手动持久化
127.0.0.1:6379[1]> BGSAVE
Background saving started
DBSIZE 返回当前库下的所有key 数量
127.0.0.1:6379> DBSIZE
(integer) 2
FLUSHDB 强制清空当前库中的所有key,此命令慎用
127.0.0.1:6379> DBSIZE
(integer) 2
127.0.0.1:6379> FLUSHDB
OK
127.0.0.1:6379> DBSIZE
(integer) 0
127.0.0.1:6379>
8FLUSHALL 强制清空当前redis服务器所有数据库中的所有key,即删除所有数据,此命令慎用
127.0.0.1:6379> FLUSHALL OK
#生产建议修改配置 /etc/redis.conf
rename-command FLUSHALL ""
#rename-command 在6.2.4版淘汰了
SHUTDOWN 停止所有客户端
如果有至少一个保存点在等待,执行 SAVE 命令
如果 AOF 选项被打开,更新 AOF 文件
关闭 redis 服务器(server)
如果持久化被打开的话, SHUTDOWN 命令会保证服务器正常关闭而不丢失任何数据。
另一方面,假如只是单纯地执行 SAVE 命令,然后再执行 QUIT 命令,则没有这一保证 —— 因为在执行SAVE 之后、执行 QUIT 之前的这段时间中间,其他客户端可能正在和服务器进行通讯,这时如果执行 QUIT 就会造成数据丢失。
redis数据类型
参考资料:http://www.redis.cn/topics/data-types.html
相关命令参考: http://redisdoc.com/
Redis有以下这五种基本类型:
- String(字符串)
- Hash(哈希)
- List(列表)
- Set(集合)
- zset(有序集合)
它还有三种特殊的数据结构类型
- Geospatial
- Hyperloglog
- Bitmap
字符串(string)
字符串是所有编程语言中最常见的和最常用的数据类型,而且也是redis最基本的数据类型之一,而且redis 中所有的 key 的类型都是字符串。常用于保存 Session 信息场景,此数据类型比较常用
set 指令可以创建一个key 并赋值, 使用格式
SETkeyvalue [EX seconds] [PX milliseconds] [NX|XX]时间复杂度: O(1)
将字符串值 value 关联到 key
如果 key 已经持有其他值, SET 就覆写旧值,无视类型。
当 SET 命令对一个带有生存时间(TTL)的键进行设置之后,该键原有的 TTL 将被清除。
从 Redis 2.6.12 版本开始, SET 命令的行为可以通过一系列参数来修改:
EX seconds :将键的过期时间设置为 seconds 秒。执行 SET key value EX seconds 的效果等同于执行 SETEX key seconds value 。
PX milliseconds :将键的过期时间设置为 milliseconds 毫秒。执行 SET key value PX
milliseconds 的效果等同于执行 PSETEX key milliseconds value 。
NX :只在键不存在时,才对键进行设置操作。执行 SET key value NX 的效果等同于执行 SETNX key value 。
XX :只在键已经存在时,才对键进行设置操作。
set 设置key
127.0.0.1:6379> set key1 value1
OK
127.0.0.1:6379> get key1
"value1"
type 判断类型
127.0.0.1:6379> TYPE key1 #判断类型
string
ex 判断自动过期
127.0.0.1:6379> SET title ceo ex 3#设置自动过期时间3s OK
setenx 查看过期时间
127.0.0.1:6379> set title
"ceo"
127.0.0.1:6379> setnx title coo #set key value nx
(integer) 0
127.0.0.1:6379> get title
"ceo"
del 删除key
127.0.0.1:6379> DEL key1
(integer) 1
mset 批量添加key
127.0.0.1:6379> MSET key1 value1 key2 value2
OK
APPEND 追加数据
127.0.0.1:6379> set key1 123
OK
127.0.0.1:6379> append key1 "cxk"
(integer) 6
127.0.0.1:6379> get key1
字符串(string)
- 简介:String是Redis最基础的数据结构类型,它是二进制[安全]的,可以[存储]图片或者序列化的对象,值最大[存储]为512M
- 简单使用举例:
set``key``value
、get``key
等 - 应用场景:共享session、分布式锁,计数器、限流。
- 内部编码有3种,
int(8字节长整型)/embstr(小于等于39字节字符串)/raw(大于39个字节字符串)
列表list
- 简介:列表(list)类型是用来存储多个有序的字符串,一个列表最多可以存储2^32-1个元素。
- 简单实用举例:lpush key value [value …] lrange key start end
- 内部编码:ziplist(压缩列表)、linkedlist(链表)
- 应用场景:消息队列,文章列表
哈希
- 简介:在Redis中,哈希类型是指v(值)本身又是一个键值对(k-v)结构
- 简单使用举例:
hset``key``field``value
、hget``key``field
- 内部编码:
ziplist(压缩列表)
、hashtable(哈希表)
- 应用场景:缓存用户信息等。
- 注意点:如果开发使用hgetall,哈希元素比较多的话,可能导致Redis阻塞,可以使用hscan。而如果只是获取部分field,建议使用hmget。
Set(集合)
- 简介:集合(set)类型也是用来保存多个的字符串元素,但是不允许重复元素
- 简单使用举例:
sadd``key``element``[element``...]
、smembers key
- 内部编码:
intset(整数集合)
、hashtable(哈希表)
- 注意点:smembers和lrange、hgetall都属于比较重的命令,如果元素过多存在阻塞Redis的可能性,可以使用sscan来完成。
- 应用场景:用户标签,生成随机数抽奖、社交需求。
有序集合(zset)
- 简介:已排序的字符串集合,同时元素不能重复
- 简单格式举例:
zadd``key``score``member``[score``member``...]
,zrank``key``member
- 底层内部编码:
ziplist(压缩列表)
、skiplist(跳跃表)
- 应用场景:排行榜,社交需求(如用户点赞)。
三种特殊的数据类型
- Geo:Redis3.2推出的,地理位置定位,用于[存储]地理位置信息,并对[存储]的信息进行操作。
- HyperLogLog:用来做基数统[计算法的数据结构,如统计网站的UV。
- Bitmaps :用一个比特位来映射某个元素的状态,在Redis中,它的底层是基于字符串类型实现的,可以把bitmaps成作一个以比特位为单位的数组
分布式锁
是控制分布式系统不同进程共同访问共享资源的一种锁的实现。秒杀下单、抢红包等等业务场景,都需要用到分布式锁
- 命令setnx + expire分开写
- setnx + value值是过期时间
- set的扩展命令(set ex px nx)
- set ex px nx + 校验唯一随机值,再删除
Redisson
分布式锁可能存在锁过期释放,业务没执行完的问题。延长时间锁闭关不能结局问题。其实我们设想一下,是否可以给获得锁的线程,开启一个定时守护线程,每隔一段时间检查锁是否还存在,存在则对锁的过期时间延长,防止锁过期提前释放。
解决办法: 只要线程一加锁成功,就会启动一个watch dog
看门狗,它是一个后台线程,会每隔10秒检查一下,如果线程1还持有锁,那么就会不断的延长锁key的生存时间。因此,Redisson就是使用Redisson解决了锁过期释放,业务没执行完问题。
消息队列
消息队列: 把要传输的数据放在队列中 功能: 可以实现多个系统之间的解耦,异步,削峰/限流等 常用的消息队列应用: kafka,rabbitMQ,redis 消息队列主要分为两种,这两种模式Redis都支持
1.生产者消费者模式
在生产者/消费者(Producer/Consumer)模式下,上层应用接收到的外部请求后开始处理其当前步骤的操作,在执行完成后将已经完成的操作发送至指定的频道(channel,逻辑队列)当中,并由其下层的应用监听该频道并继续下一步的操作,如果其处理完成后没有下一步的操作就直接返回数据给外部请求,如果还有下一步的操作就再将任务发布到另外一个频道,由另外一个消费者继续监听和处理。此模式应用广泛
2.发布者订阅模式
在发布者订阅者模式下,发布者将消息发布到指定的channel里面,凡是监听该channel的消费者都会收到同样的一份消息,这种模式类似于是收音机的广播模式,即凡是收听某个频道的听众都会收到主持人发布的相同的消息内容。此模式常用语群聊天、群通知、群公告等场景
- Publisher:发布者
- Subscriber:订阅者
- Channel:频道
拓展
MySQL与Redis 如何保证双写一致性
- 缓存延时双删
- 删除缓存重试机制
- 读取biglog异步删除缓存
在生成 RDB期间,Redis 可以同时处理写请求么?
可以的,Redis提供两个指令生成RDB,分别是save和bgsave。
- 如果是save指令,会阻塞,因为是主线程执行的。
- 如果是bgsave指令,是fork一个子进程来写入RDB文件的,快照持久化完全交给子进程来处理,父进程则可以继续处理客户端的请求。
redis的虚拟内存机制
虚拟内存机制就是暂时把不经常访问的数据(冷数据)从内存交换到磁盘中,从而腾出宝贵的内存空间用于其它需要访问的数据(热数据)。通过VM功能可以实现冷热数据分离,使热数据仍在内存中、冷数据保存到磁盘。这样就可以避免因为内存不足而造成访问速度下降的问题。
缓存击穿、缓存穿透、缓存雪崩
缓存穿透
常见的缓存使用方式:读请求,先查缓存,缓存有值命中,就直接返回;缓存未命中,就去查数据库,然后把数据库的值更新到缓存,再返回。 {data-type=drawio data-xml=%3CmxGraphModel%20dx=%22871%22%20dy=%22452%22%20grid=%221%22%20gridSize=%2210%22%20guides=%221%22%20tooltips=%221%22%20connect=%221%22%20arrows=%221%22%20fold=%221%22%20page=%221%22%20pageScale=%221%22%20pageWidth=%22827%22%20pageHeight=%221169%22%3E%3Croot%3E%3CmxCell%20id=%220%22/%3E%3CmxCell%20id=%221%22%20parent=%220%22/%3E%3CmxCell%20id=%226%22%20value=%22%22%20style=%22edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;jettySize=auto;orthogonalLoop=1;%22%20edge=%221%22%20parent=%221%22%20source=%222%22%20target=%225%22%3E%3CmxGeometry%20relative=%221%22%20as=%22geometry%22/%3E%3C/mxCell%3E%3CmxCell%20id=%222%22%20value=%22%E8%AF%BB%E5%8F%96%E8%AF%B7%E6%B1%82%22%20style=%22rounded=1;whiteSpace=wrap;html=1;%22%20vertex=%221%22%20parent=%221%22%3E%3CmxGeometry%20x=%22294%22%20y=%2250%22%20width=%22120%22%20height=%2260%22%20as=%22geometry%22/%3E%3C/mxCell%3E%3CmxCell%20id=%2210%22%20value=%22%22%20style=%22edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;jettySize=auto;orthogonalLoop=1;%22%20edge=%221%22%20parent=%221%22%20source=%225%22%20target=%229%22%3E%3CmxGeometry%20relative=%221%22%20as=%22geometry%22/%3E%3C/mxCell%3E%3CmxCell%20id=%2216%22%20style=%22edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;entryX=1;entryY=0.5;jettySize=auto;orthogonalLoop=1;%22%20edge=%221%22%20parent=%221%22%20source=%225%22%20target=%2214%22%3E%3CmxGeometry%20relative=%221%22%20as=%22geometry%22%3E%3CArray%20as=%22points%22%3E%3CmxPoint%20x=%22510%22%20y=%22240%22/%3E%3CmxPoint%20x=%22510%22%20y=%22660%22/%3E%3C/Array%3E%3C/mxGeometry%3E%3C/mxCell%3E%3CmxCell%20id=%225%22%20value=%22%E6%98%AF%E5%90%A6%E5%91%BD%E4%B8%AD%E7%BC%93%E5%AD%98%22%20style=%22rounded=1;whiteSpace=wrap;html=1;%22%20vertex=%221%22%20parent=%221%22%3E%3CmxGeometry%20x=%22294%22%20y=%22210%22%20width=%22120%22%20height=%2260%22%20as=%22geometry%22/%3E%3C/mxCell%3E%3CmxCell%20id=%2213%22%20value=%22%22%20style=%22edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;jettySize=auto;orthogonalLoop=1;%22%20edge=%221%22%20parent=%221%22%20source=%229%22%20target=%2212%22%3E%3CmxGeometry%20relative=%221%22%20as=%22geometry%22/%3E%3C/mxCell%3E%3CmxCell%20id=%229%22%20value=%22%E4%BB%8E%E6%95%B0%E6%8D%AE%E5%BA%93%E8%AF%BB%E5%8F%96%22%20style=%22rounded=1;whiteSpace=wrap;html=1;%22%20vertex=%221%22%20parent=%221%22%3E%3CmxGeometry%20x=%22294%22%20y=%22350%22%20width=%22120%22%20height=%2260%22%20as=%22geometry%22/%3E%3C/mxCell%3E%3CmxCell%20id=%2215%22%20value=%22%22%20style=%22edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;jettySize=auto;orthogonalLoop=1;%22%20edge=%221%22%20parent=%221%22%20source=%2212%22%20target=%2214%22%3E%3CmxGeometry%20relative=%221%22%20as=%22geometry%22/%3E%3C/mxCell%3E%3CmxCell%20id=%2212%22%20value=%22%E6%9B%B4%E6%96%B0%E7%BC%93%E5%AD%98%22%20style=%22rounded=1;whiteSpace=wrap;html=1;%22%20vertex=%221%22%20parent=%221%22%3E%3CmxGeometry%20x=%22294%22%20y=%22490%22%20width=%22120%22%20height=%2260%22%20as=%22geometry%22/%3E%3C/mxCell%3E%3CmxCell%20id=%2214%22%20value=%22%E8%BF%94%E5%9B%9E%E6%95%B0%E6%8D%AE%22%20style=%22rounded=1;whiteSpace=wrap;html=1;%22%20vertex=%221%22%20parent=%221%22%3E%3CmxGeometry%20x=%22294%22%20y=%22630%22%20width=%22120%22%20height=%2260%22%20as=%22geometry%22/%3E%3C/mxCell%3E%3CmxCell%20id=%2211%22%20value=%22N%22%20style=%22text;html=1;resizable=0;points=%5B%5D;autosize=1;align=left;verticalAlign=top;spacingTop=-4;fontSize=16;%22%20vertex=%221%22%20parent=%221%22%3E%3CmxGeometry%20x=%22337%22%20y=%22301%22%20width=%2220%22%20height=%2220%22%20as=%22geometry%22/%3E%3C/mxCell%3E%3CmxCell%20id=%2217%22%20value=%22Y%22%20style=%22text;html=1;resizable=0;points=%5B%5D;autosize=1;align=left;verticalAlign=top;spacingTop=-4;strokeWidth=9;fontSize=16;%22%20vertex=%221%22%20parent=%221%22%3E%3CmxGeometry%20x=%22471%22%20y=%22210%22%20width=%2220%22%20height=%2220%22%20as=%22geometry%22/%3E%3C/mxCell%3E%3C/root%3E%3C/mxGraphModel%3E}
缓存穿透 缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。 如果穿透发生 严重的情况 可能会把数据库搞挂掉,导致整个服务瘫痪。
通俗理解就是:读请求访问时,缓存和数据库都没有某个值,这样就会导致每次对这个值的查询请求都会穿透到数据库进行查询,这就是缓存穿透。
产生原因:
- 业务不合理的设计,比如大多数用户都没开守护,但是你的每个请求都去缓存,查询某个userid查询有没有守护。
- 业务/运维/开发失误的操作,如缓存和数据库的数据都被误删除了。
- 黑客非法请求攻击,如黑客故意捏造大量非法请求,读取不存在的业务数据。
如何避免缓存穿透呢? 一般有三种方法。
- 1.如果是非法请求,我们在API入口,对参数进行校验,过滤非法值。
- 2.如果查询数据库为空,我们可以给缓存设置个空值,或者默认值。但是如有有写请求进来的话,需要更新缓存,以保证缓存一致性,同时,最后给缓存设置适当的过期时间。(业务上比较常用,简单有效)
- 3.使用布隆过滤器快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器判断值是否存在,存在才继续往下查。
布隆过滤器原理:它由初始值为0的位图数组和N个哈希函数组成。一个对一个key进行N个hash算法获取N个值,在比特数组中将这N个值散列后设定为1,然后查的时候如果特定的这几个位置都为1,那么布隆过滤器判断该key存在。
缓存雪崩
指缓存中数据大批量到过期时间,而查询数据量巨大,请求都直接访问数据库,引起数据库压力过大甚至down机。(数据库挂掉)
- 缓存雪奔一般是由于大量数据同时过期造成的,对于这个原因,可通过均匀设置过期时间解决,即让过期时间相对离散一点。
- Redis 故障宕机也可能引起缓存雪奔,构造Redis高可用集群即可解决。
缓存击穿
某一个热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求 请求到数据库 导致宕机。
雪崩,缓存击穿看着有点像,其实它两区别是,缓存雪奔是指数据库压力过大甚至down机,缓存击穿只是大量并发请求到了DB数据库层面。可以认为击穿是缓存雪奔的一个子集吧。另外二者区别,是区别在于击穿针对某一热点key缓存,雪崩则是很多key。
解决方法:
- 1.使用互斥锁方案。缓存失效时,不是立即去加载db数据,而是先使用某些带成功返回的原子操作命令,如(Redis的setnx)去操作,成功的时候,再去加载db数据库数据和设置缓存。否则就去重试获取缓存。
- 2. “永不过期”,是指没有设置过期时间,但是热点数据快要过期时,异步线程去更新和设置过期时间。
解释: 热key:在Redis中,我们把访问频率高的key,称为热点key。 产生原因:
- 用户消费的数据远大于生产的数据,如秒杀商品活动、热点新闻等读多写少的场景。
- 请求分片集中,超过单Redi服务器的性能,比如固定名称key,Hash落入同一台服务器,瞬间访问量极大,超过机器瓶颈,产生热点Key问题。
解决方法:
- Redis集群扩容:增加分片副本,均衡读流量;
- 将热key分散到不同的服务器中;
- 使用二级缓存,即JVM本地缓存,减少Redis的读请求。
过期策略
在set
key
的时候,可以给它设置一个过期时间,比如expire
key
60
。指定这key60s后过期,60s后,该怎么处理数据?
定时过期
每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即对key进行清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。
惰性过期
只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
定期过期
每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。 expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。
Redis中同时使用了惰性过期和定期过期两种过期策略。
- 假设Redis当前存放30万个key,并且都设置了过期时间,如果你每隔100ms就去检查这全部的key,CPU负载会特别高,最后可能会挂掉。
- 因此,redis采取的是定期过期,每隔100ms就随机抽取一定数量的key来检查和删除的。
- 但是呢,最后可能会有很多已经过期的key没被删除。这时候,redis采用惰性删除。在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间并且已经过期了,此时就会删除。
但是呀,如果定期删除漏掉了很多过期的key,然后也没走惰性删除。就会有很多过期key积在内存内存,直接会导致内存爆的。或者有些时候,业务量大起来了,redis的key被大量使用,内存直接不够了,运维也未加大内存了。难道redis直接这样挂掉?
引申一个问题 淘汰策略 (python 写的 会进行监控 )
- volatile-lru:当内存不足以容纳新写入数据时,从设置了过期时间的key中使用LRU(最近最少使用)算法进行淘汰;
- allkeys-lru:当内存不足以容纳新写入数据时,从所有key中使用LRU(最近最少使用)算法进行淘汰。
- volatile-lfu:4.0版本新增,当内存不足以容纳新写入数据时,在过期的key中,使用LFU算法进行删除key。
- allkeys-lfu:4.0版本新增,当内存不足以容纳新写入数据时,从所有key中使用LFU算法进行淘汰;
- volatile-random:当内存不足以容纳新写入数据时,从设置了过期时间的key中,随机淘汰数据;。
- allkeys-random:当内存不足以容纳新写入数据时,从所有key中随机淘汰数据。
- volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的key中,根据过期时间进行淘汰,越早过期的优先被淘汰;
- noeviction:默认策略,当内存不足以容纳新写入数据时,新写入操作会报错。
redis 多实例操作
首先关门起始的redis数据库
[root@xyy7 etc]# systemctl stop redis.service
#准备配置文件
[root@xyy7 etc]# cp /apps/redis/etc/redis.conf /apps/redis/etc/redis6379.conf
[root@xyy7 etc]# cp /apps/redis/etc/redis.conf /apps/redis/etc/redis6380.conf
[root@xyy7 etc]# cp /apps/redis/etc/redis.conf /apps/redis/etc/redis6381.conf
[root@node2 etc]#cp /apps/redis/etc/redis.conf /apps/redis/etc/redis6379.conf
[root@node2 etc]#cp /apps/redis/etc/redis.conf /apps/redis/etc/redis6380.conf
[root@node2 etc]#cp /apps/redis/etc/redis.conf /apps/redis/etc/redis6381.conf
#准备配置文件
[root@node2 etc]#grep dump.rdb redis6379.conf
#修改 备份文件的名字
dbfilename dump.rdb
[root@node2 etc]#sed -i 's/dbfilename dump.rdb/dbfilename dump6379.rdb/' redis6379.conf
[root@node2 etc]#grep dump redis6379.conf
[root@node2 etc]#sed -i 's/dbfilename dump.rdb/dbfilename dump6380.rdb/' redis6380.conf
[root@node2 etc]#sed -i 's/dbfilename dump.rdb/dbfilename dump6381.rdb/' redis6381.conf
#修改日志文件
[root@node2 etc]#grep "logfile" redis6379.conf
logfile ""
[root@node2 etc]#sed -i 's#logfile ""#logfile /apps/redis/log/redis6379.log#' redis6379.conf
[root@node2 etc]#grep "logfile" redis6379.conf
logfile /apps/redis/log/redis6379.log
[root@node2 etc]#sed -i 's#logfile ""#logfile /apps/redis/log/redis6380.log#' redis6380.conf
[root@node2 etc]#grep "logfile" redis6380.conf
logfile /apps/redis/log/redis6380.log
[root@node2 etc]#sed -i 's#logfile ""#logfile /apps/redis/log/redis6381.log#' redis6381.conf
[root@node2 etc]#grep "logfile" redis6381.conf
logfile /apps/redis/log/redis6381.log
#修改pid文件
[root@node2 etc]#grep "pidfile" redis6379.conf
#6379 不用改了
pidfile /var/run/redis_6379.pid
[root@node2 etc]#sed -i 's/redis_6379.pid/redis_6380.pid/' redis6380.conf
[root@node2 etc]#sed -i 's/redis_6379.pid/redis_6381.pid/' redis6381.conf
[root@node2 etc]#grep "pidfile" redis6380.conf
pidfile /var/run/redis_6380.pid
[root@node2 etc]#grep "pidfile" redis6381.conf
pidfile /var/run/redis_6381.pid
#修改端口号
[root@node2 etc]#sed -i 's/^port 6379/port 6380/' redis6380.conf
[root@node2 etc]#sed -i 's/^port 6379/port 6381/' redis6381.conf
#准备service文件
[root@node2 apps]#cp /lib/systemd/system/redis.service /lib/systemd/system/redis6379.service
[root@node2 apps]#cp /lib/systemd/system/redis.service /lib/systemd/system/redis6380.service
[root@node2 apps]#cp /lib/systemd/system/redis.service /lib/systemd/system/redis6381.service
[Unit]
Description=Redis persistent key-value database
After=network.target
[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis6379.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
#Type=notify 如果支持systemd可以启用此行
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
[Unit]
Description=Redis persistent key-value database
After=network.target
[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis6380.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
#Type=notify 如果支持systemd可以启用此行
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
[Unit]
Description=Redis persistent key-value database
After=network.target
[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis6381.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
#Type=notify 如果支持systemd可以启用此行
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
[root@node2 apps]#chown redis.redis /apps/redis/ -R
[root@xyy7 etc]# systemctl daemon-reload
[root@xyy7 etc]# systemctl start redis6380
[root@xyy7 etc]# systemctl start redis6381
[root@xyy7 etc]# systemctl start redis
[root@xyy7 etc]# ss -lnt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 511 *:6379 *:*
LISTEN 0 511 *:6380 *:*
LISTEN 0 511 *:6381 *:*
#测试
[root@node2 apps]#redis-cli
[root@node2 apps]#redis-cli -p 6380
[root@node2 apps]#redis-cli -p 6381
redis-cli -p 6380
127.0.0.1:6380>