redis

1.库的概念 

 2.发布和订阅

listener配置:

 测试后发现存在重复消费和丢消息问题(只能收到客户端链接之后的消息)

 

3.事务和pipeline:

先看下没有事务时的执行情况:

 

然后我们用Pipeline:

 

可以看到每个线程的多个redis操作结果被放到了list<Object>中,且如果我们持续用redis-cli刷transaction的值会发现直到10s之后第二个redis命令执行(实际上在closePipeline之后)才出现transaction的key。查看executePipelined的实现:

 

如果我们手动close:

open和close其实初始化了connection中的pipeline对象 在后续execute中如果pipeline被初始化 则做不通的逻辑 将结果放到List<Object>  并在close时取出并清空最后返回

 pipeline和事务是不同的概念,pipeline并不保证原子性,更多的是客户端的行为来减少rtt,在不超过报文大小的情况下,pipeline中的命令会打包一起发送,结果也打包返回,当我们用事务时,则是每条命令分开发送,服务端响应queue直到exec返回结果。

pipeline非原子性实验:

 for (int i=0;i<1;i++) {
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {

                    List<Object>  result=redisTemplate.executePipelined(new RedisCallback<Object>() {
                        @Override
                        public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
                            System.out.println("pipeline start");
                            for (int j=0;j<1000;j++){
                                redisConnection.incrBy("transaction".getBytes(),1);
                            }
                            return null;
                        }
                    });
                    System.out.println(result);

                }
            });
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {

                    Object result=redisTemplate.execute(new RedisCallback<Object>() {
                        @Override
                        public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
                            System.out.println("dddd start");
                            for (int j=0;j<1000;j++){
                                System.out.println(redisConnection.incrBy("transaction".getBytes(),-1));
                            }

                            return null;
                        }
                    });
                    System.out.println(result);

                }
            });

我们在两个线程里:一个线程用pipeline自增1000次,另外一个线程里不用pipeline自减1000次,pipeline执行日志如下:

在递增到49时执行了不在pipeline中的命令:

可以看到在第243次也发生了同样的情况

 

 

事务:

我们发现redisTemplate提供的multi,exec,watch可以实现事务,同时execute也可以 关于2者的区别:

转载:https://www.cnblogs.com/wuhaonan/p/10646277.html

我们用同样的方法测试下事务的原子性:

redisTemplate.execute(new SessionCallback() {
                        @Override
                        public Object execute(RedisOperations redisOperations) throws DataAccessException {
                            System.out.println("transaction start");
                            redisOperations.multi();
                            for (int i=0;i<1000;i++){
                                redisOperations.opsForValue().increment("transaction", 1);
                            }
                            List<Object> res = redisOperations.exec();
                            System.out.println(res);
                            return null;
                        }
                    });

 redisTemplate.execute(new SessionCallback() {
                        @Override
                        public Object execute(RedisOperations redisOperations) throws DataAccessException {
                            System.out.println("dddd start");
                            for (int i=0;i<1000;i++){
                                System.out.println(redisOperations.opsForValue().increment("transaction", -1));
                            }
                            return null;
                        }
                    });

分别在2个线程里执行这2个execute,结果如下

可见事务的执行过程是保证了原子性的

 

 

 

4.rdb: 

 

 

5.aof:

6.复制

 我们关掉master之后,slave会一直报错但数据还是在的,当我们清掉master的快照和aof再次上线的时候,slave会重新同步,此时slave的数据也会被清掉

 

7.用redis构建锁

简单的setnx和del会有问题:

1.持有锁的进程因为操作时间过长而导致锁被自动释放,但进程本身并不知晓这一点,甚至还可能会错误地释放掉了其他进程持有的锁。

2.在一个进程持有的锁过期之后,其他多个进程同时尝试去获取锁

3.以上2点同时出现,导致多个进程获得了锁,而每个进程都以为自己是唯一一个获得锁的进程。

解决方法:在释放锁的时候 检查当前的锁是否是开始持有的锁,并在整个释放锁的过程watch锁

 

 

8sentinel:

 

一主两从3sentinel:

 

 

把master下线重新上线后发现如上,检查配置文件发现多了下面这行配置:

1从也变成了这样:

 2从的slaveof配置则被删掉了:

并且这个主从转化的过程有可能相当漫长 

posted @ 2020-06-04 01:24  l2c  阅读(170)  评论(0)    收藏  举报