redis相关学习

1. redis介绍

1.1. 什么是redis

​ Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库。它通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止Redis支持的键值数据类型如

下:

字符串类型

散列类型 (对应Java中的Object,它主要用来存储对象)

列表类型 (List)

集合类型 (Set)

有序集合类型。 (TreeSet)

1.2. redis的应用场景

缓存(数据查询、短连接、新闻内容、商品内容等等)。(最多使用)

分布式集群架构中的session分离。

聊天室的在线好友列表。

任务队列。(秒杀、抢购、12306等等)

应用排行榜。

网站访问统计。

数据过期处理(可以精确到毫秒)

2. Redis的安装

2.1 在Windows上安装

2.2 在Linux上安装

su root : 切换到root

1、cd /etc/sysconfig/network-scripts中找到为为ifcfg-eth0的一个。

2、使用命令vim ifcfg-eth0 命令进入到命令行模式下

3、修改相应的ip和修改启动项为yes,按下Esc退到命令行,再按下:wq保存退出

4、service network restart重启网络服务即可。

ifconfig eth0 192.168.125.100

重启网络service network restart

ifup eth0 : 激活连接

1、vim /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
search localdomain

2、然后重启网卡:使用命令: service network restart

redis是C语言开发,建议在linux上运行,示例使用CentOS7作为安装环境。

  1. 安装redis需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没有gcc环境,需要安装gcc

    yum install gcc-c++
    

    阿里云的CentOS7默认已经内置了gcc,可以跳过这一步

  2. 下载redis

    从官网下载

    http://download.redis.io/releases/redis-5.0.5.tar.gz

    将redis-5.0.5.tar.gz拷贝任意路径下,如 /home/john/opt/

  3. 解压源码

    cd /home/john/opt/
    tar -zxvf redis-3.0.0.tar.gz  
    
  4. 进入解压后的目录进行编译安装

    cd /home/john/opt/redis-5.0.5/src
    make # 编译源代码
    make install  # 安装
    # 上面两步也可以直接通过 make && make install两步并一步执行
    

    Redis默认的安装目录是/usr/local/bin, 我们在执行make install命令时添加prefix参数可修改默认安装位置,如: make PREFIX=/usr/local/redis install

3. redis启动

redis.conf是redis的配置文件,默认在redis源码包解压后的根目录有一份redis.conf文件,我们可将其拷贝一份到上一步中redis的安装目录

cd /home/john/opt/redis-5.0.5/src
cp redis.conf /usr/local/bin

我们装完redis以后,默认的安装路径是/usr/local/bin,系统会自动来此目录寻找命令,所以我们不需要在配置环境变量,在任意目录都可以使用redis相关的命令,如redis-server、redis-cli

3.1. 前端模式启动

启动命令:

redis-server /usr/local/bin/redis.conf

通过上面的命令启动,redis将以前端模式启动,前端模式启动的缺点是ssh命令窗口关闭则redis-server程序结束,不推荐使用此方法。

3.2. 后端模式启动

3.2.1 开启远程连接

  • 注释掉 bind 127.0.0.1这行
  • 关闭保护模式 将protected-mode yes 改成 protected-mode no

3.2.2 添加密码验证

放开 # requirepass foobared 这行注释,将后面的foobared改成你自己需要设置的密码

客户端连接时,需要添加-a 参数指定密码才能连上来。

3.2.3 开启后台守护进程运行模式

将 # daemonize no 这行放开注释, 并且改成 yes, Redis server将以后台方式运行。

3.2.4 指定日志文件

将 logfile “” 改成 logfile “你需要的redis日志文件名称”, 默认的空字符串代表输出到前端控制台(标准输出)

修改redis.conf配置文件, daemonize yes 以后端模式启动。

3.2.5 启动

启动命令和前端启动一样,只不过控制台不会输出任何信息,而且命令结束,如果没有异常会马上退出。

4. 通过jedis连接redis单机

4.1 SringBoot方式

4.1.1 引入依赖

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-redisartifactId>
dependency>

