为什么我们做分布式使用Redis?
Redis is single-threaded.Memory-based.
Types: String, Hash, List, Set, Sorted Set
Expiration:
Redis 采用的是定期删除(random scan and delete expired key) + 惰性删除策略
在 redis.conf 中有一行配置:
# maxmemory-policy allkeys-lru
有强一致性要求的数据,不能放缓存
先更新数据库,再删缓存
Method1: multi, discard, exec
Method2: SETNX, GETSET
*(Redis本身是单线程不需要锁,但是Redis是implement distributed lock的方式之一)
Redis事务和锁的应用详解
multi -- sql: start transaction...
discard -- sql: rollback transaction
exec -- sql: submit transaction
Redis实现分布式共享锁
SETNX key value当且仅当 key 不存在,将 key 的值设为 value ,并返回1
若给定的 key 已经存在,则 SETNX 不做任何动作,并返回0
GETSET key value
将给定 key 的值设为 value ,并返回 key 的旧值 (old value)
当 key 存在但不是字符串类型时,返回一个错误
当key不存在时,返回nil
GET key
返回 key 所关联的字符串值
如果 key 不存在那么返回特殊值 nil
DEL key
删除给定的一个或多个 key
不存在的 key 会被忽略
分布式锁的问题
1:必要的超时机制:获取锁的客户端一旦崩溃,一定要有过期机制,否则其他客户端都降无法获取锁,造成死锁问题。2:分布式锁,多客户端的时间戳不能保证严格意义的一致性,所以在某些特定因素下,有可能存在锁串的情况。要适度的机制,可以承受小概率的事件产生。
3:只对关键处理节点加锁,良好的习惯是,把相关的资源准备好,比如连接数据库后,调用加锁机制获取锁,直接进行操作,然后释放,尽量减少持有锁的时间。
4:在持有锁期间要不要CHECK锁,如果需要严格依赖锁的状态,最好在关键步骤中做锁的CHECK检查机制,但是根据我们的测试发现,在大并发时,每一次CHECK锁操作,都要消耗掉几个毫秒,而我们的整个持锁处理逻辑才不到10毫秒,玩客没有选择做锁的检查。
5:sleep学问,为了减少对Redis的压力,获取锁尝试时,循环之间一定要做sleep操作。但是sleep时间是多少是门学问。需要根据自己的Redis的QPS,加上持锁处理时间等进行合理计算。
6:至于为什么不使用Redis的muti,expire,watch等机制,可以查一参考资料,找下原因。
No comments:
Post a Comment