zoukankan      html  css  js  c++  java
  • Redis使用(Java)

    目录

    • 什么是Redis
    • 为什么用Redis
    • 如何使用Redis(5种数据类型)
    • 底层数据结构

    什么是Redis

    Redis是一个开源的高性能键值对数据库。它通过提供多种键值数据类型来适应不同场景下的存储需求,并借助许多高层级的接口使其可以胜任如缓存、队列系统等不同的角色

    为什么用Redis(特性)

    • 存储结构

    支持字符串、散列、列表、集合、有序集合等类型。与MySQL相比,对于小数据集的复杂关系操作更直观,性能更好

    • 内存存储与持久化

    Redis数据库中的所有数据都存储在内存中。由于内存的读写速度远快于硬盘,因此Redis在性能上对比其他基于硬盘存储的数据库有非常明显的优势

    Redis提供了对持久化的支持,即将可以内存中的数据异步写入到硬盘中,同时不影响继续提供服务

    • 功能丰富

    缓存:为每个键设置生存时间(Time To Live,TTL),生存时间到期后键会自动被删除

    队列:Redis的列表类型键可以用来实现队列,并且支持阻塞式读取,可以很容易地实现一个高性能的优先级队列

    构建聊天室等系统:支持“发布/订阅”的消息模式

    • 简单稳定

    如何使用Redis

    字符串

    1 public void testString(){
    2     Jedis jedis = RedisUtil.connect();
    3     jedis.set("testKey", "testValue");
    4     System.out.println("testKey: " + jedis.get("testKey"));
    5     Long delResult = jedis.del("testKey");
    6     System.out.println("del testKey, result = " + delResult);
    7     System.out.println("del后,testKey: " + jedis.get("testKey"));
    8 }
    View Code
    • 问题:字符串直接用char数组就好了,但是redis做了一些优化

    目的:提高空间的利用率

    方法:tryObjectEncoding包含的主要逻辑,依次执行以下策略

    1. 判断长度小于20,且可以将它转换为long类型的值:int string2l(const char *s, size_t slen, long *lval)

    2. 把value放在和与对象相同的内存块中:robj *createEmbeddedStringObject(const char *ptr, size_t len)

    注:o对象(即返回结果)获得如下全部的内存空间,value是设置的值,与o对象分配在同一块中

    3. 无法转换,把多分配的空间remove

    列表

     1 public void testList(){
     2     String testKey = "testKey";
     3     jedis.lpush(testKey, "testValue", "testValue2");
     4     System.out.println("testKey: " + jedis.lrange(testKey, 0, -1));
     5     jedis.lpush(testKey, "testValue", "testValue2", "testValue3");
     6     System.out.println("testKey set new: " + jedis.lrange(testKey, 0, -1));
     7     jedis.lrem(testKey, 2, "testValue");
     8     System.out.println("testKey lrem 2个数据后: " + jedis.lrange(testKey, 0, -1));
     9     Long delResult = jedis.del(testKey);
    10     System.out.println("del testKey, result = " + delResult);
    11     System.out.println("del后,testKey: " + jedis.get(testKey));
    12     System.out.println("del后,testKey: " + jedis.lrange(testKey, 0, -1));
    13 }
    View Code

    集合

    1 public void testSet(){
    2     String testKey = "testKey";
    3     jedis.sadd(testKey, "testValue", "testValue2");
    4     System.out.println("testKey: " + jedis.smembers(testKey));
    5     jedis.sadd(testKey, "testValue", "testValue2", "testValue3");
    6     System.out.println("testKey set new: " + jedis.smembers(testKey));
    7     jedis.srem(testKey, "testValue");
    8     System.out.println("testKey srem后: " + jedis.smembers(testKey));
    9 }
    View Code

    有序集合

     1 public void testSortedSet(){
     2     String testKey = "testKey";
     3     jedis.zadd(testKey, 5, "testValue5");
     4     jedis.zadd(testKey, 2, "testValue2");
     5     System.out.println("testKey: " + jedis.zrange(testKey, 0, -1));
     6     jedis.zadd(testKey, 2, "testValue2-2");
     7     jedis.zadd(testKey, 9, "testValue9");
     8     System.out.println("testKey zadd: " + jedis.zrange(testKey, 0, -1));
     9     jedis.zrem(testKey, "testValue2");
    10     System.out.println("testKey zrem后: " + jedis.zrange(testKey, 0, -1));
    11 }
    View Code

    哈希

     1 public void testHash(){
     2     String testKey = "testKey";
     3     jedis.hset(testKey, "field", "100");
     4     System.out.println("testKey: " + jedis.hget(testKey, "field"));
     5     jedis.hincrBy(testKey, "field", 100);
     6     System.out.println("testKey 的value hincrBy: " + jedis.hvals(testKey));
     7 
     8     jedis.hset(testKey, "field", "testValue");
     9     jedis.hset(testKey, "field2", "testValue2");
    10     jedis.hset(testKey, "field3", "testValue3");
    11     System.out.println("testKey new hset, keys= " + jedis.hkeys(testKey));
    12     System.out.println("testKey new hset, values= " + jedis.hvals(testKey));
    13     jedis.hdel(testKey, "field3");
    14     System.out.println("testKey hdel, keys= " + jedis.hkeys(testKey));
    15     System.out.println("testKey hdel, values= " + jedis.hvals(testKey));
    16 }
    View Code

    底层数据结构

      1 /*3个基础数据结构 */
      2 typedef struct dict {
      3     dictType *type;
      4     void *privdata;
      5     dictht ht[2];// 有两个table
      6     long rehashidx; 
      7     unsigned long iterators;
      8 } dict;
      9 
     10 /* hash table结构 */
     11 typedef struct dictht {
     12     dictEntry **table;
     13     unsigned long size;
     14     unsigned long sizemask;
     15     unsigned long used;
     16 } dictht;
     17 
     18 /* 节点结构*/
     19 typedef struct dictEntry {
     20     void *key;
     21     union {
     22         void *val;
     23         uint64_t u64;
     24         int64_t s64;
     25         double d;
     26     } v;
     27     struct dictEntry *next;
     28 } dictEntry;
     29 
     30 
     31 /* 
     32 * 根据key查找entry 
     33 * key 通过hash获取index,冲突则通过挂链方式继续查找
     34 */
     35 dictEntry *dictFind(dict *d, const void *key)
     36 {
     37     dictEntry *he;
     38     uint64_t h, idx, table;
     39 
     40     if (d->ht[0].used + d->ht[1].used == 0) return NULL; /* dict is empty */
     41     if (dictIsRehashing(d)) _dictRehashStep(d);
     42     h = dictHashKey(d, key);
     43     for (table = 0; table <= 1; table++) {
     44         idx = h & d->ht[table].sizemask;
     45         he = d->ht[table].table[idx];
     46         while (he) {//遍历该位置下所有key
     47             if (key == he->key || dictCompareKeys(d, key, he->key))
     48                 return he;
     49             he = he->next;
     50         }
     51         if (!dictIsRehashing(d)) return NULL;
     52     }
     53     return NULL;
     54 }
     55 
     56 /* 创建dict,初始化时dictht大小为0 */
     57 dict *dictCreate(dictType *type,
     58     void *privDataPtr)
     59 {
     60     dict *d = zmalloc(sizeof(*d));
     61 
     62     _dictInit(d, type, privDataPtr);
     63     return d;
     64 }
     65 
     66 /* 扩展或创建dictht */
     67 int dictExpand(dict *d, unsigned long size)
     68 {
     69     /* the size is invalid if it is smaller than the number of
     70     * elements already inside the hash table */
     71     if (dictIsRehashing(d) || d->ht[0].used > size)
     72         return DICT_ERR;
     73 
     74     dictht n; /* the new hash table */
     75         /* 获取要分配的dictht的大小 */
     76     unsigned long realsize = _dictNextPower(size);
     77 
     78     /* Rehashing to the same table size is not useful. */
     79     if (realsize == d->ht[0].size) return DICT_ERR;
     80 
     81     /* Allocate the new hash table and initialize all pointers to NULL */
     82     n.size = realsize;
     83     n.sizemask = realsize - 1;
     84     n.table = zcalloc(realsize*sizeof(dictEntry*));
     85     n.used = 0;
     86 
     87     /* Is this the first initialization? If so it's not really a rehashing
     88     * we just set the first hash table so that it can accept keys. */
     89     if (d->ht[0].table == NULL) {
     90         d->ht[0] = n;
     91         return DICT_OK;
     92     }
     93 
     94     /* Prepare a second hash table for incremental rehashing */
     95     d->ht[1] = n;
     96     d->rehashidx = 0;
     97     return DICT_OK;
     98 }
     99 
    100 /* 
    101 * hash table的容量为2的幂
    102 * 初始化大小为4
    103 */
    104 static unsigned long _dictNextPower(unsigned long size)
    105 {
    106     unsigned long i = DICT_HT_INITIAL_SIZE;
    107 
    108     if (size >= LONG_MAX) return LONG_MAX + 1LU;
    109     while (1) {
    110         if (i >= size)
    111             return i;
    112         i *= 2;
    113     }
    114 }
    115 
    116 /* 添加一个kv */
    117 dictEntry *dictAddRaw(dict *d, void *key, dictEntry **existing)
    118 {
    119     long index;
    120     dictEntry *entry;
    121     dictht *ht;
    122 
    123     if (dictIsRehashing(d)) _dictRehashStep(d);
    124 
    125     /* Get the index of the new element, or -1 if
    126     * the element already exists. */
    127     if ((index = _dictKeyIndex(d, key, dictHashKey(d, key), existing)) == -1)
    128         return NULL;
    129 
    130     /* 最新的kv放在链表的第一个,该kv最可能被访问到*/
    131     ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0];
    132     entry = zmalloc(sizeof(*entry));
    133     entry->next = ht->table[index];
    134     ht->table[index] = entry;
    135     ht->used++;
    136 
    137     /* Set the hash entry fields. */
    138     dictSetKey(d, entry, key);
    139     return entry;
    140 }
    View Code
  • 相关阅读:
    ASE19团队项目 beta阶段 model组 scrum report list
    ASE19团队项目 beta阶段 model组 scrum7 记录
    ASE19团队项目 beta阶段 model组 scrum6 记录
    ASE19团队项目 beta阶段 model组 scrum5 记录
    ASE19团队项目 beta阶段 model组 scrum4 记录
    ASE19团队项目 beta阶段 model组 scrum3 记录
    ASE19团队项目 beta阶段 model组 scrum2 记录
    ASE19团队项目 beta阶段 model组 scrum1 记录
    【ASE模型组】Hint::neural 模型与case study
    【ASE高级软件工程】第二次结对作业
  • 原文地址:https://www.cnblogs.com/coolqiyu/p/12150736.html
Copyright © 2011-2022 走看看