redis配置和使用

redis的优点缺点

优点

1 redis 是基于内存的运行速度比较快我们将常用的数据存到redis 中用来代替数据库的查询会

2 支持数据持久化,支持AOF和RDB两种持久化方式

3 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。

4 数据结构丰富:除了支持string类型的value外还支持string、hash、set、sortedset、list等数据结构。

缺点

1 Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费。

redis如何存储一个对象

(序列化和json字符串)

序列化:通过对象输出流可以把对象的状态保存为字节数组,并且可以在有需要的时候将这个字节数组通过反序列化的方式再转换成对象

jedis.set(key, JSON.toJSONString(object));

也可以通过JSON.toJSONString将对象转成JSON 形式保存到数组中

1: redis的基本功能和概念

       A:Redis是基于内存的所以运行速度快,将常用的数据放在redis 中用来代替数据库的访问。

       B: Redis 还提供了简单的事务,保证了数据在搞并发场景下数据的一直性。 还有流水线,发布订阅, Lua 语等功能。

       C: spring-data-redis项目介绍

       Spring 提供了一个RedisConnectionFactory接口,通过这个接口生成redisConnction接口,这个这个各接口对原生的Jedis 进行封装,首先配置这个工厂就是配置redis 的基本属性。

2: RedisTemplate

        A: spring操作Redis 主要是通过 redisTemplate 这个类来操作, 这个类自动封装了redis 的连接和关闭

        B:redis 是基于字符串存储的NoSql 数据库 而java 是基于对象的,spring提供了redis 序列化器

3: Redis配置

  

/**
 * Redis配置
 */
@Configuration
public class RedisConfig {
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    /**
     *  实例化 RedisTemplate 对象
     * @return
     */
    @Bean
    public RedisTemplate functionDomainRedisTemplate() {
        RedisTemplate redisTemplate = new RedisTemplate<>();
        initDomainRedisTemplate(redisTemplate, redisConnectionFactory);
        return redisTemplate;
    }

    /**
     * 创建RedisTemplate 对象自动创建连接
     * @return
     */
    @Bean
    public RedisTemplate redisTemplate() {
        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }


    /**
     * 设置数据存入 redis 的序列化方式
     *  redis 实现了序列化接口后就可以将对象以序列化的方式进行存取
     *  也可以将二进制的字符串反序列化转换为对象
     *  这样redis 就可以将对象以字符串的形式存取
     *  使用字符串序列化器
     */
    private void initDomainRedisTemplate(RedisTemplate redisTemplate, RedisConnectionFactory factory) {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());

        redisTemplate.setHashValueSerializer(new RedisObjectSerializer());
        redisTemplate.setValueSerializer(new RedisObjectSerializer());
        redisTemplate.setConnectionFactory(factory);
    }

    /**
     * 使用redisCallback和sessionCallback 接口
     * 主要作用是让redis 进行回调可以在同一条连接下执行多个redis命令
     */
    public void useSessionCallback(RedisTemplate redisTemplate){
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations ro) throws DataAccessException {
                ro.opsForValue().set("key1","huyunqiang");
                ro.opsForHash().put("hash","filed","hvalue");
                return null;
            }
        });
    }

    /**
     * 使用lambda 优化代码
     * @param redisTemplate
     */
