缓存数据库--Redis

发布于 2017-10-17 · 本文总共 12296 字 · 阅读大约需要 36 分钟

使用缓存保护MySQL

MySQL能承担的并发读写的量是有上限的,当系统的在线用户超过几万到几十万这个量级的时候, 单台MySQL就很难应付了。

Redis简介

与其他数据库和软件的比较

与memcache比较

底层实现机制

1.内存分配

memcache使用预分配内存池的方式管理内存,能够省去内存分配时间。

redis则是临时申请空间,可能导致碎片。

2.虚拟内存使用

memcache把所有的数据存储在物理内存里。

redis有自己的VM机制,理论上能够存储比物理内存更多的数据,当数据超量时,会引发swap,把冷数据刷到磁盘上。

3.网络模型

memcache使用非阻塞IO复用模型;

redis也是使用非阻塞IO复用模型,redis还提供一些非KV存储之外的排序,聚合功能, 在执行这些功能时,复杂的CPU计算,会阻塞整个IO调度;

4.线程模型

memcache使用多线程,主线程监听,worker子线程接受请求,执行读写,这个过程中,可能存在锁冲突。

redis使用单线程,虽无锁冲突,但难以利用多核的特性提升整体吞吐量。

什么时候倾向于选择redis?

1.复杂数据结构

value是哈希,列表,集合,有序集合这类复杂的数据结构时,会选择redis,因为mc无法满足这些需求。 最典型的场景,用户订单列表,用户消息,帖子评论列表等。

memcache只能存储普通的字符串键

2.持久化

mc无法满足持久化的需求,只得选择redis。

只读场景,或者允许一些不一致的业务场景,可以尝试开启redis的固化功能。

3.天然高可用

redis天然支持集群功能,可以实现主动复制,读写分离。

但是,这里要提醒的是,大部分业务场景,缓存真的需要高可用么?
(1)缓存场景,很多时候,是允许cache miss
(2)缓存挂了,很多时候可以通过DB读取数据

4.存储的内容比较大

memcache的value存储,最大为1M,如果存储的value很大,只能使用redis。

什么时候倾向于memcache?

纯KV,数据量非常大,并发量非常大的业务,使用memcache或许更适合。

Redis为什么快

Redis 是一个使用内存保存数据的高性能 KV 数据库,它的高性能主要来自于:

  • 简单的数据结构;
  • 使用内存存储数据;
  • epoll

缺点:

Redis 仍然是一个不可靠的存储,它在设计上天然就不保证数据的可靠性,所以一般我们都使用 Redis 做缓存, 很少使用它作为唯一的数据存储。

Redis数据结构

String

数据类型比较简单,对应到数据结构里,就是字符串

常用命令:set/get/decr/incr/mget等;

使用场景:String是最常用的一种数据类型,普通的key/value存储都可以归为此类;

实现方式:默认是一个字符串,被redisObject所引用,遇到incr/decr等操作时会转成数值型进行计算;

List

常用命令:lpush/rpush/lpop/rpop/lrange等;

应用场景:如微博关注列表、粉丝列表等可以用list结构来实现;

1.压缩列表-ziplist

当列表中存储的数据量比较小的时候,列表就可以采用压缩列表的方式实现。

具体需要同时满足下面两个条件:

  • 列表中保存的单个数据(有可能是字符串类型的)小于 64 字节

  • 列表中数据个数少于 512 个

2.双向循环链表

以下是C语言代码

typedef struct listnode {
  struct listNode *prev;
  struct listNode *next;
  void *value;
} listNode;


typedef struct list {
  listNode *head;
  listNode *tail;
  unsigned long len;
  // ....省略其他定义
} list;

Set

常用命令:sadd/spop/smembers/sunion等;

应用场景:Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的, 当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择, 并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的;

set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的, 这也是set能提供判断一个成员是否在集合内的原因;

1.有序数组

需要同时满足下面两个条件:

  • 存储的数据都是整数

  • 存储的数据元素个数不超过 512 个

2.散列表

Hash

常用命令:hget/hset/hgetall等;

