1.jedis: redis的java客户端;
   快速入门使用:
   1.导入依赖:
   <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.9.0</version>
    </dependency>
	测试的话可以导入junit依赖
	<dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
     </dependency>
	 
	 2.使用:
	 @Test
    public void testJedis(){
        //注册jedis
        //1.设置
        jedis =new Jedis("localhost",6379);
        //2.设置密码
        //  jedis.auth("******");
        //3.选择库
        jedis.select(0);
        //开始使用
        //1.存入数据
        String result = jedis.set("name", "xiangxiang");
        System.out.println(result);
        //2.获取数据
        String name = jedis.get("name");
        System.out.println("name="+name);
        //结束使用释放内存
        if(jedis !=null){
            jedis.close();
        }
    }
---------------------------------------
2.jedis连接池:
  public class JedisConnectionFactory {
    private static final JedisPool jedispool;
    public  static final int port=6379;
    static {
        //配置连接池
        JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();
        //最大连接
        jedisPoolConfig.setMaxTotal(8);
        //最大空闲连接
        jedisPoolConfig.setMaxIdle(8);
        //最小空闲连接
        jedisPoolConfig.setMinIdle(0);
        //设置最长等待时间
        jedisPoolConfig.setMaxWaitMillis(200);
        jedispool=new JedisPool(jedisPoolConfig,"localhost",port,200);
    }
    //获取jedis对象
    public static Jedis getJedis(){
        return jedispool.getResource();
    }
}
使用时直接调用方法即可: jedis = JedisConnectionFactory.getJedis();
--------------------------------------------------------
3,springdataredis:redis的java客户端
   1.springboot项目导入依赖(也可以创建时在nosql中勾选,但是勾选后仍要导入连接池依赖) :
     <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <!--连接池依赖-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
     2.配置文件配置相关配置
	 例如:
spring:
  data:
    redis:
      host: "localhost"
      port: 6379
      password: 
      lettuce:
        pool:
          max-active: 8
          max-idle: 8
          min-idle: 0
          max-wait: 200
     3.注入redisTemplate使用:
	 @Autowired
    private RedisTemplate redisTemplate;
    @Test
    void testString() {
        redisTemplate.opsForValue().set("name","xiangxiang");
        System.out.println(redisTemplate.opsForValue().get("name"));
        redisTemplate.opsForHash().put("user:1","name","haha");
        redisTemplate.opsForHash().put("user:1","age","18");
        redisTemplate.opsForHash().put("user:1","sex","woman");
        System.out.println(redisTemplate.opsForHash().entries("user:1"));
    }
	
	由于序列化,更建议设置redistemplate序列化器:
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        //创建redisTemplate对象
        RedisTemplate<String,Object> template=new RedisTemplate<>();
        //设置连接工厂
        template.setConnectionFactory(redisConnectionFactory);
        //创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        //设置key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        //设置value的序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashKeySerializer(jackson2JsonRedisSerializer);
        //返回
        return template;
    }
}

使用时只要把private RedisTemplate redisTemplate;改为: private RedisTemplate<String,Object> redisTemplate;

------------
stringRedisTemplate: 可以代替redisTemplate; 
优点:序列化key时不会转为"@class": "com.xiangxiang.pojo.Student" 的形式而是"@class": "Student" 可以节约内存;
缺点:写入时要手动把对象序列化转为JSON, 读取时也要手动把读取到的JSON反序列化为对象;
  代码:
  @Autowired
    private StringRedisTemplate stringRedisTemplate;
    //JSON工具
    private static final ObjectMapper mapper=new ObjectMapper();
    @Test
    void testString() throws JsonProcessingException {
        stringRedisTemplate.opsForValue().set("name","xiangxiang");
        System.out.println(stringRedisTemplate.opsForValue().get("name"));
        stringRedisTemplate.opsForHash().put("user:1","name","haha");
        stringRedisTemplate.opsForHash().put("user:1","age","18");
        stringRedisTemplate.opsForHash().put("user:1","sex","woman");
        System.out.println(stringRedisTemplate.opsForHash().entries("user:1"));


        Student s1=new Student("ZhangSan",18);
        //对象转为json
        String json = mapper.writeValueAsString(s1);
        //写入数据
        stringRedisTemplate.opsForValue().set("student1",json);

        //读取数据
        String val = stringRedisTemplate.opsForValue().get("student1");
        //json转为对象
        Student student = mapper.readValue(val, Student.class);  //第二个参数时对象类型的字节码文件
        System.out.println("student="+student);
    }
	
	注意点:对string类型操作时,操作一样,对对象类型操作时才与redisTemplate不同;
