Redis由于数据存储在内存(随机访问内存要比硬盘快100万倍),下面是Google 工程师Jeff Dean在分布式系统PPT中给出的各种访问速度参考值:
访问方式 | 耗时 |
---|---|
L1 cache reference 读取CPU的一级缓存 | ~0.5 ns |
L2 cache reference 读取CPU的二级缓存 | ~7ns |
Mutex lock/unlock 互斥锁\解锁 | ~100 ns |
Main memory reference 读取内存数据 | ~100 ns |
Compress 1K bytes with Zippy 1k字节压缩 | ~10,000 ns |
Send 2K bytes over 1 Gbps network 在1Gbps的网络上发送2k字节 | ~20,000 ns |
Read 1 MB sequentially from memory 从内存顺序读取1MB | ~250,000 ns |
Round trip within same datacenter 从一个数据中心往返一次,ping一下 | ~500,000 ns |
Disk seek 磁盘搜索 | ~10,000,000 ns |
Read 1 MB sequentially from network 从网络上顺序读取1兆的数据 | ~10,000,000 ns |
Read 1 MB sequentially from disk 从磁盘里面读出1MB | ~30,000,000 ns |
Send packet CA->Netherlands->CA 一个包的一次远程访问 | ~150,000,000 ns |
由于基于内存随机访问效率极高,所以Redis设计为单线程操作,确保了线程安全。由于其线程安全,访问效率极高,但内存的存储空间较小,在实际项目应用中通常用来实现分布式锁和缓存。
下面我们看一下如何利用spring-data-redis提供的接口实现redis分布式锁。
一、SETNX设置KV并设置超时时间实现分布式锁
从spring-data-redis源码中可以看到setIfAbsent底层就是调用了Redis的SETNX命令,setIfAbsent方法的源码如下:
public Boolean setIfAbsent(K key, V value) {
final byte[] rawKey = rawKey(key);
final byte[] rawValue = rawValue(value);
return execute(new RedisCallback<Boolean>() {
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
return connectio