Redis一点基础的东西

目录

1.基础底层数据结构

2.windows下环境搭建

3.java里连接redis数据库

4.关于认证

5.redis高级功能总结

1.基础底层数据结构

1.1.简单动态字符串SDS

定义:

    struct sdshdr{
        int len;
        int free;
        char buf[];
}

优势:

为了重用部分C语言函数库功能,在buf里存储了空字符‘\0’,但是不同于C char[]的是:

  • 取sds长度时,直接从len中获取,不是像C中遍历buf,直到遇到空字符结束。
  • 在改变sds内容时,如果当前的buf能容纳得下新内容,则不重新分配内存,否则进行内存重分配,分配的原则为:当内容小于1M时,分配两倍实际大小+1(存空字符)的大小,当长度大于1M时,只多分配1M。
  • 针对sds的操作是安全的。在操作时,会首先检测buf的大小是否能完成此次操作,如果不行,则进行内存扩展。

惰性内存回收:

当sds内存缩减时,并不立即回收buf中多余的空间,而是只是修改free,len的值。

1.2.链表

同数据结构中的链表

1.3.字典(hash表)

定义:同数据结构中的hash表

解决冲突的方法:拉链法

结构:

struct dict{
        dicType *type;
        void *private;
        dictht ht[2];//rehash时,有一个做临时的存储
        int trehashidx;//在rehash时,已经保存到的index号
}dic;//字典结构,主要使用了dictht哈希表实现

哈希表结构: struct  dicht{
        dictEntry **table;
        unsigned long size;
        unsigened long sizemask;
        unsigned long used;
}dictht;

哈希表节点:  struct dictEntry{
        void *key;
        union{
        void *val;
        int64  ——tu64;;
        int64_ts64;
        }v;
        struct dictEntry *next;
}dictEntry;

rehash

保证loadfactor=1/2

实现:通过 dictht ht[2];和trehashidx;这两个变量,首先为ht[1]分配新的内存空间,然后将ht[0]中的值拷贝到ht[1]中,然后将ht[1]和ht[0]交换,释放掉ht[1],为ht[1]分配一个新的空的哈希表

在redis中,rehash是渐进的(因为如果字典中保存的键值对比较多,则rehash时,可能需要非常多的时间,所以,在每次拷贝一点后,将当前拷贝的索引号保存在trehashidx中,并且以后插入的话,直接插入到ht[1]中。在rehash过程中,每次执行一个添加,删除,查找或者更新操作后,拷贝一个trehashidx链,然后更新trehashidx,直到rehash结束,将trehashidx置为-1)

1.4.跳跃表

为了支持有序集合而实现。同数据结构中的跳跃表

优势:简单,比起红黑树,二叉平衡树来说

总结:是有序集合的底层实现

1.5.整数集合*

用来保存整数值集合的抽象数据结构,是整数集合的底层实现方式之一

定义:
struct intset{
        unit32_t  encoding;
        uint_t length;
        int8_t contends[]
}intset;

1.6.压缩列表(遍历时,是反向遍历的)

定义:构成

zlbytes:记录整个压缩列表占用的内存字节数

zltail:记录压缩列表表尾节点距离压缩列表的起始地址多少字节。通过这个,可以方便得到表尾节点的地址

zllen:节点数量

entryx:具体的节点

zlen:特殊字符,表示压缩类别结束

Entry 节点构成:

优势:节约内存

总结:用作list 和哈希表的底层实现之一

1.7.对象

定义:Redis并没有直接使用上述的数据结构,而是基于这些数据结构创建了一个对象系统,包括*字符串对象、列表对象、哈希对象、集合对象、有序集合对象这五中类型。

Redis是一个键-值对 数据库,每次在Redis数据库中创建一个新的键值对时,Redis至少会创建两个对象,一个是对象的key对象,另一个是value对象。*

对于key来说,就是一个字符串对象,value可以为上面说的5中对象之一。