应用场景:如果需要存储一个用户信息对象数据,其中包括用户ID、name、age、birth, 通过用户ID我们希望获取该用户的name、age或者birth;

内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口。Key是用户ID, value是一个Map。这个Map的key是成员的属性名,value是属性值。这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据;

1.压缩列表-ziplist

只有当存储的数据量比较小的情况下,Redis 才使用压缩列表来实现字典类型

具体需要同时满足下面两个条件:

  • 字典中保存的键和值的大小都要小于 64 字节

  • 字典中键值对的个数要小于 512 个

2.散列表

MurmurHash2这种运行速度快、随机性好的哈希算法作为哈希函数

哈希冲突问题:使用链表法

动态扩容、缩容

渐进式扩容缩容策略,将数据的搬移分批进行

ZSET

常用命令:zadd/zrange/zrem/zcard等;

应用场景:Redis sorted set的使用场景与set类似,区别是set不是自动有序的, 而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序, 并且是插入有序的,即自动排序。 当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构;

sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序, HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员, 排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单;

1.压缩列表

使用压缩列表来实现有序集合的前提:

  • 所有数据的大小都要小于 64 字节

  • 元素个数要小于 128 个

跳表

各方面性能都比较优秀的动态数据结构,可以支持快速的插入、删除、查找操作,写起来也不复杂,甚至可以替代红黑树(Red-black tree)

链表加多级索引

在跳表中查询某个数据的时候,如果每一层都要遍历 m 个结点,那在跳表中查询一个数据的时间复杂度就是 O(m*logn)。

插入、删除操作的时间复杂度也是 O(logn)

跳表通过随机函数来维护“平衡性”。

跳表与红黑树

插入一个数据;

删除一个数据;

查找一个数据;

按照区间查找数据(比如查找值在[100, 356]之间的数据);

迭代输出有序序列。

按照区间来查找数据这个操作,红黑树的效率没有跳表高

跳表也不能完全替代红黑树。因为红黑树比跳表的出现要早一些,很多编程语言中的 Map 类型都是通过红黑树来实现的。我们做业务开发的时候,直接拿来用就可以了,不用费劲自己去实现一个红黑树,但是跳表并没有一个现成的实现,所以在开发中,如果你想使用跳表,必须要自己实现。

应用场景

1.Session Cacheh会话缓存

2.全页缓存

3.计数器

4.排行榜

5.队列

6.发布/订阅

持久化策略

快照(RDB)

RDB持久化指的是在满足一定的触发条件时(在一个的时间间隔内执行修改命令达到一定的数量, 或者手动执行SAVE和BGSAVE命令),对这个时间点的数据库所有键值对信息生成一个压缩文件dump.rdb, 然后将旧的删除,进行替换。

默认开启
fork一个进程来进行持久化
持久化的文件默认保存在dump.rdb, 可以修改redis.conf文件的dir配置路径 bgsave使用子进程持久化
save使用主进程持久化
shutdown时会自动触发

主从复制的情况下rdb关不掉

bgsave的原理主要是fork和cow,fork即redis通过创建子进程来进行bgsave操作; cow即Copy On Write,子进程创建后,父子进程共享数据段,父进程继续提供读写服务, 写脏的页面数据会逐渐和子进程分离开来;

AOF 日志

AOF持久化主要是Redis在修改相关的命令后,将命令添加到aof_buf缓存区的末尾,然后在每次事件循环结束时, 根据appendfsync的配置(always是总是写入,everysec是每秒写入,no是根据操作系统来决定何时写入), 判断是否需要将aof_buf写入AOF文件。

丢失的数据少,每1s执行一次保存,丢失数据不超过2s
每秒可以写10W+数据
可在配置中修改,appendonly 开关,使用everysec,不要用always
appendonly.aof

aof重写:

auto-aof-rewrite-min-size 64M

auto-aof-rewrite-percentage 100

bgrewriteaof

redis4.0
混合持久化机制

如何做持久化

bgsave做镜像全量持久化,AOF做增量持久化;

