redis相关

旧街凉风 提交于 2019-12-20 01:28:53

redis结构:

String,Hash,List,Set,Zet

持久化:

         RDB 快照形式

         AOF 追加

1,redis既然是单线程的,为啥处理速度很快

   redis每秒处理100000+的QPS,基于内存操作,只是我们在处理网络请求的时候,是单线程处理,redis Server在运行的时候肯定不止一个线程,单线程省去了很多上下文切换的时间,redis使用多路复用技术,可以处理并发的连接。非阻塞IO 内部实现采用epoll,采用了epoll+自己实现的简单的事件框架。epoll中的读、写、关闭、连接都转化成了事件,然后利用epoll的多路复用特性,绝不在io上浪费一点时间。

2.分布式锁

加锁使用setnx(); key可以为当前线程id,value随便,当执行完后返回1,表明没有加锁,可以使用,当返回0的时候,表明当key已经存在,加锁失败,解锁的话del(key),

锁超时:当线程获取锁之后,挂掉了,那么锁就无法释放,这个时候需要设置expire()超时时间,保证到期释放锁

问题一: setnx 和expire操作非原子性,解决:redis高版本有set()方法设置超时时间

问题二: 线程执行时间太长,超时时间过了,其他线程获取锁执行,redis误删其他的锁,解决:删除锁时校验是否为当前线程

             校验和删除非原子性操作,可以通过LUA脚本来操作,

String luaScript = 'if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end';

redisClient.eval(luaScript , Collections.singletonList(key), Collections.singletonList(threadId));

问题三:问题二虽然避免了误操作,但是同时有两个线程在访问代码块,有高并发问题

            解决:可以开启守护线程,用来给过期的锁续命,当快要到时间的时候,程序还没执行完,这个时候,守护线程会执行expire命令

                     续命,

              虽是高可用,但是会出现问题,集群的话主从复制,是异步的,master同步到slave时候,可能会导致数据丢失

问题三,缓存穿透和缓存雪崩

           缓存穿透: 无用的值,多次咋访问数据库,数据库中不存在,比如id为 -1:

                           解决:接口层做权限校验和基础的数据校验

                                    针对数据库中不存在的对象,也保存到数据库中,设置有效时间短点

          缓存击穿: 针对缓存中没有,但是数据库中有的数据,一旦缓存到期,由于并发量特别大,导致数据库压力大,

                           解决: 设置热点数据,永不过期

                                     加互斥锁

          缓存雪崩: 指大量数据同一时间到期,导致查询数据量巨大,引起数据库压力大 甚至down机,

                           解决: 设置有效时间随机

                                     设置热点数据永不过期

                                      如果redis分布式部署,则热点数据分布在不同机器上

redis 热点数据问题:

     如何查找热点数据,根据点击量或根据时间可以用Zset(),set(key1, key2,value);

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!