//    public void useSessionCallback1(RedisTemplate redisTemplate){
//        redisTemplate.execute((RedisOperations os) -> {
//                ro.opsForValue().set("key1","huyunqiang");
//                ro.opsForHash().put("hash","filed","hvalue");
//                return null;
//        });
//    }


    /**
     * 实例化 HashOperations 对象,可以使用 Hash 类型操作
     */
    @Bean
    public HashOperations hashOperations(RedisTemplate redisTemplate) {
        return redisTemplate.opsForHash();
    }

    /**
     * 实例化 ValueOperations 对象,可以使用 String 操作
     */
    @Bean
    public ValueOperations valueOperations(RedisTemplate redisTemplate) {
        return redisTemplate.opsForValue();
    }

    /**
     * 实例化 ListOperations 对象,可以使用 List 操作
     * @return
     */
    @Bean
    public ListOperations listOperations(RedisTemplate redisTemplate) {
        return redisTemplate.opsForList();
    }

    /**
     * 实例化 SetOperations 对象,可以使用 Set 操作
     */
    @Bean
    public SetOperations setOperations(RedisTemplate redisTemplate) {
        return redisTemplate.opsForSet();
    }

    /**
     * 实例化 ZSetOperations 对象,可以使用 ZSet 操作
     */
    @Bean
    public ZSetOperations zSetOperations(RedisTemplate redisTemplate) {
        return redisTemplate.opsForZSet();
    }

    public static void main(String[] args){


    }
} 
  
 redis:
        database: 0
        host: localhost
        port: 6379
        password:      # 密码(默认为空)
        timeout: 6000ms  # 连接超时时长(毫秒)
        jedis:
            pool:
                max-active: 1000  # 连接池最大连接数(使用负值表示没有限制)
                max-wait: -1ms      # 连接池最大阻塞等待时间(使用负值表示没有限制)
                max-idle: 10      # 连接池中的最大空闲连接
                min-idle: 5       # 连接池中的最小空闲连接

4 Spring 对Redis 数据类型操作封装

          

5:  redis中常用的命令

     http://redisdoc.com/set/index.html    

     dbsize查看当前数据库的key的数量,flushdb:清空当前库,Flushall;通杀全部库

6:redis 中数据类

        string,一个key对应一个value。string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。一个redis中字符串value最多可以是512M   

        Hash(哈希)
        Redis hash 是一个键值对集合。 Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。类似Java里面的Map

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

        Set(集合
        Redis的Set是string类型的无序集合。它是通过HashTable实现实现的,

       zset(sorted set:有序集合)
        Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。

  7:redis 持久化

       RDB说明:

       指定时间间隔将内存中的数据写入磁盘,也就是Snapshot快照,恢复是将快照文件写入到内存中  

       Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。

       Fork

       复制一个和当前一样的进行,进程的所有数据都保持一致(变量,环境变量,计数器)但是是一个全新的进程和原来的进程保持一致。

 RDB 保存的是dump.rdb文件 

 配置位置

 如何触发RDB快照

      # save "" save 900 1 save 300 10 save 60 10000

     若不想用RDB方案,可以把 save "" 的注释打开,下面三个注释

 如何恢复

       将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可

 优势

      适合大规模的数据恢复,对数据完整性和一致性要求不高

 劣势

     在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。

      fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑

 如何停止

     动态所有停止RDB保存规则的方法:redis-cli config set save ""

 小总结

AOF说明

     以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作,Aof保存的是appendonly.aof文件

优势

     每修改同步:appendfsync always   同步持久化 每次发生数据变更会被立即记录到磁盘  性能较差但数据完整性比较好

     每秒同步:appendfsync everysec    异步操作,每秒记录   如果一秒内宕机,有数据丢失

     不同步:appendfsync no   从不同步

劣势

      相同数据集的数据而言aof文件要远大于rdb文件,恢复速度慢于rdb

     aof运行效率要慢于rdb,每秒同步策略效率较好,不同步效率和rdb相同

AOF启动/修复/恢复

     正常恢复

      修改默认的appendonly no,改为yes。将有数据的aof文件复制一份保存到对应目录(config get dir)。恢复:重启redis然后重新加载

     异常恢复

    修改默认的appendonly no,改为yes。备份被写坏的AOF文件,redis-check-aof --fix进行修复。恢复:重启redis然后重新加载

rewrite

     说明:AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集.可以使用命令bgrewriteaof

     触发:Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发

     原理:AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename),遍历新进程的内存中数据,每条记录有一条的Set语句。重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似

7: 发布订阅

        进程间的一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。一般很少用redis作为消息的发送订阅,一般都是通过消息中间件 rabbitMq或者activeMq做消息同步。

8:   redis事务

正常执行  如果在 set b bbb 处失败,set a 已成功不会回滚,set c 还会继续执行。