在Redis实例重启时,使用bgsave持久化文件重新构建内存, 再使用AOF重放近期的操作指令来实现完整恢复重启之前的状态;

过期策略

惰性清除(被动删除)

在访问key时,如果发现key已经过期,那么会将key删除。

定时清理(主动清理)

由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动淘汰一批已过期的key

Redis会把有过期时间的key放在一个单独的字典里,默认每100ms检查,是否有过期的key,有过期的key则删除

Redis配置项hz定义了serverCron任务的执行周期,默认每次清理时间为25ms,每次清理会依次遍历所有DB, 从db随机取出20个key,如果过期就删除,如果其中有5个key过期,那么就继续对这个db进行清理,否则开始清理下一个db。

内存不够时,淘汰策略

当执行写入命令时,如果发现内存不够,那么就会按照配置的淘汰策略清理内存

淘汰策略主要由以下几种:

eviction: 不删除,达到内存限制时,执行写入命令时直接返回错误信息。

allkeys-lru: 在所有key中,优先删除最少使用的key(适合请求符合幂定律分布,也就是一些键访问频繁,一部分键访问较少)

allkeys-random: 在所有key中,随机删除一部分key(适合请求分布比较平均)

volatile-lru: 在设置了expire的key中,优先删除最少使用的key

volatile-random: 在设置了expire的key中,随机删除一部分key。

volatile-ttl: 在设置了expire的key中,优先删除剩余时间短的key。

高可用

1.cluster
2.主从
3.哨兵,小规模,中小型公司

演进:

单机———-> 主从复制 ———> 哨兵模式 —-> cluster —->
读写分离、容灾备份 解决单机故障,自动转移

  • 单机版

内存容量有限

处理能力有限

无法高可用

  • 主从复制

特点:

master/slave 角色

master/slave 数据相同

降低 master 读压力在转交从库

问题:

无法保证高可用

没有解决master写的压力

  • 哨兵

特点:

保证高可用

监控各个节点

自动故障迁移

缺点:

主从模式,切换需要时间丢数据

没有解决master写的压力

  • 集群(proxy型)

Twemproxy是一个Twitter开源的一个redis和memcache快速/轻量级代理服务器,Twemproxy是一个快速的单线程代理程序, 支持Memcached ASCII协议和redis协议

特点:

多种hash算法: MD5、CRC16、CRC32、CRC32a、hsieh、murmur、Jenkins

支持失败节点自动删除

后端Sharding 分片逻辑对业务透明,业务方的读写方式和操作单个Redis一致

缺点:

增加了新的proxy,需要维护其高可用
failover 逻辑需要自己实现,其本身不能支持故障的自动转移可扩展性差,进行扩缩容都需要手动干预

  • 集群(redis cluster)

从redis 3.0之后版本支持redis-cluster集群,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态, 每个节点都和其他所有节点连接。

特点:

无中心结构(不存在哪个节点影响性能瓶颈),少了proxy层

数据按照slot存储分布在多个节点,节点间数据共享,可动态调整数据分布

可扩展性,可线性扩展到1000个节点,节点可动态添加和删除

高可用性,部分节点不可用时,集群仍可用,通过添加Slave做备份数据副本

实现故障自动failover,节点之间通过gossip协议交换状态信息,用投票机制完成Slave到Master的角色提升

缺点:

资源隔离性较差,容易出现相互影响的情况

数据通过异步复制,不保证数据的强一致性

Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务;

Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储;

同步机制

Redis可以使用主从同步、从从同步; 第一次同步时,主节点bgsave,同时将后续修改操作记录到内存buffer, 待完成后将rdb文件全量同步到复制节点;

redis分布式锁

先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放;

如果在setnx之后执行expire之前进程意外crash?

可以同时把setnx和expire合成一条指令来用

redis异步队列

一般使用list结构作为队列,rpush生产消息,lpop消费消息; 当lpop没有消息的时候,要适当sleep一会再重试;

使用pub/sub主题订阅模式实现1:N消息队列;但在消费者下线的情况下,生产的消息会丢失;

Redis事务