4.1.2 SpringBoot配置

application.yml

spring:
    redis:
    host: www.taotao.com
#    port: 6379
#    password:
    jedis:
      pool:
        max-idle: 2
        max-wait: 1000ms

4.3. 单实例连接

通过创建单实例jedis对象连接redis服务,如下代码:

@Slf4j
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestRedisClient {

   @Autowired
   private StringRedisTemplate redisTemplate;

   @Test
   public void testRedis() {
      Set<String> keys = redisTemplate.keys("*");
      log.info("操作前存在的keys: " + keys);

      String key = "lanou_F4";

      redisTemplate.opsForList().rightPushAll(key, new String[]{"宋超", "国胜", "国伟", "高飞"});

      long size = redisTemplate.opsForList().size(key);
      log.info("当前"+key+"值的数量: " + size);

      List<String> values = redisTemplate.opsForList().range(key, 0, size);
      log.info("当前" + key +"的值: " + values);

      keys = redisTemplate.keys("*");
      log.info("操作后存在的keys: " + keys);
   }
}

4.3. 外部连接不上redis的解决方法

由于linux防火墙默认开启,redis的服务端口6379并不在开放规则之内,所有需要将此端口开放访问或者关闭防火墙。

关闭防火墙命令:sevice iptables stop

如果是修改防火墙规则,可以修改:/etc/sysconfig/iptables文件

5. redis集群

5.1. 集群原理

5.1.1. redis-cluster架构图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6EE61sGR-1592644866491)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image013.jpg)]

架构细节:

(1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.

(2)节点的fail是通过集群中超过半数的节点检测失效时才生效.

(3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可

(4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value

Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点

5.1.2. redis-cluster投票:容错

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m5ZTfRvB-1592644866505)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image014.jpg)]

(1)领着投票过程是集群中所有master参与,如果半数以上master节点与master节点通信超过(cluster-node-timeout),认为当前master节点挂掉.

(2):什么时候整个集群不可用(cluster_state:fail)?

​ a:如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成集群的slot映射[0-16383]不完成时进入fail状态. ps : redis-3.0.0.rc1加入cluster-require-full-coverage参数,默认关闭,打开集群兼容部分失败.

​ b:如果集群超过半数以上master挂掉,无论是否有slave集群进入fail状态.

ps:当集群不可用时,所有对集群的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down)错误

5.2. ruby环境(Redis5以后的版本不需要依赖Ruby环境)

redis集群管理工具redis-trib.rb依赖ruby环境,首先需要安装ruby环境:

安装ruby

yum install ruby

yum install rubygems

安装ruby和redis的接口程序

拷贝redis-3.0.0.gem至/usr/local下

执行:

gem install /usr/local/redis-3.0.0.gem

5.3. 创建集群:

5.3.1. 集群结点规划

这里在同一台服务器用不同的端口表示不同的redis服务器,如下:

主节点:192.168.101.3:7001 192.168.101.3:7002 192.168.101.3:7003

从节点:192.168.101.3:7004 192.168.101.3:7005 192.168.101.3:7006

在/usr/local下创建redis-cluster目录,其下创建7001、7002。。7006目录,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ucNMLpoN-1592644866507)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image016.jpg)]

将redis安装目录bin下的文件拷贝到每个700X目录内,同时将redis源码目录src下的redis-trib.rb拷贝到redis-cluster目录下。

修改每个700X目录下的redis.conf配置文件:

port XXXX

#bind 192.168.101.3

cluster-enabled yes

pidfile /var/run/redis_6379.pid #这里的进程文件也要修改一下,否则会冲突

5.3.2. 启动每个结点redis服务

进入/usr/local/redis_cluster目录下,编写启动集群脚本:start_redis_cluster.sh

cd /usr/local/redis_cluster

vim start_redis_cluster.sh

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SybRp3so-1592644866511)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image018.jpg)]

编辑完成后,按ESC切换到命令模式, 输入ZZ 或者 :wq保存退出。

启动Redis集群中所有节点:

./start_redis_cluster.sh

