Redis基础安装、命令、持久化(基础-番外篇)

Redis安装、数据结构、命令、Jedis操作、持久化

Redis

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。
Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

默认开启,会按照配置的指定时间将内存中的数据快照到磁盘中,创建一个dump.rdb文件,Redis启动时再恢复到内存中。
Redis会单独创建fork()一个子进程,将当前父进程的数据库数据复制到子进程的内存中,然后由子进程写入到临时文件中,持久化的过程结束了,再用这个临时文件替换上次的快照文件,然后子进程退出,内存释放。
需要注意的是,每次快照持久化都会将主进程的数据库数据复制一遍,导致内存开销加倍,若此时内存不足,则会阻塞服务器运行,直到复制结束释放内存;都会将内存数据完整写入磁盘一次,所以如果数据量大的话,而且写操作频繁,必然会引起大量的磁盘I/O操作,严重影响性能,并且最后一次持久化后的数据可能会丢失;

Redis官网
Redis中文网
Redis下载地址
本文使用Redis-x64-3.2.100版本。本文使用版本
Redis基础安装、命令、持久化(基础-番外篇)

Redis基础安装、命令、持久化(基础-番外篇)
Redis官网响应较慢的可以用中文网下载,本人下载的Redis-x64-3.2.100本进行学习,下载完解压即可,无需安装。
Redis基础安装、命令、持久化(基础-番外篇)如上图所示,解压后的目录结构。

  1. redis-server.exe为服务端;
  2. redis-cli.exe为客户端。
  3. redis.windows.conf为配置文件;