Redis 通过 MULTI 、 DISCARD 、 EXEC 和 WATCH 四个命令来实现事务功能;

事务提供了一种“将多个命令打包, 然后一次性、按顺序地执行”的机制, 并且事务在执行的期间不会主动中断:服务器在执行完事务中的所有命令之后,才会继续处理其他客户端的其他命令;

MULTI 命令的执行标记着事务的开始;当客户端进入事务状态之后, 服务器在收到来自客户端的命令时, 不会立即执行命令, 而是将这些命令全部放进一个事务队列里, 然后返回 QUEUED , 表示命令已入队;

当事务队列里的所有命令被执行完之后, EXEC 命令会将回复队列作为自己的执行结果返回给客户端, 客户端从事务状态返回到非事务状态, 至此, 事务执行完毕;

DISCARD 命令用于取消一个事务, 它清空客户端的整个事务队列, 然后将客户端从事务状态调整回非事务状态, 最后返回字符串 OK 给客户端, 说明事务已被取消;

WATCH 命令用于在事务开始之前监视任意数量的键: 当调用 EXEC 命令执行事务时, 如果任意一个被监视的键已经被其他客户端修改了, 那么整个事务不再执行, 直接返回失败;

常见问题

缓存穿透

查询不存在数据的现象我们称为缓存穿透

查询缓存—->没有—->数据库查询—->回写缓存

解决办法

1.为这些key对应的值设置为null 丢到缓存里面去。后面再出现查询这个key 的请求的时候,直接返回null 。设置过期时间。

2.在缓存之前在加一层 BloomFilter ,在查询的时候先去 BloomFilter 去查询 key 是否存在,如果不存在就直接返回,存在再走查缓存 -> 查 DB。 针对key异常多、请求重复率比较低的数据(攻击),我们就没有必要进行缓存,使用第二种方案直接过滤掉。 而对于空数据的key有限的,重复率比较高的,我们则可以采用第一种方式进行缓存。

缓存击穿

在平常高并发的系统中,大量的请求同时查询一个key时, 此时这个key正好失效了,就会导致大量的请求都打到数据库上面去。

这种现象我们称为缓存击穿。

影响

会造成某一时刻数据库请求量过大,压力剧增。

解决办法

多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个 互斥锁 来锁住它。 其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。 后面的线程进来发现已经有缓存了,就直接走缓存。

缓存雪崩

缓存雪崩的情况是说,当某一时刻发生大规模的缓存失效的情况, 比如你的缓存服务宕机了,会有大量的请求进来直接打到DB上面。

结果就是DB撑不住,挂掉

解决办法

1.事前:使用集群缓存,保证缓存服务的高可用

2.事中:ehcache本地缓存 + Hystrix限流&降级,避免MySQL被打死

3.事后:开启Redis持久化机制,尽快恢复缓存集群

缓存与数据库不一致问题

多数情况下,使用缓存的策略是:

读请求: 先读缓存,缓存没有命中就读数据库,然后同步到缓存

写请求: 1.先删除缓存再更新数据库–可能读到缓存脏数据; 2.先更新数据库再删除缓存–看着没什么问题,除非更新数据库之后,宕机,缓存没来得及更新(概率很小),一直是脏数据

加入缓存后,导致的不一致影响时间会很长,并且最终也不会达到一致;

如果是Redis集群,或者主从模式,由于Redis复制存在一定时延,也有可能导致数据不一致;

解决思路

1.延时双删

写库前后都进行缓存删除操作;

2.异步淘汰

通过读取binlog的方式,异步淘汰缓存;

业务代码侵入性低,缩小缓存与数据库不一致的时间

常见性能问题

1.master最好不要写内存快照,或者AOF持久化

会阻塞主线程的工作,当快照比较大时对性能的影响很大,会间断性暂停服务;

AOF持久化对性能影响最小,但随着AOF文件不断增大,会影响master重启的恢复速度;

master最好不要做任何持久化工作,如果数据比较关键,可以某个slave开启AOF备份数据,每秒同步一次;

2.master和slave最好在同一局域网内,主从复制性能会更好;