查看redis进程:

ps aux | grep redis

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N5QC9HeS-1592644866514)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image020.jpg)]

5.3.3. 执行创建集群命令

Redis 5以下需要使用redis-trib.rb这个Ruby脚本来管理集群,所以需要事先安装Ruby运行环境

执行redis-trib.rb,此脚本是ruby脚本,它依赖ruby环境。

./redis-trib.rb create --replicas 1 192.168.101.3:7001 192.168.101.3:7002 192.168.101.3:7003 192.168.101.3:7004 192.168.101.3:7005 192.168.101.3:7006

Redis 5开始,集群不需要依赖Ruby,官方直接提供了集群管理支持

注意:如果创建redis集群的时候,ip用的是127.0.0.1,那么你在用Java客户端远程操作Redis集群的时候,会死活连不上,一直是报127.0.0.1:7001无法连接

解决办法:创建Redis集群时,用外部可以访问的IP

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bUFt12JY-1592644866516)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image022.jpg)]

说明:

redis集群至少需要3个主节点,每个主节点有一个从节点总共6个节点

–cluster-replicas指定为1表示每个主节点有一个从节点

注意:

如果执行时报如下错误:

[ERR] Node XXXXXX is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0

解决方法是删除生成的配置文件nodes.conf,如果不行则说明现在创建的结点包括了旧集群的结点信息,需要删除redis的持久化文件后再重启redis,比如:appendonly.aof、dump.rdb

创建集群输出如下:

>>> Creating cluster

Connecting to node 192.168.101.3:7001: OK

Connecting to node 192.168.101.3:7002: OK

Connecting to node 192.168.101.3:7003: OK

Connecting to node 192.168.101.3:7004: OK

Connecting to node 192.168.101.3:7005: OK

Connecting to node 192.168.101.3:7006: OK

>>> Performing hash slots allocation on 6 nodes…

Using 3 masters:

192.168.101.3:7001

192.168.101.3:7002

192.168.101.3:7003

Adding replica 192.168.101.3:7004 to 192.168.101.3:7001

Adding replica 192.168.101.3:7005 to 192.168.101.3:7002

Adding replica 192.168.101.3:7006 to 192.168.101.3:7003

M: cad9f7413ec6842c971dbcc2c48b4ca959eb5db4 192.168.101.3:7001

slots:0-5460 (5461 slots) master

M: 4e7c2b02f0c4f4cfe306d6ad13e0cfee90bf5841 192.168.101.3:7002

slots:5461-10922 (5462 slots) master

M: 1a8420896c3ff60b70c716e8480de8e50749ee65 192.168.101.3:7003

slots:10923-16383 (5461 slots) master

S: 69d94b4963fd94f315fba2b9f12fae1278184fe8 192.168.101.3:7004

replicates cad9f7413ec6842c971dbcc2c48b4ca959eb5db4

S: d2421a820cc23e17a01b597866fd0f750b698ac5 192.168.101.3:7005

replicates 4e7c2b02f0c4f4cfe306d6ad13e0cfee90bf5841

S: 444e7bedbdfa40714ee55cd3086b8f0d5511fe54 192.168.101.3:7006

replicates 1a8420896c3ff60b70c716e8480de8e50749ee65

Can I set the above configuration? (type ‘yes’ to accept): yes

>>> Nodes configuration updated

>>> Assign a different config epoch to each node

>>> Sending CLUSTER MEET messages to join the cluster

Waiting for the cluster to join…

>>> Performing Cluster Check (using node 192.168.101.3:7001)

M: cad9f7413ec6842c971dbcc2c48b4ca959eb5db4 192.168.101.3:7001

slots:0-5460 (5461 slots) master

M: 4e7c2b02f0c4f4cfe306d6ad13e0cfee90bf5841 192.168.101.3:7002

slots:5461-10922 (5462 slots) master

M: 1a8420896c3ff60b70c716e8480de8e50749ee65 192.168.101.3:7003

slots:10923-16383 (5461 slots) master

