分布式缓存Redis_1 Redis环境搭建和数据结构

                                         分布式缓存Redis

                                         1 Redis环境搭建和数据结构

                                                                                                                                                                                                田超凡

                                                                                                                                                                                           20191118

 

转载请注明原作者

1 Redis框架介绍

Redis是一个完全开源免费的高性能非关系型数据库(nosql),主要用来做分布式缓存和分布式数据共享,底层基于NIO多路IO复用机制实现IO处理,基于Linux Epoll选择器可以实现单线程处理多个Redis客户端发送的IO处理请求,实现多路IO复用,在高并发环境下的数据存储和数据共享方面性能优越。

Redis官方是没有Windows版本的,只有Linux版本。这是因为Redis基于NIO多路IO复用实现,而在Windows系统中NIO选择器使用的是Selector,对于IO并发处理使用的是轮询机制实现,容易产生Selector空轮询,最终导致CPU 100%。在Linux系统中NIO选择器使用的是Epoll,Epoll基于事件监听回调机制来实现的多路IO复用,对于IO并发处理而言,客户端每次发送的IO处理请求都会被加入事件监听,不使用轮询来实现,避免了空轮训问题,并且这种基于事件监听回调的方式实现多路IO复用,执行效率也更加优越。

一个Redis服务器默认初始化16个库用来存放数据(0-15),可以在redis.conf配置文件中修改配置调整数据库初始个数:databases=初始化库的数量(默认16)

 

2 NIO模型和多路IO复用

NIO模型指的是同步非阻塞式IO处理,使用同步的方式来并发处理客户端发送的IO处理请求,使用轮询的机制实现,不会导致线程阻塞。

NIO模型主要有三部分组成:选择器Selector、通道Channel、缓冲区Buffer

多路IO复用指的是服务器使用单线程来批量处理多个客户端发送的IO处理请求,共用同一个IO处理操作,这样做的好处就是可以很好的解决客户端高并发访问下的服务器IO处理性能问题,是NIO同步非阻塞模型的一种具体实现方式。

NIO的处理过程我认为可以这样理解,当客户端和服务器建立TCP链接之后,每个客户端和服务器的连接都会在NIO中初始化为通道Channel,服务器使用Selector选择器统一存储这些通道Channel,根据不同的选择器实现策略(Selector轮询或者Epoll事件监听回调)来使用单线程批量处理IO操作请求,最终实现多路IO复用,减轻服务器IO处理压力,提高IO操作性能。

 

3 Redis单线程NIO处理

Redis的底层采用Nio中的多路IO复用的机制,能够非常好的支持这样的并发,从而保证线程安全问题。

但是NIO在不同的操作系统上选择器的实现方式有所不同,在我们windows操作系统使用select实现轮训时间复杂度是为o(n),而且还存在空轮训的情况,效率非常低, 其次是默认对我们轮训的数据有一定限制,所以支持上万的tcp连接是非常难。

所以在linux操作系统采用Epoll实现事件驱动回调,不会存在空轮训的情况,只对活跃的 socket连接实现主动回调,这样在性能上有大大的提升,所以时间复杂度是为o(1)

注意:windows操作系统NIO选择器是Selector,linux系统NIO选择器是Epoll

所以为什么nginx、redis都能够非常高支持高并发,最终都是因为基于linux中的多路IO复用机制Epoll

 

4 Redis应用场景

(1).Token令牌的生成

(2).短信验证码Code

(3).缓存查询数据

(4).网页计数器

(5).分布式锁

(6).延迟操作

 

5 Linux环境下安装Redis

环境安装Redis

  1. 上传Redis的安装包

redis-5.0.6.tar.gz

  1. 解压我们的Redis安装包

tar -zxvf redis-5.0.6.tar.gz

  1. mkdir /usr/redis
  2. make install PREFIX=/usr/redis
  3. 启动Redis cd /usr/redis/bin     ./redis-server

