侧边栏壁纸
  • 累计撰写 251 篇文章
  • 累计创建 138 个标签
  • 累计收到 16 条评论

目 录CONTENT

文章目录

Redis Studing

Sherlock
2015-05-20 / 0 评论 / 0 点赞 / 1051 阅读 / 11903 字 / 编辑
温馨提示:
本文最后更新于 2023-10-09,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

一.Redis的安装和使用

1、什么 Redis

REmote DIctionary Server,简称 Redis,可以直接理解为远程字典服务,是一个类似于Memcached的Key-Value存储系统。相比Memcached,它支持更丰富的数据结构,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型),并提供了数据持久化机制,在某些场景下,你完全可以把它当做非关系型数据库来使用。它是一个高性能的存储系统,能支持超过 100K+ 每秒的读写频率。同时还支持消息的发布/订阅,从而让你在构建高性能消息队列系统时多了另一种选择。

2、Redis VS Memcached,为啥选择用Redis作为缓存中间件?

Memcached 的特点

  • 处理请求时使用多线程异步 IO 的方式,可以合理利用 CPU 多核的优势,性能非常优秀;
  • 功能简单,使用内存存储数据;
  • 内存结构以及钙化问题

Memcached采用LRU淘汰算法,在内存容量满时踢出过期失效和LRU数据,为新数据腾出内存空间。不过该淘汰算法在内存空间不足以分配新的Slab情况下,只会在同一类Slab内部踢出数据。 即当某个Slab容量满,且内存不足够分配新的Slab,只会在相同Slab内部踢出数据,而不会挪用或者踢出其他Slab的数据。这种局部剔除数据的淘汰算法带来一个问题:Slab钙化

  • 对缓存的数据可以设置失效期,过期后的数据会被清除;
  • 失效的策略采用延迟失效,就是当再次使用数据时检查是否失效;
  • 当容量存满时,会对缓存中的数据进行剔除,剔除时除了会对过期 key 进行清理,还会按 LRU 策略对数据进行剔除。

Memcached 的一些限制

这些限制在现在的互联网场景下很致命,成为大家选择Redis、MongoDB的重要原因:

  • key 不能超过 250 个字节;
  • value 不能超过 1M 字节;
  • key 的最大失效时间是 30 天;
  • 只支持 K-V 结构,不提供持久化和主从同步功能。

Redis 支持复杂的数据结构

Redis 相比 Memcached 来说,拥有更多的数据结构,能支持更丰富的数据操作。如果需要缓存能够支持更复杂的结构和操作, Redis 会是不错的选择。

Redis 原生支持集群模式

在 redis3.x 版本中,便能支持 Cluster 模式,而 Memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据。

性能对比

由于 Redis 只使用单核,而 Memcached 可以使用多核,所以平均每一个核上 Redis 在存储小数据时比 Memcached 性能更高。 而在 100k 以上的数据中,Memcached 性能要高于 Redis,虽然 Redis 最近也在存储大数据的性能上进行优化,但是比起 Remcached,还是稍有逊色。

此部分来自《吊打面试官》系列-Redis常见面试题 by 敖丙,《吊打面试官》系列-Redis双写一致性、并发竞争、线程模型,感谢~

2、安装

Redis装起来,实在是过于简单,让我几乎“无从下手”。因为连configure文件都不需要,你只需要做个makemake install就好。我在这里下载的是redis-3.0.1版. 如果报找不到gc++, 执行以下命令即可。

yum -y install make gcc gcc-c++ ncurses-devel 
yum -y install zlib zlib-devel 

如果报 error: jemalloc/jemalloc.h: No such file or directory 使用以下命令即可编译通过

make MALLOC=libc

关于分配器 allocator, 如果有 MALLOC 这个环境变量,会用这个环境变量的 去建立Redis。而且 libc 并不是默认的 分配器, 默认的是 jemalloc, 因为 jemalloc 被证明有比libc更少的 fragmentation problems 。但是如果你又没有 jemalloc 而只有 libc 当然 make 出错。 所以加这么一个参数。

3、运行

  • 1.启动服务,先进入 src 目录,然后执行 redis-server。(6379 是 redis 默认端口)
  • 2.也可以把默认的配置文件——redis.conf拷贝到固定的目录下,例如:/etc/redis/目录下,然后执行命令