M: 69d94b4963fd94f315fba2b9f12fae1278184fe8 192.168.101.3:7004

slots: (0 slots) master

replicates cad9f7413ec6842c971dbcc2c48b4ca959eb5db4

M: d2421a820cc23e17a01b597866fd0f750b698ac5 192.168.101.3:7005

slots: (0 slots) master

replicates 4e7c2b02f0c4f4cfe306d6ad13e0cfee90bf5841

M: 444e7bedbdfa40714ee55cd3086b8f0d5511fe54 192.168.101.3:7006

slots: (0 slots) master

replicates 1a8420896c3ff60b70c716e8480de8e50749ee65

[OK] All nodes agree about slots configuration.

>>> Check for open slots…

>>> Check slots coverage…

[OK] All 16384 slots covered.

5.4. 停止Redis集群

在/usr/local/redis_cluster目录下,创建脚本文件:stop_redis_cluster.sh

输入一下内容:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hKsTTjde-1592644866519)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image024.jpg)]

5.5. 查询集群信息

集群创建成功登陆任意redis结点查询集群中的节点情况。

客户端以集群方式登陆:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VmhfLPIk-1592644866521)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image026.jpg)]

说明:

./redis-cli -c -h 192.168.101.3 -p 7001 ,其中-c表示以集群方式连接redis,-h指定ip地址,-p****指定端口号

cluster nodes 查询集群结点信息

cluster info 查询集群状态信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4c5R7ZlA-1592644866523)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image028.jpg)]

5.6. 添加主节点

集群创建成功后可以向集群中添加节点,下面是添加一个master主节点

添加7007结点,参考集群结点规划章节添加一个“7007”目录作为新节点。

执行下边命令:

./redis-trib.rb add-node 192.168.101.3:7007 192.168.101.3:7001

Redis 5 添加主节点命令:

语法:redis-cli –cluster add-node **要添加节点的ip:端口 集群中当前存在的任何一个节点的ip**和端口

redis-cli --cluster add-node 10.10.14.166:7006 10.10.14.166:7000

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lJXMX1ML-1592644866525)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image030.jpg)]

查看集群结点发现7007已添加到集群中:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lt6PSy3z-1592644866527)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image032.jpg)]

5.6.1. hash槽重新分配

添加完主节点需要对主节点进行hash槽分配这样该主节才可以存储数据。

redis集群有16384个槽,集群中的每个结点分配自已槽,通过查看集群结点可以看到槽占用情况。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W8UTvhFa-1592644866530)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image034.gif)]

给刚添加的7007结点分配槽:

第一步:连接上集群

./redis-trib.rb reshard 192.168.101.3:7001(连接集群中任意一个可用结点都行)

第二步:输入要分配的槽数量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tQ89M5bF-1592644866532)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image036.jpg)]

输入 500表示要分配500个槽

第三步:输入接收槽的结点id

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uJExelRa-1592644866533)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image038.gif)]

这里准备给7007分配槽,通过cluster nodes查看7007结点id为15b809eadae88955e36bcdbb8144f61bbbaf38fb

输入:15b809eadae88955e36bcdbb8144f61bbbaf38fb

第四步:输入源结点id

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vkXg4drK-1592644866535)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image040.gif)]

这里输入all

第五步:输入yes开始移动槽到目标结点id

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3qFEe4IR-1592644866537)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image042.jpg)]

关于Redis 集群的hash slots相关知识,可以参阅:

redis hash slot(虚拟桶)

Redis Cluster及hash slot 算法

5.7. 添加从节点

集群创建成功后可以向集群中添加节点,下面是添加一个slave从节点。

添加7008从结点,将7008作为7007****的从结点。

./redis-trib.rb add-node --slave --master-id 主节点id 添加节点的ip****和端口 集群中已存在节点ip****和端口

Redis 5 命令:

语法:redis-cli –cluster add-node 要添加节点的ip:端口 **集群中已有master的ip**和端口 --cluster-slave

示例:redis-cli --cluster add-node 10.10.14.166:7006 10.10.14.166:7001 --cluster-slave