环境核心配置 

将Redis设置为后台启动

cp /usr/redis-5.0.6/redis.conf    /usr/redis/bin

vi redis.conf  daemonize yes

./redis-server ./redis.conf 重启启动Redis

ps aux | grep 'redis' 查看redis服务运行进程id

设置Redis账号密码

搜索:# requirepass foobared

requirepass 123456

客户端连接:auth 123456

 

设置Redis允许ip访问

注释掉bind 127.0.0.1

protected-mode no ###允许外界访问

 

Redis客户端连接Redis服务器

./redis-cli 默认连接本机(127.0.0.1:6379) Redis服务

./redis-cli -h 192.168.212.155 -p 6379 -a 123456 连接redis服务器

 

6 Redis基本数据类型

String类型、Hash类型、Set类型、Sorted-Sets类型、List类型

 

String类型

String是redis最基本的类型,一个key对应一个value,String类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象, Sring类型是Redis最基本的数据类型,一个键最大能存储512MB。

 

set name mayikt

get name mayikt

 

Hash类型

每一个元素都是一个<Key,Value>键值对

  我们可以将Redis中的Hash类型看成具有<key,<key1,value>>,其中同一个key可以有多个不同key值的<key1,value>,所以该类型非常适合于存储值对象的信息。如Username、Password和Age等。如果Hash中包含很少的字段,那么该类型的数据也将仅占用很少的磁盘空间。

hmset mayikt zhangsan 21

hgetall mayikt

 

List类型

有序集合(按加入顺序),元素可以重复

Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)

lpush mayiktlist xiaoming xiaojun xiaoxiao

lrange mayiktlist 0 10

 

Redis 集合(Set)

无序集合,元素唯一

Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

sadd mayiktset mayikt mayikt02 mayikt03

smembers mayiktset

 

Redis 有序集合(sorted set)

有序集合(按分数排序)元素唯一,但分数(score)却可以重复。

Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。

不同的是每个元素都会关联一个double类型的分数。redis正是通过Sorted Set集合中每个元素的分数来为集合中的成员进行从小到大的排序。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

zadd mayikt 1 redis

zadd mayiktsets  1 redis

zrange mayiktsets 0 10 withscores

 

7 SpringBoot整合Redis案例

 

案例:Redis客户端集成SpringBoo,在Redis存放一个对象,使用JSON序列化与反序列化

Maven依赖


<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
</parent>
<dependencies>
    <!-- 集成commons工具类 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
    </dependency>
    <!-- 集成lombok 框架 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <!-- fastjson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.30</version>
    </dependency>
    <!-- SpringBoot-整合Web组件 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
</dependencies>
<!-- 管理依赖 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Finchley.M7</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

 

工具类

@Component
public class RedisUtils {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public void setString(String key, String value) {
        setString(key, value, null);
    }

    public void setString(String key, String value, Long timeOut) {
        stringRedisTemplate.opsForValue().set(key, value);
        if (timeOut != null) {
            stringRedisTemplate.expire(key, timeOut, TimeUnit.SECONDS);
        }
    }

    public String getString(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }
}

 

 

控制层

@RestController
public class IndexController {
    @Autowired
    private RedisUtils redisUtils;

    @RequestMapping("/setRedis")
    public void setRedisKey(UserEntity userEntity) {
        redisUtils.setString("userEntity", JSONObject.toJSONString(userEntity));
    }

    @RequestMapping("/getRedis")
    public UserEntity setRedisKey() {
        String userEntityJson = redisUtils.getString("userEntity");
        UserEntity userEntity = JSONObject.parseObject(userEntityJson, UserEntity.class);
        return userEntity;
    }
}

 

 

配置文件

spring:
  redis:
    host: 192.168.212.155

    port: 6379
    password: 123456

 

 

转载请注明原作者

发布了100 篇原创文章 · 获赞 10 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq_30056341/article/details/103116255