【redis】01-redis简介

时间:2022-07-25
本文章向大家介绍【redis】01-redis简介,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

关系型数据和非关系型数据库有那些:

关系型数据库 非关系型数据库 mysql redis orcale Memcached(不支持持久化) sqlserver

关系型数据和非关系型数据库的区别:

关系型数据库:操作的是IO,效率低 非关系型数据库:操作的是内存,效率高

redis的应用场景:

  1. token 令牌的生成
  2. 短信验证码code(验证码有效期)
  3. 实现数据缓存,经常查询的接口,数据不会经常变化的。做成缓存,当数据更改了,再同步缓存即可
  4. redis实现计数器(redis单线程,线程安全,保证原子性)
  5. 分布式锁
  6. 延迟操作。下单以后不付款,但是库存已经减一了。所以延迟半个小时不付款,就直接取消订单
  7. 分布式消息中间件

为什么redis是单线程,还能支持高并发呢?

因为redis使用的是nio(no-blocking-io)。使用IO多路复用原则,一个线程管理多个redis连接。

nio

我们先看一下nio的伪代码

public class OnceSocketTcpServer {
    static ByteBuffer byteBuffer = ByteBuffer.allocate(512);
    static List<SocketChannel> selectors =  new ArrayList<>();
    public static void main(String[] args) {
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress(8080));
            // 设置为异步接收
            serverSocketChannel.configureBlocking(false);
            while(true) {
                // 接收管道内的数据
                SocketChannel socketChannel = serverSocketChannel.accept();
                // 如果数据不为空,则讲管道添加到selector选择器中
                if (socketChannel != null) {
                    socketChannel.configureBlocking(false);
                    selectors.add(socketChannel);
                }
                // 遍历选择器中的所有管道,看是否已经发送数据
                for (SocketChannel sel : selectors) {
                    int j = sel.read(byteBuffer);
                    if (j > 0) {
                        byteBuffer.flip(); 
                        byte[] bytes = Arrays.copyOf(byteBuffer.array(), byteBuffer.limit());
                        System.out.println("已经获取到了数据" + new String(bytes));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

nio的原理,当多个连接进来了,统一交给selectors 进行管理,此selector是一个集合。再使用while(true)循环来查看是否有数据进来。

这种方式实现的缺点 当没有数据进来,一直循环。效率很低

redis官方只有linux版本,而没有windows版本?

因为redis使用的io多路复用原则,在windows环境下用轮询的机制,会存在空轮询的问题也就是上面那个示例存在的问题。在linux版本下使用的是epoll事件驱动通知,本身就不会存在空轮询问题。我们平时看到的windows版本都是大牛更改的

redis的线程模型

redis采用的是Nio,使用的是IO多路复用原则,单线程的情况下,使用一个selector来管理多个redis连接,由于linux环境下存在epoll事件驱动回调。所以,避免了windows环境下的空轮询问题。使redis单线程情况下效率也很高,能够支撑高并发。

linux环境下安装redis

redis安装步骤

  1. 上传Redis的安装包
redis-5.0.6.tar.gz

如果本地没有安装包可以采用wget或者yum下载

wget http://download.redis.io/releases/redis-5.0.6.tar.gz
  1. 解压我们的Redis安装包
tar -zxvf redis-5.0.6.tar.gz
  1. 创建redis文件夹
mkdir /usr/redis
  1. 编译
make install PREFIX=/usr/redis
  1. 启动Redis
cd /usr/redis/bin     ./redis-server

前台启动的方式

./redis-server 

后台启动的方式(需要现在redis.conf修改daemonieze yes)

./redis-server ./redis.conf 

环境核心配置

将Redis设置为后台启动,重启启动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账号密码
vi redis.conf
requirepass 123456
./redis-server ./redis.conf 
工具连接
./redis-cli -h 192.168.212.155 -p 6379 -a 123456
设置Reids允许ip访问
注释掉bind 127.0.0.1
protected-mode no ###允许外界访问
关闭防火墙
systemctl stop firewalled

如果是腾讯云或者阿里云,还需要配置安全组

redis默认情况下分为16个库,且每一个库的key不能重复,不同的库之间互不影响

redis数据结构

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

String类型

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

操作指令:

Set name mayikt
Gey name mayikt

Hash类型

我们可以将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)

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

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

有序集合的成员是唯一的,但分数(score)却可以重复。

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

ZADD mayikt 1 redis
ZADD mayiktsets  1 redis
ZRANGE mayiktsets 0 10 WITHSCORES

SpringBoot整合Redis

在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;
    }
}

配置文件application.yml

spring:
  redis:
    host: 192.168.212.155
    password: 123456
    port: 6379