redis常用知识汇总( 十 )


基于zookeeper临时有序节点可以实现的分布式锁 。大致思想为:每个客户端对某个方法加锁时 , 在zookeeper上的与该方法对应的指定节点的目录下 , 生成一个唯一的瞬时有序节点 。判断是否获取锁的方式很简单 , 只需要判断有序节点中序号最小的一个 。当释放锁的时候 , 只需将这个瞬时节点删除即可 。同时 , 其可以避免服务宕机导致的锁无法释放 , 而产生的死锁问题 。完成业务流程后 , 删除对应的子节点释放锁 。
在实践中 , 当然是从以可靠性为主 。所以首推Zookeeper 。
参考:
https://www.jianshu.com/p/8bddd381de06
分布式Redis是前期做还是后期规模上来了再做好?为什么?
既然Redis是如此的轻量(单实例只使用1M内存) , 为防止以后的扩容 , 最好的办法就是一开始就启动较多实例 。即便你只有一台服务器 , 你也可以一开始就让Redis以分布式的方式运行 , 使用分区 , 在同一台服务器上启动多个实例 。
一开始就多设置几个Redis实例 , 例如32或者64个实例 , 对大多数用户来说这操作起来可能比较麻烦 , 但是从长久来看做这点牺牲是值得的 。
这样的话 , 当你的数据不断增长 , 需要更多的Redis服务器时 , 你需要做的就是仅仅将Redis实例从一台服务迁移到另外一台服务器而已(而不用考虑重新分区的问题) 。一旦你添加了另一台服务器 , 你需要将你一半的Redis实例从第一台机器迁移到第二台机器 。
什么是 RedLock
Redis 官方站提出了一种权威的基于 Redis 实现分布式锁的方式名叫 Redlock , 此种方式比原先的单节点的方法更安全 。它可以保证以下特性:
1、安全特性:互斥访问 , 即永远只有一个 client 能拿到锁
2、避免死锁:最终 client 都可能拿到锁 , 不会出现死锁的情况 , 即使原本锁住某资源的 client crash 了或者出现了网络分区
3、容错性:只要大部分 Redis 节点存活就可以正常提供服务
缓存异常
缓存雪崩
缓存雪崩是指缓存同一时间大面积的失效 , 所以 , 后面的请求都会落到数据库上 , 造成数据库短时间内承受大量请求而崩掉 。
解决方案
1、缓存数据的过期时间设置随机 , 防止同一时间大量数据过期现象发生 。
2、一般并发量不是特别多的时候 , 使用最多的解决方案是加锁排队 。
3、给每一个缓存数据增加相应的缓存标记 , 记录缓存的是否失效 , 如果缓存标记失效 , 则更新数据缓存 。
 
缓存穿透
缓存穿透是指缓存和数据库中都没有的数据 , 导致所有的请求都落到数据库上 , 造成数据库短时间内承受大量请求而崩掉 。
解决方案
1、接口层增加校验 , 如用户鉴权校验 , id做基础校验 , id<=0的直接拦截;
2、从缓存取不到的数据 , 在数据库中也没有取到 , 这时也可以将key-value对写为key-null , 缓存有效时间可以设置短点 , 如30秒(设置太长会导致正常情况也没法使用) 。这样可以防止攻击用户反复用同一个id暴力攻击
3、采用布隆过滤器 , 将所有可能存在的数据哈希到一个足够大的 bitmap 中 , 一个一定不存在的数据会被这个 bitmap 拦截掉 , 从而避免了对底层存储系统的查询压力
附加
对于空间的利用到达了一种极致 , 那就是Bitmap和布隆过滤器(Bloom Filter) 。
Bitmap: 典型的就是哈希表
缺点是 , Bitmap对于每个元素只能记录1bit信息 , 如果还想完成额外的功能 , 恐怕只能靠牺牲更多的空间、时间来完成了 。
布隆过滤器(推荐)
就是引入了k(k>1)k(k>1)个相互独立的哈希函数 , 保证在给定的空间、误判率下 , 完成元素判重的过程 。
它的优点是空间效率和查询时间都远远超过一般的算法 , 缺点是有一定的误识别率和删除困难 。
Bloom-Filter算法的核心思想就是利用多个不同的Hash函数来解决“冲突” 。
Hash存在一个冲突(碰撞)的问题 , 用同一个Hash得到的两个URL的值有可能相同 。为了减少冲突 , 我们可以多引入几个Hash , 如果通过其中的一个Hash值我们得出某元素不在集合中 , 那么该元素肯定不在集合中 。只有在所有的Hash函数告诉我们该元素在集合中时 , 才能确定该元素存在于集合中 。这便是Bloom-Filter的基本思想 。


推荐阅读