结构:

 struct redisObject{
        unsigned type:4;// 表面的类型
        unsigned encoding:4;//底层实现时,使用的类型
        void *ptr;//指向底层额数据结构指针

使用type 命令可以查看对象的类型(看的是value的类型)

type和encoding:

关于Redis_Encoding_raw 和 Redis_Encoding_embstr: 都是sds对象,只是embstr用来存储字符串长度小于等于32字节的字符串值。但是,在使用embstr类型保存对象时,只调用一次内存分配函数,直接分配redisobject 和sdshdr内存,而使用raw时,需要两次内存分配,第一次为redisobject分配内存,另一次为sdshdr分配内存。embstr是用来优化小字符串的。

不同value类型支持的操作:

string:
        set:
        get:
        setrange:
        getrange:
        append:
        incrbyfloat:只支持能转化成数值型的value
        incrby::只支持能转化成数值型的value
        decrby::只支持能转化成数值型的value
        strlen:
list:
        lpush:
        rpush:
        lpop:
        rpop:
        lindex:
        llen:
        linsert:
        ltrim::
        lset:
hash:
        hset:
        hget:
        hexists:
        hdel:
        hlen:
        hgetall:
set:
        sadd:
        scard:返回键数量
        sismember:
        smembers:遍历整个集合,返回集合元素
        srandmember:随机返回一个元素
        spop:
        srem:
        :
        :
zset:
        zadd:
        zcard:
        zcount:
        zrange:从表头到表尾遍历整个列表,返回给定索引范围内的所有元素。
        zrevrange:
        zrank:
        zrevrank:
        zrem:
        zscore:

2.windows下环境搭建

2.

下载地址github.com/dmajkic/redis/downloads

  • 在列表中搜索,下载到的Redis支持32bit和64bit。
  • 根据自己实际情况选择,我选择32bit。把32bit文件内容拷贝到需要安装的目录下,比如:D:\dev\redis-2.4.5。
  • 打开一个cmd窗口,使用cd命令切换到指定目录(D:\dev\redis-2.4.5)运行 redis-server.exe redis.conf 。
  • 重新打开一个cmd窗口,使用cd命令切换到指定目录(D:\dev\redis-2.4.5)运行 redis-cli.exe -h 127.0.0.1 -p 6379,其中 127.0.0.1是本地ip,6379是redis服务端的默认端口。这样,Redis windows环境下搭建已经完成。

    (其实本机测试的话,直接运行redis-cli.exe就可以了,会默认连接到本机的server上去)

3.java里连接redis数据库

3.1关于Jedis

需要导入jedis jar包

关于Jedis: Redis的java版客户端实现

3.2实例

        //连接redis服务器,192.168.0.100:6379
        jedis = new Jedis("127.0.0.1", 6379);

        jedis.auth("password");
 jedis.set("name","xinxin");//向key-->name中放入了value-->xinxin
        System.out.println(jedis.get("name"));//执行结果:xinxin  

        jedis.append("name", " is my lover"); //拼接
        System.out.println(jedis.get("name")); 

        jedis.del("name");  //删除某个键
        System.out.println(jedis.get("name"));
        //设置多个键值对
        jedis.mset("name","liuling","age","23","qq","476777XXX");
        jedis.incr("age"); //进行加1操作
        System.out.println(jedis.get("name") + "-" + jedis.get("age") + "-" + jedis.get("qq"));

3.3.使用jedis进行事务操作

   //连接redis服务器,192.168.0.100:6379
        jedis = new Jedis("127.0.0.1", 6379);
        jedis.auth("password");
            Transaction t = jedis.multi();
            // 开启事务,当server端收到multi指令
            // 会将该client的命令放入一个队列,然后依次执行,知道收到exec指令
            String key="a";
            String value="hello world";
            t.set(key, value)   ;
            t.set(key+key, value)   ;
            t.set(key+key+key, value)   ;
            t.set(key+key+key, value)   ;
            t.set(key+key+key, value)   ;
         String ret = (String) t.exec().get(0);
        if(ret!=null)
                System.out.println(ret);

关于Redis的认证问题

如果要使用认证功能的话,则redis启动时,要开启认证功能

4.关于认证

redis启动时,如果不指定服务器配置文件,则是不需要认证的。

需要认证时,需要在配置文件中配置,加入一行 :requirepass yourpassword

然后以该配置文件启动redis.server.exe,如:

redis-server.exe redis.conf

客户端连接时,在启动 redis-cli.exe后,首先需要执行auth命令,不然,其他命令都不会执行,见:

这里输入的密码为你在配置文件中配置的密码(由此可见,所有的客户应该都是共用一个密码的)

5.redis高级功能总结

5.1 1.Redis数据库

Redis服务器中的所有数据库都保存在服务器状态redisServer数据结构中

struct redisServer{
        int dbnum;
        redisDb *db;
...}

在初始化时,服务器根据服务器状态dbnum属性来决定创建多少个数据库,默认为16个。

客户端使用select dbnum来切换数据库,如select 2

另外,当前redis数据库版本没有办法知道当前处于那个数据库中,因此如果应用需要经常切换数据库,为了保证操作的数据库正确,应该多执行select dbnum指令,显示表明自己操作的数据库。

在Redis中,其实每个数据库里面的内容都是使用一个字典来保存的,见redisdb数据结构

struct redisDb{
        dict *dict;//保存数据库键空间
        dict *expires;//过期字典
        dict *watched_keys;//正在被监视的键
  };

5.2.Redis数据库的键的过期时间

可以通过 expire 或是 pexpire命令设置键的失效,如:

set key value
expire key 5
//5秒之后
get key
//输出 nil

redisDb中的expires结构保存了数据库中所有键的过期时间

可以通过persist命令移除一个键的过期时间(即不加过期约束),如:

persist key

Redis过期键删除策略

同时使用惰性删除策略(使用时,检测键是否过期,过期,则删除,同时返回nil给客户端),定期删除测试(定期运行程序来删除过期键)

惰性删除:所有读写数据库的redis命令执行之前都会检测键是否过期。

定期删除:在周期性执行的函数serverCron函数中,都会调用键过期检测函数(activeExpireCycle)。

关于函数activeExpireCycle:并不检查所有过期字典中的键,而是随机的取出一定数量的键检测,并删除其中的过期键。全局变量current_db会记录当前函数检测的进度,下一次调用该函数时,会接着检测。

5. 3.Redis数据库的持久化

Redis可设置定期保存任务,服务器维持一个dirty计数和lastsave属性。如在配置文件中配置:

 save 900 1
 save 300 1
 save 60  10000 //在60s内进行了10000次修改就保存一次

同时Redis可通过命令方式,主动发起保存,命令有:save,bgsave。其中bgsave是通过子进程方式来执行保存任务,save是通过主进程来执行保存任务,会阻塞当前操作。

保存的方式:

有两种方式:AOP,RDB

RDB:直接导出存储数据库的当前状态

AOP:保存的是数据库中执行的命令。以AOP方式进行持久化时,可以执行重写优化(本来aop会保存所有执行过的命令,但是这样太多。因此在重写时,会根据当前状态,生成相应的指令,保存这些指令,这些指令会保存在一个新文件中,在保存完后,替换原来的文件)

5.4.Redis数据库的事件

分为两种:文件事件,时间事件

文件事件:是对套接字的操作的抽象,分为读事件,写事件。

时间事件:服务器将所有的时间事件放在一个无序链表中,每当时间事件执行器运行时,就遍历这个链表,指向达到的事件。典型的时间事件为serverCron

5. 5.Redis服务器的程序的伪代码

 main()
        {
            init_server();
            while server_is_not_shutdown(): aeprecessEvents();
             clean_server();
        }

    aeprecessEvents()
        {
        time_event=aesearchNearestTimer();获得离当前时间最近的一个时间事件
       //获取这个事件离当前时间的距离
         remaid_ms=time_event.when  -unix_ts_now();

        if(remaid_ms<0)//如果已经达到
            remaid_ms=0;
        //创建时间结构体
        timeval=create_timeval_with_ms(remaind_ms)

        //阻塞并等待文件事件的发生,最大阻塞时间由传入的timeval结构觉得,如果remaind_ms的值为0,那么aeAPIpoll调用之后马上返回,不阻塞
        aeAPIpoll(timeval);

        //处理文件事件
        processfileEvents();
        //处理时间事件
        processTimeEvents();
        }

总结:

文件事件和时间事件是同步,有序,原子的执行的,不会中途中断处理事件,也没有抢占机制。

服务器在一般情况下,只会执行一个时间时间

时间事件的实际处理通常会比设定的达到时间晚一些。

5. 6.Redis数据库的事务

Redis数据库通过multi,exec,watch命令来实现事务功能,将多个命令请求打包,然后一次性的、按顺序的执行多个命令。

例子:

一个事务会经历三个阶段:(redis的每个客户端都会有自己的事务状态,保存事务的队列信息)

  • a.开始事务
  • b.事务入队
  • c.事务执行

命令的处理流程:

使用watch命令监视数据库键:

当你开启了事务,且还没有提交事务时,使用watch命令监视你要操作的键。如果事务提交之前,监视的键被别的客户端修改了,则你的时候就会失效。

判断事务的安全性:

redis数据库redisDb数据结构中的 dict *watched_keys字典保存该数据库被监视的键,通过这个字典,能知道那个键被那个客户端监视,当这些键被修改后,将对应的客户端的redis_dirty_cas标志置位。但该客户端提交事务时,会检查这个标志。

Redis事务的特性

Redis事务不具有持久性。且不支持回滚。

当一个事务的命令在入队时,出现了错误,如命令不存在或是参数不对,则Redis拒绝执行这个事务(还是可以提交这个事务,但是你执行exec时,会报错)

当事务在执行时,如果某个命令出错,不会中断该事务其他命令的执行,也不会回滚该事务的错误操作,且出错的命令不会影响后面命令的执行。

时间: 2024-08-06 16:04:32

Redis一点基础的东西的相关文章

一点基础知识

1.肉鸡:所谓“肉鸡”是一种很形象的比喻,比喻那些可以随意被我们控制的电脑,对方可以是WINDOWS系统,也可以是UNIX/LINUX系统,可以是普通的个人电脑,也可以是大型的服务器,我们可以象操作自己的电脑那样来操作它们,而不被对方所发觉.2.木马:就是那些表面上伪装成了正常的程序,但是当这些被程序运行时,就会获取系统的整个控制权限.有很多黑客就是热中与使用木马程序来控制别人的电脑,比如灰鸽子,黑洞,PcShare等等.3.网页木马:表面上伪装成普通的网页文件或是将而已的代码直接插入到正常的网

cocos2d(3.0)一些基础的东西

1.创建项目后环境配置: 附加文件夹:加入 $(EngineRoot) $(EngineRoot)cocos $(EngineRoot)cocos\editor-support $(EngineRoot)build\Debug.win32 ..\proj.win32 通用属性加入 (先从 cocos2d-x-3.0rc0 中 extensions   cocos\editor-support   cocos\ui 加入进去) libcocosstudio libExtensions libGUI

一些基础的东西总结一下

1.string类型转Date类型 SimpleFormatDate sdf = new SimpleFormatDate("yyyy-MM-dd"); Date date = sdf.parse(dateString); 2.disabled 和 readonly的区别 当表单提交的时候,使用了disabled的表单元素的值是不会被提交的,而readonly的则可以 3.处于$(function(){})里面的js函数外部js是调用不到的 4.ctrl + shift + P 快速定

回归基础的东西,不能只是“感觉会了”

很多时候,觉得自己掌握的东西还是很少,做事情的效率还不是很高,希望自己能够成长起来,认认真真做事. -------------------------------------------------------------------------------------------------------------------------------------------- Javascript声明变量的时候,虽然用var关键字声明和不用关键字声明,很多时候运行并没有问题,但是这两种方式还是

redis使用基础(九) ——Redis虚拟内存

redis使用基础(九) --Redis虚拟内存 (转载请附上本文链接--linhxx) 一.概述 Redis的数据是保存在内存中,当物理内存不足,其会保存在虚拟内存(VM)中.Redis的vm类似操作系统的vm,其会把所有的键都存在内存中,而把部分很少被访问到的值放在硬盘中. 操作系统的vm是基于页的概念,linux每个页4KB,而redis很多对象远小于4KB.另外,redis将交换到磁盘的对象压缩,保存到磁盘的对象可以去除指针和对象元数据,这样可以减少很多的I/O操作. redis的虚拟内

redis使用基础(六) ——Redis集群

redis使用基础(六) --Redis集群 (转载请附上本文链接--linhxx) 一.单台服务器 单台redis服务器,会出现单点故障,且需要承受所有的负载.另外,所有的内容都存在单个服务器上,该服务器会成为瓶颈. 使用多台服务器作为redis服务器,需要考虑集群管理,如数据一致性.增加节点.故障恢复等问题.redis对处理这些问题有一套方案. 二.复制 redis的持久化功能保证了数据的持久性,但是如果服务器故障,数据还是可能会丢失,因此需要将数据备份到其他服务器.当一台服务器内容更新,会

redis使用基础(十) ——Redis存储Session

redis使用基础(十) --Redis存储Session (转载请附上本文链接--linhxx) 一.概述 PHP默认是将session存于服务器的文件中.当并发量大,此方式效率低,因此可以采用redis存储session. 要改变session的存储位置,首先要改变php.ini中的配置项session.save_handler,将其值设置为user. 二.改变存储位置函数 php内置的函数session_set_save_handler可以重新设定session的保存方式,包括sessio

redis使用基础(二) ——Redis数据类型

redis使用基础(二) --Redis数据类型 (转载请附上本文链接--linhxx)  一.概述 Redis是一种Key-Value类型的数据库,属于非关系型数据库,NoSQL的一种.Redis共有5种数据类型:字符串(string).散列(hash).列表(list).集合(set).有序集合(zset). 1.通配符 Redis支持部分通配符,包括?.*.[].\x,和正则表达式一致,?表示匹配0或1个,*匹配任意个,[]匹配框内的任意一个内容,\x转义,例如\?表示匹配?. 2.获取键

redis使用基础(四) ——Redis排序与消息通知

redis使用基础(四) --Redis排序与消息通知 (转载请附上本文链接--linhxx) 一.排序 1.命令 SORT key [ALPHA] [DESC] [LIMIT start end],对列表.集合和有序集合进行排序,当加上alpha参数后,则可以按照字典顺序排序,加上desc则倒序排序,加上limit则支持分页. 2.关键参数 by参数:by key:*->val,可以指定排序的标准,可以自己传入一个list,也可以指定某个列进行排序. get参数:get key:*->val