美文网首页
redis不仅仅只是缓存

redis不仅仅只是缓存

作者: 农民工进城 | 来源:发表于2019-08-12 11:04 被阅读0次

本章要点

  • 发布与订阅
  • 地理环境GEO
  • 基数
  • 分布式锁(推荐zk)
  • Redis为什么快

1. 发布订阅

发布订阅命令主要包括:publish、subscribe、unsubscribe、psubscribe(正则匹配订阅)、punsubscribe(正则匹配取消订阅)等命令组成。
jedis代码如下:

2.GEO

redis在3.2版本以后新增了对GEO对支持,主要包括命令:geoadd、geodist、geohash、geopos、georadius、georadiusbymember等。
jedis代码:

public static Long geoadd(String key, double longitude, double latitude, final String member){
        return redis.geoadd(key, longitude,latitude, member);
    }
    
    
    public static List<GeoCoordinate> geopos(String key, String... members){
        return redis.geopos(key, members);
    }
    
    
    public static Double geodist( String key,  String member1, String member2,GeoUnit unit){
        return redis.geodist(key, member1, member2, unit);
    }
    
    public static List<GeoRadiusResponse> georadius(String key, double longitude, double latitude,
               double radius, GeoUnit unit){
        return redis.georadius(key, longitude, latitude, radius, unit);
    }
    
    public static List<GeoRadiusResponse> georadius(String key, double longitude, double latitude,
               double radius, GeoUnit unit,GeoRadiusParam param){
        return redis.georadius(key, longitude, latitude, radius, unit, param);
    }

3.基数(HyperLogLog)

redis 在 2.8.9 版本添加了 HyperLogLog 结构,用来做基数统计的算法。主要包括“pfadd、pdcount、pfmerge等命令。
jedis代码:

    public static Long pfadd(String key,String elements){
        return redis.pfadd(key, elements);
    }
    
    public static Long pfcount(String key){
        return redis.pfcount(key);
    }
    
    public static String pfmerge(String destkey, String... sourcekeys){
        return redis.pfmerge(destkey, sourcekeys);
    }

4.Redis分布式锁(Redlock)

  • 分布式锁特性:
    1)在分布式系统环境下,一个方法在同一时间只能被一个机器的的一个线程执行;
    2)高可用的获取锁与释放锁;
    3)高性能的获取锁与释放锁;
    4)具备可重入特性;
    5)具备锁失效机制,防止死锁;
    6)具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败
public class RedisLock {

    public static boolean lock(Jedis jedis, String lockKey, String requestId, int expireTime) {

        String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
        if ("OK".equals(result)) {
            return true;
        }
        return false;
    }

    public static boolean unlock(Jedis jedis, String lockKey, String requestId) {

        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
        if ("1".equals(result)) {
            return true;
        }
        return false;
    }

}
  • redis分布式锁,其实需要自己不断去尝试获取锁,比较消耗性能
  • zk分布式锁,获取不到锁,注册个监听器即可,不需要不断主动尝试获取锁,性能开销较小
  • 如果是redis获取锁的那个客户端bug了或者挂了,那么只能等待key过期之后才能释放锁;而zk的话,因为创建的是临时znode,只要客户端挂了,znode就没了,此时就自动释放锁

5. redis为什么快

1、协议简单,RESP是纯字符串,解析简单
2、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);
3、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
4、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
5、使用多路I/O复用模型,非阻塞IO;
6、Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

相关文章