史上最全redis教程

个人最近总结了一下redis的知识如下,可能有的东西写的比较杂,只是为了自我总结一下。

  1. redis简介
  • 什么是redis
    Redis的的是完全开源免费的,遵守BSD协议,是一个高性能的键值数据库。是当前最热门的的的NoSql数据库之一,也被人们称为数据结构服务器。Redis以内存作为数据存储介质,所以读写数据的效率极高,远远超过数据库。以设置和获取一个256字节字符串为例,它的读取速度可高达110000次/s,写速度高达81000次/s。
    Redis跟memcache不同的是,储存在Redis中的数据是持久化的,断电或重启后,数据也不会丢失。因为Redis的存储分为内存存储、磁盘存储和log文件三部分,重启后,Redis可以从磁盘重新将数据加载到内存中,这些可以通过配置文件对其进行配置,正因为这样,Redis才能实现持久化。
    Redis支持主从模式,可以配置集群,这样更利于支撑起大型的项目,这也是Redis的一大亮点。

  • redis到底有多快
    Redis采用的是基于内存的采用的是单进程单线程模型的 KV 数据库,由C语言编写,官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。这个数据不比采用单进程多线程的同样基于内存的 KV 数据库 Memcached 差。

  • redis为什么这么快
    1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);
    2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
    3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
    4、使用多路I/O复用模型,非阻塞IO;
    5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;
    以上几点都比较好理解,下边我们针对多路 I/O 复用模型进行简单的探讨:
    (1)多路 I/O 复用模型
    多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。
    这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。

  • redis为什么是单线程的
    官方FAQ表示,因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了(毕竟采用多线程会有很多麻烦!),并且正是由于在单线程模式的情况下已经很快了,就没有必要在使用多线程了!

  1. 安装

1、下载对应版本的压缩包,上传到对应的linux服务器上,解压缩
下载地址https://redis.io/
2、解压tar -zxvf redis-5.0.5.tar.gz
3、redis是由C语言编写的,它的运行需要C环境,所以编译前需安装 gcc
yum install gcc-c++
4、编译:进入解压后的 redis-5.0.5 目录,执行 make 命令(稍慢)
5、安装:进入 src 目录后执行 make install(很快)
6、修改redis 的核心配置文件 redis.conf
(1) 注释掉 bind 127.0.0.1 这一行(解决只能特定网段连接的限制)
(2) 将 protected-mode 属性改为 no (关闭保护模式,不然会阻止远程访问)
(3) 将 daemonize 属性改为 yes (这样启动时就在后台启动)
(4) 设置密码(可选,个人建议还是设个密码)
修改完成后,wq保存并退出(先按Esc,接着输入 :wq)
7、进入到src目录下直接输入redis-server …/etc/redis.conf启动redis
使用redis-cli可以进入redis客户端,设置的密码的话,需要输入相应的密码。
8、也可以下载可视化工具连接RedisDesktopManager连接redis
下载地址https://github.com/qishibo/AnotherRedisDesktopManager/releases

  1. redis基本知识点
    redis数据结构:
    Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
    1、String类型是二进制安全的,意思是redis的String可以包含任何数据。比如jpg图片或者序列化的对象。string 类型的值最大能存储 512MB
    2、Redis hash 是一个键值(key=>value)对集合,Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象,每个 hash 可以存储 232 -1 键值对(40多亿)
    3、List Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。lpush runoob mongodb 、、
    4、Redis 的 Set 是 string 类型的无序集合,集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1),根据集合内元素的唯一性,第二次插入的元素将被忽略,集合中最大的成员数为 232 - 1(4294967295, 每个集合可存储40多亿个成员)。
    sadd key member
    smembers runoob
    5、zset(sorted set:有序集合),不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。zadd zset 0 test
    阿斯蒂芬打算史上最全redis教程_第1张图片
    1、redisTemplate.opsForValue().setIfAbsent(key, value)
    如果键不存在则新增,存在则不改变已经有的值。
    2、redisTemplate.opsForValue().getAndSet(key, value)
    获取输出旧值,修改旧值
    1、2可以一起使用实现redis的分布式锁
  2. 结合SpringBoot使用redis
    4.1. 添加pom依赖
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.1.3.RELEASE</version>
        </dependency>