redis-server /etc/redis/redis.conf

4、测试

通过客户端命令redis-cli访问Redis

set name sherlock
get name

进行数据测试:

redis-benchmark -l

5、关闭

可通过客户端命令redis-cli完成Redis关闭操作,当然,也可以通过 kill 命令来关闭服务。

redis-cli shutdown

6、调优

1) /etc/sysctl.conf

刚才启动后有以下警告:

WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.

需要修改/etc/sysctl.conf文件:

末尾追加**vm.overcommit_memory=1**

然后执行**sysctl vm.overcommit_memory=1**,使之生效:

2) /proc/sys/vm/overcommit_memory

为了调整内存分配策略,需要配置/proc/sys/vm/overcommit_memory

  • 0:表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
  • 1:表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
  • 2:表示内核允许分配超过所有物理内存和交换空间总和的内存

默认为0,如果内存情况比较紧张的话,设为1:

echo 1 > /proc/sys/vm/overcommit_memory

3) redis.conf

前面启动Redis后,总是在命令行里不断跳着各种日志,很麻烦。即便通过**&**,令其后台运行,也无济于事。这就需要修改redis.conf,以Daemo模式运行!

redis.conf参数:

  • daemonize:是否以后台daemon方式运行
  • pidfile:pid文件位置
  • port:监听的端口号
  • timeout:请求超时时间
  • loglevel:log信息级别
  • logfile:log文件位置
  • databases:开启数据库的数量
  • save * *:保存快照的频率,第一个*表示多长时间(秒级),第三个*表示执行多少次写操作。在一定时间内执行一定数量的写操作时,自动保存快照。可设置多个条件。
  • rdbcompression:是否使用压缩
  • dbfilename:数据快照文件名(只是文件名,不包括目录)
  • dir:数据快照的保存目录(这个是目录)
  • appendonly:是否开启appendonlylog,开启的话每次写操作会记一条log,这会提高数据抗风险能力,但影响效率。
  • appendfsync:appendonlylog如何同步到磁盘(三个选项,分别是每次写都强制调用fsync、每秒启用一次fsync、不调用fsync等待系统自己同步)
  • slaveof <masterip> <masterport> :主从配置,在redis-slave上配置master的ip port,即可。

例如,我们可以修改为如下方式:

daemonize yes #守护进程模式

save 60 1000 #当时间间隔超过60秒,或存储超过1000条记录时,进行持久化。

maxmemory 256mb #分配256MB内存

PS:切记,一定要设定maxmemmory,且配置大小要小于物理内存,留有足够的内存供系统使用。

4) TCP somaxconn配置修改

刚才启动后还有以下警告:

17366:M 26 May 15:28:57.245 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.

/proc/sys/net/core/somaxconn 这个参数,linux中内核的一个不错的参数somaxconn

对于一个TCP连接,Server与Client需要通过三次握手来建立网络连接.当三次握手成功后,我们可以看到端口的状态由LISTEN转变为ESTABLISHED,接着这条链路上就可以开始传送数据了.

每一个处于监听(Listen)状态的端口,都有自己的监听队列.监听队列的长度,与如下两方面有关:

  • somaxconn参数.
  • 使用该端口的程序中listen()函数.

关于somaxconn参数:

  定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数,默认值为128,具体信息为:

  Purpose:
  Specifies the maximum listen backlog.
  Values:
  Default: 128 connections
  Range: 0 to MAXSHORT
  Type: Connect
  Diagnosis:
  N/A
  Tuning
  Increase this parameter on busy Web servers to handle peak connection rates.

看下FREEBSD的解析:

  限制了接收新 TCP 连接侦听队列的大小。对于一个经常处理新连接的高负载 web服务环境来说,默认的 128 太小了。大多数环境这个值建议增加到 1024 或者更多。 服务进程会自己限制侦听队列的大小(例如 sendmail(8) 或者 Apache),常常在它们的配置文件中有设置队列大小的选项。大的侦听队列对防止拒绝服务 DoS 攻击也会有所帮助。

我们可以通过,

echo 511 >/proc/sys/net/core/somaxconn

来修改这个参数。

5) 下面介绍另外一种配置方式,通过命令行来配置。

假如说我们不想修改配置文件来启动指定端口号的redis服务,我们可以在终端上执行下面的命令:

redis-server --port 6379 --daemonize yes

redis-cli -p 6379

但我还是推荐使用配置文件的方式。

如果在生产环境里面需要修改某些配置项,但我们又不想停掉服务,怎么办?

Redis允许在运行的过程中,在不重启服务器的情况下更改服务器配置,同时也支持 使用特殊的CONFIG SETCONFIG GET命令用编程方式查询并设置配置。

二.Redis 主从复制

Redis 的主从复制配置非常容易,但我们先来了解一下它的一些特性。

  • 1.redis 使用异步复制。从 redis 2.8 开始,slave 也会周期性的告诉 master 现在的数据量。可能只是个机制,用途应该不大。

  • 2.一个 master 可以拥有多个 slave,废话,这也是业界的标配吧。

  • 3.slave 可以接收来自其他 slave 的连接。意思是不是就是说 slave 在接收其他的slave的连接之后成为 master ?等下我们来验证。

  • 4.redis 复制在 master 这一端是非阻塞的,也就是说在和 slave 同步数据的时候,master 仍然可以执行客户端的操作命令而不受其影响。这点都不能保证,要你干嘛?

  • 5.redis 复制在 slave 这一端也是非阻塞的。在配置文件里面有 slave-serve-stale-data 这一项,如果它为 yes ,slave 在执行同步时,它可以使用老版本的数据来处理查询请求,如果是 no ,slave 将返回一个错误。在完成同步后,slave 需要删除老数据,加载新数据,在这个阶段,slave 会阻止连接进来。

  • 6.Replication can be used both for scalability, in order to have multiple slaves for read-only queries (for example, heavy SORT operations can be offloaded to slaves), or simply for data redundancy.这句话我也没理解什么意思。

  • 7.使用复制可以避免 master 因为需要把全部的数据集写入磁盘而造成的开销,因此可以把 master 中 save 配置项全部注释掉,不让它进行保存,然后配置 slave ,让 slave 保存。虽然有这个特性,但是我们好像一般不这么做。

好吧,我们做几个例子练习一下。

先打开三个终端,然后起三个实例,分别用三个 client 去连接它们:

master

$ ./redis-server --port 10000 --daemonize yes

$ ./redis-cli -p 10000

slave 01:

$ ./redis-server --port 10001 --daemonize yes

$ ./redis-cli -p 10001

slave 02:

$ ./redis-server --port 10002 --daemonize yes

$ ./redis-cli -p 10002

上面只是让它们的实例启动了并用客户端去连接它,并没有设置主从关系。在 slave 01slave 02 上执行下面的命令:

127.0.0.1:10001> slaveof 127.0.0.1 10000

OK

127.0.0.1:10001>

这样就设置好了主从关系。我们来试试有没有效果。

127.0.0.1:10001> get name

(nil)

127.0.0.1:10001>

这个时候是没有值的。

master 上执行:

127.0.0.1:10000> set name sherlock

OK

127.0.0.1:10000>

然后看看 slave 上有没有:

127.0.0.1:10001> get name

"sherlock"

127.0.0.1:10001>

127.0.0.1:10002> get name

"sherlock"

127.0.0.1:10002>

有了,是不是很easy ?已经有了感性的认识,我们来介绍一下它的原理吧。

当你设置了主从关系后,slave 在第一次连接或者重新连接 master 时,slave 都会发送一条同步指令给master

master 接到指令后,开始启动后台保存进程保存数据,接着收集所有的数据修改指令。后台保存完了,master 就把这份数据发送给 slaveslave 先把数据保存到磁盘,然后把它加载到内存中,master 接着就把收集的数据修改指令一行一行的发给 slaveslave 接收到之后重新执行该指令,这样就实现了数据同步。

slave 在与 master 失去联系后,自动的重新连接。如果 master 收到了多个 slave 的同步请求,它会执行单个后台保存来为所有的 slave 服务。

一旦 masterslave 在失去联系并重新连接上,总是会重新进行一次完整的同步。不过从 redis 2.8 开始,只是部分重新同步也是可以的。具体请大家参考官方文档。 #三.主从备份 在从服务器上执行下列命令:

$备份

redis-cli save

$关闭redis服务器

redis-cli shutdown

然后,拷贝数据目录下的rdb文件。

参考

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区