3.使用keys命令可以扫出指定模式的key列表,但会导致线程阻塞一段时间, 线上服务会停顿,直到指令执行完毕,服务才能恢复; 可以使用scan命令,scan指令可以无阻塞的取出指定模式的key列表,但是会有一定的重复率; 可以在客户端做一次去重;

4.如果大量的key过期时间设置的过于集中,在过期的那个时间点,Redis可能会出现短暂的卡顿现象; 一般需要在时间上加一个随机值,使得时间分散一些;

5.如何删除一个大key 非字符串的bigkey,不要使用 del 删除,使用 hscan、sscan、zscan 方式渐进式删除; Redis 4.0 推出了一个重要命令 UNLINK,用来拯救 del 删大key的困境:在所有命名空间中把 key 删掉,立即返回,不阻塞, 后台线程执行真正的释放空间的操作;

Redis常见命令

1.连接操作相关的命令

quit:关闭连接(connection)
auth:简单密码认证

2.对value操作的命令

exists(key):确认一个key是否存在
del(key):删除一个key
type(key):返回值的类型
keys(pattern):返回满足给定pattern的所有key
randomkey:随机返回key空间的一个key
rename(oldname, newname):将key由oldname重命名为newname,若newname存在则删除newname表示的key
dbsize:返回当前数据库中key的数目
expire:设定一个key的活动时间(s)
ttl:获得一个key的活动时间
select(index):按索引查询
move(key, dbindex):将当前数据库中的key转移到有dbindex索引的数据库
flushdb:删除当前选择数据库中的所有key
flushall:删除所有数据库中的所有key

3.对String操作的命令

set(key, value):给数据库中名称为key的string赋予值value
get(key):返回数据库中名称为key的string的value
getset(key, value):给名称为key的string赋予上一次的value
mget(key1, key2,…, key N):返回库中多个string(它们的名称为key1,key2…)的value
setnx(key, value):如果不存在名称为key的string,则向库中添加string,名称为key,值为value
setex(key, time, value):向库中添加string(名称为key,值为value)同时,设定过期时间time
mset(key1, value1, key2, value2,…key N, value N):同时给多个string赋值,名称为key i的string赋值value i
msetnx(key1, value1, key2, value2,…key N, value N):如果所有名称为key i的string都不存在,则向库中添加string,名称key i赋值为value i
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的子串

4.对List操作的命令

压缩列表(ziplist)/双向循环链表

rpush(key, value):在名称为key的list尾添加一个值为value的元素
lpush(key, value):在名称为key的list头添加一个值为value的 元素
llen(key):返回名称为key的list的长度
lrange(key, start, end):返回名称为key的list中start至end之间的元素(下标从0开始,下同)
ltrim(key, start, end):截取名称为key的list,保留start至end之间的元素
lindex(key, index):返回名称为key的list中index位置的元素
lset(key, index, value):给名称为key的list中index位置的元素赋值为value
lrem(key, count, value):删除count个名称为key的list中值为value的元素。count为0,删除所有值为value的元素,count>0从头至尾删除count个值为value的元素,count<0从尾到头删除|count|个值为value的元素。 lpop(key):返回并删除名称为key的list中的首元素 rpop(key):返回并删除名称为key的list中的尾元素 blpop(key1, key2,… key N, timeout):lpop命令的block版本。即当timeout为0时,若遇到名称为key i的list不存在或该list为空,则命令结束。如果timeout>0,则遇到上述情况时,等待timeout秒,如果问题没有解决,则对keyi+1开始的list执行pop操作。
brpop(key1, key2,… key N, timeout):rpop的block版本。参考上一命令。
rpoplpush(srckey, dstkey):返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部

对Hash操作的命令

压缩列表/散列表

hset(key, field, value):向名称为key的hash中添加元素field<—>value
hget(key, field):返回名称为key的hash中field对应的value
hmget(key, field1, …,field N):返回名称为key的hash中field i对应的value
hmset(key, field1, value1,…,field N, value N):向名称为key的hash中添加元素field i<—>value i
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