redis 127.0.0.1:7000> multi
OK
redis 127.0.0.1:7000> set a aaa
QUEUED
redis 127.0.0.1:7000> set b bbb
QUEUED
redis 127.0.0.1:7000> set c ccc
QUEUED
redis 127.0.0.1:7000> exec
1) OK
2) OK
3) OK

放弃事务

redis 127.0.0.1:6379> MULTI
OK

redis 127.0.0.1:6379> PING
QUEUED

redis 127.0.0.1:6379> SET greeting "hello"
QUEUED

redis 127.0.0.1:6379> DISCARD
OK

全体连坐 : 一个出错全部挂掉

127.0.0.1:6379> hset user id 11
(integer) 1
127.0.0.1:6379> hget user id
"11"
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set ﾿ᄡ v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> getset k3
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k2
(nil)
127.0.0.1:6379>

冤头债主

watch

Redis Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断事

事务的三个阶段

开启:以MULTI开始一个事务

入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面

执行:由EXEC命令触发事务

特征:
单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行,
也就不存在”事务内的查询要看到事务里的更新,在事务外查询不能看到”这个让人万分头痛的问题
不保证原子性:redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚

Redis的复制(Master/Slave)主从赋值读写分离

一主二仆

   一个Master两个Slave

1 切入点问题?slave1、slave2是从头开始复制还是从切入点开始复制?比如从k4进来,那之前的123是否也可以复制


2 从机是否可以写?set可否?


3 主机shutdown后情况如何?从机是上位还是原地待命


4 主机又回来了后,主机新增记录,从机还能否顺利复制?


5 其中一台从机down后情况如何?依照原有它能跟上大部队吗?

修改配置文件 赋值三个redis.conf 分别修改一下配置文件

port 6379
daemonize yes
pidfile /var/run/redis_6379.pid
logfile "6379.log"
dbfilename dump6379.rdb 

分别启动三个redis配置

redis-server /usr/local/java/redis/etc/redis3679.conf

redis-server /usr/local/java/redis/etc/redis3680.conf

redis-server /usr/local/java/redis/etc/redis3681.conf

  •  info replication 查看主从状态三台分别执行时平等的
192.168.234.6:7002> info replication
# Replication
role:slave
master_host:192.168.234.7
master_port:7003
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:0
  •  SLAVEOF 192.168.234.6 7000    //将该服务设置为 7000的从机 备份主机数据(备份了主机的所有数据,不管实在主机添加到一半的时候备份之前的数据都是可以获取到的)
  • 读写分离 (只有主机可以写入数据,从机只能存放数据)
  • 主机挂了从机等待主机回复,主机回复后数据正常保存到从机中
  • 从机挂了要从新指定是从机(也可以在配置文件中配置好说明这个是从机)

是什么

行话:也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主

能干什么

读写分离,容灾恢复

常用操作 

一主二仆:一个Master两个Slave

薪火相传:

  • 上一个Slave可以是下一个slave的Master,Slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了链条中下一个的master,可以有效减轻master的写压力
  • 中途变更转向:会清除之前的数据,重新建立拷贝最新的
  • slaveof 新主库IP 新主库端口

反客为主

使当前数据库停止与其他数据库的同步,转成主数据库

哨兵模式(sentinel)

反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库

怎么用

自定义的/myredis目录下新建sentinel.conf文件,名字绝不能错

配置哨兵,填写内容

 sentinel monitor 被监控数据库名字(自己起名字) 127.0.0.1 6379 1

上面最后一个数字1,表示主机挂掉后salve投票看让谁接替成为主机,得票数多少后成为主机

启动哨兵

 redis-sentinel /myredis/sentinel.conf 

原有的master挂了 投票新选 出新的主机 重新主从继续开工,info replication查查看
如果之前的master重启回来,会不会双master冲突?
不会 新的主机主动变为从机
一组sentinel能同时监控多个Master

缺点:复制延时

entinel monitor host6379 192.168.234.3 6379 1

/usr/local/java/redis/etc/sentinel.conf

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(redis配置和使用)