执行如下命令:

./redis-trib.rb add-node --slave --master-id cad9f7413ec6842c971dbcc2c48b4ca959eb5db4 192.168.101.3:7008 192.168.101.3:7001

cad9f7413ec6842c971dbcc2c48b4ca959eb5db4 是7007结点的id,可通过cluster nodes查看。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w5CmQfpa-1592644866539)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image044.jpg)]

注意:如果原来该结点在集群中的配置信息已经生成cluster-config-file指定的配置文件中(如果cluster-config-file没有指定则默认为nodes.conf),这时可能会报错:

[ERR] Node XXXXXX is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0

解决方法是删除生成的配置文件nodes.conf,删除后再执行**./redis-trib.rb add-node**指令

查看集群中的结点,刚添加的7008为7007的从节点:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NBI7Xgfg-1592644866541)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image046.jpg)]

5.8. 删除结点:

./redis-trib.rb del-node 127.0.0.1:7005 4b45eb75c8b428fbd77ab979b85080146a9bc017

Redis5以后命令:

redis-cli --cluster del-node ip:port node_id
 
比如:./redis-cli --cluster del-node 10.10.14.166:7006 d3b977fd46386db84fd85b9240deb602087c8617

删除已经占有hash槽的结点会失败,报错如下:

[ERR] Node 127.0.0.1:7005 is not empty! Reshard data away and try again.

需要将该结点占用的hash槽分配出去(参考hash槽重新分配章节)。

5.9. 使用springboot整合RedisCluster

配置文件:application.yml

spring:
   redis:
   host: www.taotao.com
   #    port: 6379
   #    password:
   jedis:
     pool:
       max-idle: 2
       max-wait: 1000ms
   cluster:
     nodes: 10.10.14.166:7001,10.10.14.166:7002,10.10.14.166:7003,10.10.14.166:7004,10.10.14.166:7005,10.10.14.166:7006

测试代码

@Slf4j
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestRedisClient {

  @Autowired
  private StringRedisTemplate redisTemplate;

  @Test
  public void testRedis() {
     Set<String> keys = redisTemplate.keys("*");
     log.info("操作前存在的keys: " + keys);

     String key = "lanou_F4";

     redisTemplate.opsForList().rightPushAll(key, new String[]{"宋超", "国胜", "国伟", "高飞"});

     long size = redisTemplate.opsForList().size(key);
     log.info("当前"+key+"值的数量: " + size);

     List<String> values = redisTemplate.opsForList().range(key, 0, size);
     log.info("当前" + key +"的值: " + values);

     keys = redisTemplate.keys("*");
     log.info("操作后存在的keys: " + keys);
  }
}

6. 系统添加缓存逻辑示例

添加缓存逻辑的原则:缓存逻辑不能影响正常的业务逻辑执行。

6.1. 添加缓存后系统架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s6vcAY5u-1592644866543)(file:///C:\Users\John\AppData\Local\Temp\msohtmlclip1\01\clip_image048.gif)]

gRunner.class)
public class TestRedisClient {

@Autowired
private StringRedisTemplate redisTemplate;

@Test
public void testRedis() {
Set keys = redisTemplate.keys("*");
log.info("操作前存在的keys: " + keys);

  String key = "lanou_F4";

  redisTemplate.opsForList().rightPushAll(key, new String[]{"宋超", "国胜", "国伟", "高飞"});

  long size = redisTemplate.opsForList().size(key);
  log.info("当前"+key+"值的数量: " + size);

  List values = redisTemplate.opsForList().range(key, 0, size);
  log.info("当前" + key +"的值: " + values);

  keys = redisTemplate.keys("*");
  log.info("操作后存在的keys: " + keys);

}
}










# 6.   系统添加缓存逻辑示例

添加缓存逻辑的原则:**缓存逻辑不能影响正常的业务逻辑执行。**

## 6.1. 添加缓存后系统架构

[外链图片转存中...(img-s6vcAY5u-1592644866543)]

​      








你可能感兴趣的:(redis相关学习)