对Set操作的命令

有序数组/散列表

sadd(key, member):向名称为key的set中添加元素member
srem(key, member) :删除名称为key的set中的元素member
spop(key) :随机返回并删除名称为key的set中一个元素
smove(srckey, dstkey, member) :将member元素从名称为srckey的集合移到名称为dstkey的集合
scard(key) :返回名称为key的set的基数
sismember(key, member) :测试member是否是名称为key的set的元素
sinter(key1, key2,…key N) :求交集
sinterstore(dstkey, key1, key2,…key N) :求交集并将交集保存到dstkey的集合
sunion(key1, key2,…key N) :求并集
sunionstore(dstkey, key1, key2,…key N) :求并集并将并集保存到dstkey的集合
sdiff(key1, key2,…key N) :求差集
sdiffstore(dstkey, key1, key2,…key N) :求差集并将差集保存到dstkey的集合
smembers(key) :返回名称为key的set的所有元素
srandmember(key) :随机返回名称为key的set的一个元素

对zset(sorted set)操作的命令

跳表/压缩列表

zadd(key, score, member):向名称为key的zset中添加元素member,score用于排序。如果该元素已经存在,则根据score更新该元素的顺序。
zrem(key, member) :删除名称为key的zset中的元素member
zincrby(key, increment, member) :如果在名称为key的zset中已经存在元素member,则该元素的score增加increment;否则向集合中添加该元素,其score的值为increment
zrank(key, member) :返回名称为key的zset(元素已按score从小到大排序)中member元素的rank(即index,从0开始),若没有member元素,返回“nil”
zrevrank(key, member) :返回名称为key的zset(元素已按score从大到小排序)中member元素的rank(即index,从0开始),若没有member元素,返回“nil”
zrange(key, start, end):返回名称为key的zset(元素已按score从小到大排序)中的index从start到end的所有元素
zrevrange(key, start, end):返回名称为key的zset(元素已按score从大到小排序)中的index从start到end的所有元素
zrangebyscore(key, min, max):返回名称为key的zset中score >= min且score <= max的所有元素 zcard(key):返回名称为key的zset的基数 zscore(key, element):返回名称为key的zset中元素element的score zremrangebyrank(key, min, max):删除名称为key的zset中rank >= min且rank <= max的所有元素 zremrangebyscore(key, min, max) :删除名称为key的zset中score >= min且score <= max的所有元素
zunionstore / zinterstore(dstkeyN, key1,…,keyN, WEIGHTS w1,…wN, AGGREGATE SUM|MIN|MAX):对N个zset求并集和交集,并将最后的集合保存在dstkeyN中。对于集合中每一个元素的score,在进行AGGREGATE运算前,都要乘以对于的WEIGHT参数。如果没有提供WEIGHT,默认为1。默认的AGGREGATE是SUM,即结果集合中元素的score是所有集合对应元素进行SUM运算的值,而MIN和MAX是指,结果集合中元素的score是所有集合对应元素中最小值和最大值。

持久化

save:将数据同步保存到磁盘
bgsave:将数据异步保存到磁盘
lastsave:返回上次成功将数据保存到磁盘的Unix时戳
shundown:将数据同步保存到磁盘,然后关闭服务

远程服务控制

info:提供服务器的信息和统计
monitor:实时转储收到的请求
slaveof:改变复制策略设置
config:在运行时配置Redis服务器

管理命令

启动Redis

redis-server [–port 6379]

连接Redis

./redis-cli [-h 127.0.0.1 -p 6379]

停止Redis

redis-cli shutdown

kill redis-pid

测试连通性

ping

refs

https://zhuanlan.zhihu.com/p/130923806




本博客所有文章采用的授权方式为 自由转载-非商用-非衍生-保持署名 ,转载请务必注明出处,谢谢。
声明:
本博客欢迎转发,但请保留原作者信息!
博客地址:邱文奇(qiuwenqi)的博客;
内容系本人学习、研究和总结,如有雷同,实属荣幸!
阅读次数:

文章评论

comments powered by Disqus


章节列表