一、Redis为什么效率快

  1. Redis是纯内存数据库,一般都是简单的存取操作,线程占用的时间很多,时间的花费主要集中在IO上,所以读取速度快。(纯内存操作
  2. 使用的是非阻塞IO,IO多路复用,使用了单线程来轮询描述符,将数据库的开、关、读、写都转换成了事件,减少了线程切换时上下文的切换和竞争。(单线程操作,避免了频繁的上下文切换
  3. 采用了单线程的模型,保证了每个操作的原子性,也减少了线程的上下文切换和竞争。(非阻塞I/O多路复用机制
  4. 采用自己实现的事件分离器,效率比较高,内部采用非阻塞的执行方式,吞吐能力比较大。
  5. 全程使用hash(key-value)结构,读取速度快,还有一些特殊的数据结构,对数据存储进行了优化,如压缩表,对短数据进行压缩存储,再如,跳表,使用有序的数据结构加快读取的速度。

二、Redis的数据结构及命令

字符串(strings)

  • 设置:

    • set key value (设置的key相同时,覆盖之前的值)
      127.0.0.1:6379> set username zhangsan
      Redis基础安装、命令、持久化(基础-番外篇)
  • 查询:

    • get key
      127.0.0.1:6379> get username
      Redis基础安装、命令、持久化(基础-番外篇)
  • 删除:
    • del key
      127.0.0.1:6379> del username
      Redis基础安装、命令、持久化(基础-番外篇)

散列(hashes)

  • 设置:
    • hset key field value (设置的值里面又是一个键值对)
      127.0.0.1:6379> hset user name zhangsan
      Redis基础安装、命令、持久化(基础-番外篇)
  • 查询:
    • hget key field
      127.0.0.1:6379> hget user name
      127.0.0.1:6379> hget user age
      Redis基础安装、命令、持久化(基础-番外篇)
  • 删除:
    • hdel key field
      127.0.0.1:6379> hdel user name
      Redis基础安装、命令、持久化(基础-番外篇)
  • 查询所有:
    • hgetall key
      127.0.0.1:6379> hgetall user
      Redis基础安装、命令、持久化(基础-番外篇)

列表(lists)

  • 设置:
    • lpush key value1 将一个或多个值插入到列表头部。
      127.0.0.1:6379> lpush username zhangsan
      Redis基础安装、命令、持久化(基础-番外篇)
    • rpush key value1 将一个或多个值插入到列表尾部。
      127.0.0.1:6379> rpush username lisi
      Redis基础安装、命令、持久化(基础-番外篇)
  • 查询:
    • lrange key start end
      127.0.0.1:6379> lrange username 0 -1
      Redis基础安装、命令、持久化(基础-番外篇)
  • 删除:
    • lpop key 从列表头部移除一个元素,并返回移除的值
      127.0.0.1:6379> lpop username
      Redis基础安装、命令、持久化(基础-番外篇)
    • rpop key 从列表尾部移除一个元素,并返回移除的值
      127.0.0.1:6379> rpop username
      Redis基础安装、命令、持久化(基础-番外篇)

集合(sets)(无序集合)

  • 设置:
    • sadd key value
      127.0.0.1:6379> sadd username zhangsan
      127.0.0.1:6379> sadd username lisi
      Redis基础安装、命令、持久化(基础-番外篇)
  • 查询:
    • smembers key
      127.0.0.1:6379> smembers username
      Redis基础安装、命令、持久化(基础-番外篇)
  • 删除:
    • del key(移除并返回集合中的一个随机元素)
      127.0.0.1:6379> del username
      Redis基础安装、命令、持久化(基础-番外篇)

有序集合(sorted sets)

  • 设置:

    • zadd key score value (scoure分数用来排序)
      127.0.0.1:6379> zadd username 10 zhangsan
      127.0.0.1:6379> zadd username 18 lisi
      127.0.0.1:6379> zadd username 5 wangwu
      Redis基础安装、命令、持久化(基础-番外篇)
  • 查询:

    • zrange key start end(可以看到是根据分数排序的)
      127.0.0.1:6379> zrange username 0 -1
      Redis基础安装、命令、持久化(基础-番外篇)
  • 删除:

    • zrem key value
      127.0.0.1:6379> zrem username zhangsan
      Redis基础安装、命令、持久化(基础-番外篇)

全局常用命令

  • keys * (查询所有key值)
  • type key (查询key的类型)

三、持久化

  • Redis本身运行时数据保存在内存中,支持RDBAOF两种持久化机制(这两种方式可以单独使用其中一种,或者混合使用),持久化功能有效地避免因进程退出造成的数据丢失问题,当下次重启时利用之前持久化的文件即可实现数据恢复。Redis默认就采用了一种持久化方式,即RDB。(Redis持久化的优先级:AOF>RDB)

RDB持久化(默认)

Redis默认支持RDB持久化。

  • RDB方式是通过快照完成的,一段时间内Redis会自动将内存中的所有数据进行快照,并且存储到硬盘上(进行快照的条件在配置文件中指定)。当下次启动redis的时候,回去读取硬盘上的快照恢复数据,进而实现Redis的持久化。

持久化时,会在指定的目录中生成一个.rdb结尾的快照文件。

redis.conf配置文件

  • 设置触发条件:
    Redis基础安装、命令、持久化(基础-番外篇)
    Redis基础安装、命令、持久化(基础-番外篇)
  • 设置rdb文件路径:
    Redis基础安装、命令、持久化(基础-番外篇)

测试

  1. 修改配置文件
    Redis基础安装、命令、持久化(基础-番外篇)

  2. 启动Redis服务,指定配置文件
    Redis基础安装、命令、持久化(基础-番外篇)

  3. 启动客户端,触发持久化
    Redis基础安装、命令、持久化(基础-番外篇)

  4. 验证
    Redis基础安装、命令、持久化(基础-番外篇)

  5. 关闭服务重新打开(直接获取可获得值)
    Redis基础安装、命令、持久化(基础-番外篇)

AOF持久化(耗内存,不建议)

  • RDB方式不能提供强一致性,如果Redis进程崩溃,那么两次RDB之间的数据也随之消失。那么AOF的出现很好的解决了数据持久化的实时性,AOF以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令来恢复数据。AOF会先把命令追加在AOF缓冲区,然后根据对应策略写入硬盘(appendfsync)。

Redis主进程fork子进程来执行AOF重写,这个子进程创建新的AOF文件来存储重写结果,防止影响旧文件。因为fork采用了写时复制机制,子进程不能访问在其被创建出来之后产生的新数据。Redis使用“AOF重写缓冲区”保存这部分新数据,最后父进程将AOF重写缓冲区的数据写入新的AOF文件中然后使用新AOF文件替换老文件。

以日志的形式记录每个写操作(读操作不记录),只需追加文件但不可以改写文件,Redis启动时会根据日志从头到尾全部执行一遍以完成数据的恢复工作。包括flushDB也会执行。
主要有两种方式触发:有写操作就写、每秒定时写(也会丢数据)。
因为AOF采用追加的方式,所以文件会越来越大,针对这个问题,新增了重写机制,就是当日志文件大到一定程度的时候,会fork出一条新进程来遍历进程内存中的数据,每条记录对应一条set语句,写到临时文件中,然后再替换到旧的日志文件(类似rdb的操作方式)。默认触发是当aof文件大小是上次重写后大小的一倍且文件大于64M时触发。
当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。一般情况下,只要使用默认开启的RDB即可,因为相对于AOF,RDB便于进行数据库备份,并且恢复数据集的速度也要快很多。
开启持久化缓存机制,对性能会有一定的影响,特别是当设置的内存满了的时候,更是下降到几百reqs/s。所以如果只是用来做缓存的话,可以关掉持久化。

  1. 配置文件修改

    • always:命令写入aof缓冲区后,每一次写入都需要同步,直到写入磁盘(阻塞,系统调用fsync)结束后返回。显然和Redis高性能背道而驰,不建议配置。
    • everysec:命令写入aof缓冲区后,在写入系统缓冲区直接返回(系统调用write),然后有专门线程每秒执行写入磁盘(阻塞,系统调用fsync)后返回。
    • no:命令写入aof缓冲区后,在写入系统缓冲区直接返回(系统调用write)。之后写入磁盘(阻塞,系统调用fsync)的操作由操作系统负责,通常最长30s。
      Redis基础安装、命令、持久化(基础-番外篇)
  2. 启动Redis服务时指定配置文件
    Redis基础安装、命令、持久化(基础-番外篇)

  3. 启动客户端,触发持久化
    Redis基础安装、命令、持久化(基础-番外篇)

  4. 验证
    Redis基础安装、命令、持久化(基础-番外篇)

  5. 关闭服务重新打开(直接获取可获得值)
    Redis基础安装、命令、持久化(基础-番外篇)

四、Java操作Redis

下载 jedis.jar

Java工程目录结构:
Redis基础安装、命令、持久化(基础-番外篇)

字符串(strings)

	@Test
	public void test_String() {
		Jedis jedis = new Jedis();
		jedis.set("username", "zhangsan");
		System.out.println(jedis.get("username"));
	}

Redis基础安装、命令、持久化(基础-番外篇)

散列(hashes)

	@Test
	public void test_Hash() {
		Jedis jedis = new Jedis();
		jedis.hset("user", "name", "mengmeng");
		jedis.hset("user", "age", "18");
		System.out.println(jedis.hget("user", "name"));
		System.out.println(jedis.hget("user", "age"));
		System.out.println(jedis.hgetAll("user").toString());
	}

Redis基础安装、命令、持久化(基础-番外篇)

列表(lists)

	@Test
	public void test_list() {
		Jedis jedis = new Jedis();
		jedis.lpush("list", "hehe"); 	// hehe
		jedis.lpush("list", "1111"); 	// 1111, hehe
		jedis.rpush("list", "heihei");	// 1111, hehe, heihei
		jedis.rpush("list", "xixi");	// 1111, hehe, heihei, xixi
		System.out.println(jedis.lrange("list", 0, -1));
		System.out.println(jedis.lpop("list"));
		System.out.println(jedis.lrange("list", 0, -1));
		System.out.println(jedis.rpop("list"));
		System.out.println(jedis.lrange("list", 0, -1));
	}

Redis基础安装、命令、持久化(基础-番外篇)

集合(sets)(无序集合)

@Test
	public void test_set() {
		Jedis jedis = new Jedis();
		jedis.sadd("setdemo", "zhangsan", "lisi", "wangwu", "zhaoliu");
		System.out.println(jedis.smembers("setdemo"));
		System.out.println(jedis.srem("setdemo", "lisi"));
		System.out.println(jedis.smembers("setdemo"));
	}

Redis基础安装、命令、持久化(基础-番外篇)

有序集合(sorted sets)

	@Test
	public void test_sortedset() {
		Jedis jedis = new Jedis();
		jedis.zadd("sortedset", 10, "zhangsan");
		jedis.zadd("sortedset", 12, "list");
		jedis.zadd("sortedset", 2, "wangwu");
		jedis.zadd("sortedset", 80, "zhanxing");
		System.out.println(jedis.zrange("sortedset", 0, -1));
		System.out.println(jedis.zrem("sortedset", "wangwu"));
		System.out.println(jedis.zrange("sortedset", 0, -1));
	}

Redis基础安装、命令、持久化(基础-番外篇)

上一篇:Redis实现分布式锁(单机版)


下一篇:Jedis的基本操作