4.2 在application.properties中加入redis配置

#-------------redis配置------------
# Redis数据库索引(默认为0)
#spring.redis.database=0
# Redis服务器地址
spring.redis.host=xxxxxxxxx
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=redis
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制,s)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=1000

4.3. 初始化配置类

package com.zyu.springandmybatis.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;


@Configuration
public class RedisConfig {

    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
    {
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(redisConnectionFactory);
        template.setKeySerializer(jackson2JsonRedisSerializer);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashKeySerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    @ConditionalOnMissingBean(StringRedisTemplate.class)
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
    {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}


4.4 创建一个service测试使用redisTemplate往redis服务器中存数据取数据

package com.zyu.springandmybatis.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class RedisService {
    @Autowired
    RedisTemplate redisTemplate;
    //    测试redis
    //存String类型数据
    public void setToRedis(){
        redisTemplate.opsForValue().set("testString","testString");
        String test= (String) redisTemplate.opsForValue().get("testString");
        System.out.println(test);
    }
    //存Hash类型数据
    public void setHash(){
        Map<String,String> map=new HashMap<>();
        map.put("key1","value1");
        map.put("key2","value2");
        map.put("key3","value3");
        map.put("key4","value4");
        map.put("key5","value5");
        redisTemplate.opsForHash().putAll("map1",map);
        Map<String,String> resultMap= redisTemplate.opsForHash().entries("map1");
        List<String> reslutMapList=redisTemplate.opsForHash().values("map1");
        Set<String>resultMapSet=redisTemplate.opsForHash().keys("map1");
        String value=(String)redisTemplate.opsForHash().get("map1","key1");
        System.out.println("value:"+value);
        System.out.println("resultMapSet:"+resultMapSet);
        System.out.println("resultMap:"+resultMap);
        System.out.println("resulreslutMapListtMap:"+reslutMapList);
    }
    //存List类型数据
    public void setList(){
        List<String> list1=new ArrayList<String>();
        list1.add("a1");
        list1.add("a2");
        list1.add("a3");

        List<String> list2=new ArrayList<String>();
        list2.add("b1");
        list2.add("b2");
        list2.add("b3");
        redisTemplate.opsForList().leftPush("listkey1",list1);
        redisTemplate.opsForList().rightPush("listkey2",list2);
        redisTemplate.opsForList().leftPushAll("list",list1);
        List<String> resultList1=(List<String>)redisTemplate.opsForList().leftPop("listkey1");
        List<String> resultList2=(List<String>)redisTemplate.opsForList().rightPop("listkey2");
        System.out.println("resultList1:"+resultList1);
        System.out.println("resultList2:"+resultList2);

    }
    //存set类型数据
    public void setSet(){
        Set<String> set1=new HashSet<String>();
        set1.add("set1");
        set1.add("set2");
        set1.add("set3");
        redisTemplate.opsForSet().add("set1",set1);
        Set<String> resultSet =redisTemplate.opsForSet().members("set1");
        System.out.println("resultSet:"+resultSet);
    }
}

4.5 创建一个controller访问服务

package com.zyu.springandmybatis.controller;

import com.zyu.springandmybatis.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "redis")
public class RedisController {
    @Autowired
    RedisService redisService;

    @RequestMapping(value = "/setString")
    public void setToRedis(){
        redisService.setToRedis();
    }

    @RequestMapping(value = "/set")
    public void set(){
        redisService.setSet();
    }

    @RequestMapping(value = "/hash")
    public void hash(){
        redisService.setHash();
    }
    @RequestMapping(value = "/list")
    public void list(){
        redisService.setList();
    }

}

4.6 也可以使用注解
要先在启动类中加入@EnableCaching // 开启缓存注解
1、@Cacheable(cacheNames= “”)能够达到缓存方法的返回对象的效果。
value 或 cacheNames 属性做键,key 属性则可以看作为 value 的子键, 一个 value 可以有多个 key 组成不同值存在 Redis 服务器。
2、@CachePut缓存新增的或更新的数据到缓存,其中缓存名称为people,数据的key是person的id。
3、@CacheEvict从缓存people中删除key为id的数据。
配合redis来做缓存

done

你可能感兴趣的:(redis,redis介绍)