---------------------------------------------------
3.tostring()方法相当与new了一个新的字符串;如果用tostring().intern()就是先去串池里寻找,如果有就直接用,没有就new;	 


----------------------------------------------------------
4.UUID:
UUID 的全称是 通用唯一识别码。它是一个用于识别信息的128位的数字标识符。

它的核心特性体现在名字上:
1.通用: 可以在任何地方生成,不需要中心化的授权机构。
2.唯一: 在可预见的未来,在同一时空中的所有系统中,生成重复标识符的概率极低,几乎可以忽略不计。
-----------------------------------------------------------------
5.redisson;
------------------------------------------
6.分布式锁的原理(跳过,以后学习);
--------------------------------------
7.创建线程池和线程任务:
    //创建线程池
    private static final ExecutorService SECKILL_ORDER_EXECUTOR=Executors.newSingleThreadExecutor();

    //创建线程任务
    private class VoucherOrderHandler implements Runnable{

        @Override
        public void run() {
            
        }
    }
----------------------------------
8.redis的主从架构:
redis中从结构只有一个主节点,可以有多个从节点;
从节点需要执行slaveof命令来确定主节点;
从节点连接主节点的第一次需要做全量同步;
主从节点数据同步分为全量同步和增量同步;
全量同步有三个阶段:
1.从节点发送自己的replid 和 offset 给主节点来和主节点的 replid 来匹配,匹配成功说明不是第一次连接,不需要做全量同步只需要做增量同步,否则需要做全量同步; 如果是全量同步,主节点会返回自己的replid 和 offset给从节点,让从节点继承自己的replid;
2.主节点执行bgsave生成RDB操作,并且将未来得及存储在RDB中的命令存储到缓冲区repl_baklog中, 然后将RDB传给从节点,从节点执行brush指令,清空自身然后执行RDB文件;
3.主节点将缓存在repl_baklog中的数据发送给从节点,从节点执行剩下的命令实现数据同步;
增量同步两个阶段:
1.和全量同步第一阶段一样,replid匹配说明是做增量同步;
2.主节点将缓存在repl_baklog中的数据发送给从节点,从节点执行剩下的命令实现数据同步;
--------
repl_backlog相当于一个环形数组,可以覆盖原先传输给从节点的数据;但是如果从节点宕机,repl_backlog就会发生错误,覆盖未传输的数据,就要等从节点修复好执行全量同步;
--------
执行全量同步的两种情况:
1.第一次连接
2.从节点宕机导致repl_backlog覆盖未传输的数据;

--------
修正:
第一阶段从节点还会和prior_replid匹配,
如果 replid = 主节点当前 replid 且 offset 合法 → 执行增量同步
如果 replid = 主节点的 prior_replid (历史id)也可以尝试执行增量同步(PSYNC 2 特性)
否则才执行全量同步 

第一次连接不一定增量同步,
如果主节点重启过,产生新的replid,
从节点有主节点的 旧 replid(主节点 prior_replid == 从节点 replid)
offset 仍然在 backlog 范围内
仍然可以增量同步!

---------------------------
哨兵集群依赖主从集群;
分片集群内含主从结构;
----------------------------------