【搞定Redis】第1篇:Redis基础知识

首先推荐一个Redis的学习网站:http://www.redis.net.cn/

目  录:

一、基本概念

二、Redis的下载及安装

三、Redis的常用操作

1、redis数据类型

2、Redis常用命令

四、Redis的持久化方案

1、Rdb方式

2、Aof方式

五、Redis的主从复制

六、Redis集群


一、基本概念

1、什么是NoSql?

Redis是NoSql的一种,那么要了解Redis之前,我们就必须知道NoSql到底是什么意思:

NoSql:非关系型数据库,它的全名叫做Not only Sql。它不能替代关系型数据库,只能作为关系型数据库的一个良好的补充。它主要是为了解决高并发、高可用、高扩展、大数据存储等一系列问题而产生的数据库解决方案

2、什么是Redis?

redis是内存高速缓存的数据库(C语言开发),redis内部有多个数据库(在redis-conf文件中有配置,用户可以通过select 下标来选择数据库),它保存的数据模型为key-value,支持String、Hash、List、Set、Sortedset等类型。redis可将数据从内存持久化到硬盘,保证了数据安全,最重要的是使用缓存减轻了数据库的负载。

redis的应用场景:

1、缓存:数据查询、短连接、新闻内容、商品内容等等;【用的最多】

2、分布式集群架构中的session分离;

3、任务队列:秒杀、抢购、12306抢票等等。

3、什么是缓存

在开发网站的时候,如果有一些数据在短时间之内不会发生变化,而他们还要被频繁访问为了提高用户的请求速度和降低网站的负载,就把这些数据放到一个读取速度更快的介质上(或者是通过较少的计算量就可以获得该数据),该行为就称作对数据的缓存。该介质可以是文件、数据库、内存。内存经常用于数据缓存。

缓存的两种形式 :

1、页面缓存:经常用在CMS内存管理系统里边,如新闻页面,内容主体单一集中 (smarty页面缓存–>将页面缓存成静态); 

2、数据缓存:经常用在页面的具体数据里边。比如商品页面的组成部分根据业务特点(如热卖、推荐、正常商品),各个部分数据比较独立,适合给他们分别数据缓存;


二、Redis的下载及安装

redis官网:http://redis.io/

redis下载:http://download.redis.io/releases/

Linux系统安装可以参考:https://www.jb51.net/article/79096.htm

1、启动和关闭

redis共有三种启动方式:前端启动、后端启动以及redis自带的客户端启动。

  • 前端启动和关闭:
前端启动的命令:
[root@pc bin]# ./redis-server
前端启动的关闭:
    强制关闭:Ctrl+c
    正常关闭:[root@pc bin]# ./redis-cli shutdown

需要说明的是:如果采用前端启动,一旦客户端关闭,则redis服务也就停掉了。

  • 后端启动和关闭:
后端启动四步:
    第一步:需要将redis解压之后的源码包中的redis.conf文件拷贝到bin目录下
    [root@pc bin]# cp /root/redis-3.0.0/redis.conf ./

    第二步:vim redis.conf:修改redis.conf文件,将daemonize改为yes

    第三步:使用命令后端启动redis
    [root@pc bin]# ./redis-server redis.conf

    第四步:查看是否启动成功
    [root@pc bin]# ps -aux | grep redis

后端关闭:
强制关闭:[root@pc bin]# kill -9 进程号
正常关闭:[root@pc bin]# ./redis-cli shutdown
  • redis自带客户端启动
启动客户端命令:
[root@pc bin]# ./redis-cli -h 127.0.0.1 -p 6379

还可以写成:
[root@pc bin]# ./redis-cli

关闭
Ctrl+c
或者:
127.0.0.1:6379> quit

最后补充一种Java的redis客户端:Jedis客户端

Jedis下载地址:https://github.com/xetorthio/jedis

需要两个Jar包:commons-pool2-2.3.jar 和 jedis-2.7.0.jar

package com.zju.jedis.client;

import java.util.HashSet;
import java.util.Set;

import org.junit.Test;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;

public class JedisClient {

	/**
	 * 单实例连接
	 */
	@Test
	public void jedisClient(){
		// 连接到Rdeis
		Jedis jedis = new Jedis("192.168.253.129", 6379);
		// 通过jedis赋值
		jedis.set("s3", "333");
		// 通过jedis取值
		String result = jedis.get("s3");
		System.out.println(result);
		// 关闭jedis
		jedis.close();
	}
	
	/**
	 * 使用jedis连接池连接redis服务器
	 */
	@Test
	public void jedisPool(){
		// 连接到redis
		JedisPool pool = new JedisPool("192.168.253.129", 6379);
		// 从连接池中获取一个jedis对象
		Jedis jedis = pool.getResource();
		
		jedis.set("s4", "444");
		String result = jedis.get("s4");
		System.out.println(result);
		
		// 关闭jedis客户端
		jedis.close();
		
		// 关闭连接池
		pool.close();
	}
	
	/**
	 * 使用jedis连接redis集群
	 */
	@Test
	public void jedisCluster(){
		// 创建jedisCluster
		Set<HostAndPort> nodes = new HashSet<>();
		nodes.add(new HostAndPort("192.168.253.129", 7001));
		nodes.add(new HostAndPort("192.168.253.129", 7002));
		nodes.add(new HostAndPort("192.168.253.129", 7003));
		nodes.add(new HostAndPort("192.168.253.129", 7004));
		nodes.add(new HostAndPort("192.168.253.129", 7005));
		nodes.add(new HostAndPort("192.168.253.129", 7006));
		
		JedisCluster cluster = new JedisCluster(nodes);
		cluster.set("s9", "999");
		
		String result = cluster.get("s9");
		System.out.println(result);
		
		cluster.close();
	}
}

三、Redis的常用操作

1、redis数据类型

  • String

键值:设置值通过字符串名
set:设置键值 

setnx(set not exist):设置键值|若键不存在则可以存,否则返回0.

setex(set expire):设置键值(含过期时间),set key seconeds value

setrange:设置指定位置key的键值 例如setrange name diaodiao 2 haha-->dihahaao 从第二个位置开始替换

mset:设置多个键值

msetnx:设置多个不存在的键值

get:通过键获得值

getset:先通过键获得值,再设置值。

getrange(0~-1):获取指定范围的字符。范围|从左往右数从0开始 从右往左数-1开始。例如:hello(0~4|-5~-1)

mget:获得多个键的值。

数字类型相关操作
set age 10(以下操作都是针对10操作)

incr 递增1 incr age-->11 

incrby 递增指定数字-->incr age 5->16

decr 递减1

decrby 递减指定值

字符属性操作
set name "hello"
append:在尾部追加字符串 append name "Diaodiao"->helloDiaodiao

strlen: 获得字符串长度 strlen name ->5
  • Hash

Hash叫做散列类型,它提供了字段和字段值之间的映射。字段值只能是字符串类型:

可以看作是:字段是建的value,但是字段同时又是字段值的key,即字段值是字段的value。

1 配置(redis.conf配置文件中)
默认:
hash-max-zipmap-entries 配置字段最多64个(key的个数)
hash-max-zipmap-value 配置value最大为512字节

2 命令(参考String)
hset key field value

hset:若key不存在就创建,否则覆盖。

hsetnx:设置 hash field 为指定值,如果 key 不存在,则先创建。如果 field 已经存在,返回 0,nx 是
not exist 的意思。

hmset:同时设置多个field

hget:获取指定的hash field

hmget:获取多个指定的hash field

hexists:测试指定field是否存在

hlen:返回指定的field的个数

hdel:删除指定field。

hkeys:查询指定key的所有field

hvals:获取指定key的所有value

hgetall:获得指定key的所有field以及值
  • List

redis的list是采用链表来存储数据的,所以对redis的list数据类型的操作,都是操作list的两端数据来操作的。

lpush:在key对应的list的头部添加元素。

rpush:在key对应的list的尾部添加元素

lrange:获得list范围的值。 lrange mylist start(0) stop(2)(获取0 1 2索引的值)

linsert:在key对应的特定位置之前或者之后添加字符串元素 linsert mylist before “world” “hello”

lset:设置list指定下表的元素(从0开始)

lrem:从key对应的list里,删除count个value相同的元素。

ltrim:保留指定key的值范围内的数据。

lpop:从list的头部删除元素,并且返回删除元素

rpop:从list的尾部删除元素,并且返回删除元素

rpoplpush:第一个list的尾部移除元素并且添加到第二个list的头部

lindex:返回名称为key的list中index位置的元素

llen:返回key对应list的长度
  • Set

Set是无序不可重复的集合,通过hashtable实现。

sadd:向名称为key的set当中添加元素

srem:删除名称为key的元素

spop:随机返回并且删除set中某key元素

sdiff:两个set的差集

sdiffstore:假设有set3、set1、set2-->set1与set2差集返回的元素,添加到set3中

sinter:两个set的交集

sinterstore:假设有set3、set1、set2-->set1与set2交集返回的元素,添加到set3中

sunion:两个set的并集

sunionstore:假设有set3、set1、set2-->set1与set2交集返回的元素,添加到set3中

smove:假设有set1、set2-->删除set1的某个key值,并且添加到set2

scard:返回set的元素个数

sismember:测试set中是否存在某member(元素)。

srandmember:随机返回一个元素,但是不删除
  • SortedSet

SortedSet(skip list|双向链表和hashtable的结合体)是set的一个升级版本,升级版本的sets,有两个纬度,一个纬度用来存顺序,一个纬度用于存value。

SortedSort和Set的不同之处是会给set中的元素添加一个分数,然后通过这个分数进行排序。

zadd:向名称为key的zset中添加元素member、score用于排序。如果该元素存在,则根据score更新该元素的顺序

zrem:删除名为key的zset的元素member

zincrby:如果在名称为 key 的 zset 中已经存在元素 member,则该元素的 score 增加 increment;否则向集合中添加该元素,其 score 的值为 increment

zrank:返回名称为 key 的 zset 中 member 元素的排名(按 score 从小到大排序)即下标

zrevrank:返回名称为 key 的 zset 中 member 元素的排名(按 score 从大到小排序)即下标

zrange:返回名称为 key 的 zset(按 score 从小到大排序)中的 index 从 start 到 end 的所有元素

zrevrange:返回名称为 key 的 zset(按 score 从大到小排序)中的 index 从 start 到 end 的所有元素

zrangebyscore:返回集合中 score 在给定区间的元素

zcount:返回集合中 score 在给定区间的数量

zcard:返回集合中元素个数

zscore:返回给定元素对应的 score

zremrangebyrank:删除集合中排名在给定区间的元素

zremrangebytscore:删除集合中 score 在给定区间的元素

2、Redis常用命令

1、键值相关命令
keys pattern*   // 返回满足给定pattern的所有key

exists key:确认一个 key 是否存在

del key:删除一个 key

expire key seconeds:设置一个 key 的过期时间(单位:秒)

move:将当前数据库中的 key 转移到其它数据库中。

persist:移除给定 key 的过期时间

ttl:查看过期还需要多长时间

randomkey:随机返回命名空间的一个key

renamekey:重命名key

type:返回值类型

2、服务器相关命令
ping:测试连接是否存活

echo:在命令行打印一些内容

select:选择数据库。Redis 数据库编号从 0~15,我们可以选择任意一个数据库来进行数据的存取

quit:退出连接

dbsize:返回当前数据库中 key 的数目

info:获取服务器的信息和统计

monitor:实时转储收到的请求

config:获取服务器配置信息

flushdb:删除当前选择数据库中的所有 key

flushall:删除所有数据库中的所有 key

四、Redis的持久化方案

redis一般都是做缓存用的,所以存储在内存中。但是开关机后内存就没有了,所以需要对redis中的数据进行持久化。

redis两种持久化方法:Rdb方式Aof方式

1、Rdb方式

将数据以快照的方式写入到二进制文件中,也是dump.rpb。执行save、bgsave的时候会对dump.rpb

保存方式:

1、save:手动存储、阻塞当前线程,把内存数据存到dump.rpb中。

2、bgsave:开启子线程、调用fork操作,后台将内存数据存到dump.rpb中。

redis.conf中默认设置为自动bgsave。

缺陷:假设有client1、client2。client1执行flushall、把内存数据全部清除。client2执行的时候,因为之前数据在未知情况下被清除,这样就会造成很大的麻烦。通常情况下,我们先把save之前,把相应dump.rpb转移到其他目录下进行保存,利于数据恢复。

2、Aof方式

如果应用要求不能丢失任何修改的话,可以采用 aof 持久化方式。

机制:默认每隔一秒,redis会收到写命令,把内容追加到appendonnly.aof文件中。

配置redis.conf:

appendonly yes // 启用 aof 持久化方式

# appendfsync always // 收到写命令就立即写入磁盘,最慢,但是保证完全的持久化

appendfsync everysec // 每秒钟写入磁盘一次,在性能和持久化方面做了很好的折中

# appendfsync no // 完全依赖 os,性能最好,持久化没保证

Redis 持久化磁盘 IO 方式及其带来的问题:

  有 Redis 线上运维经验的人会发现 Redis 在物理内存使用比较多,但还没有超过实际物理内存总容量时就会发生不稳定甚至崩溃的问题,有人认为是基于快照方式持久化的 fork 系统调用造成内存占用加倍而导致的,这种观点是不准确的,因为 fork 调用的 copy-on-write 机制是基于操作系统页这个单位的,也就是只有有写入的脏页会被复制,但是一般你的系统不会在短时间内所有的页都发生了写入而导致复制,那么是什么原因导致 Redis 崩溃的呢?

  答案是 Redis 的持久化使用了 Buffer IO 造成的,所谓 Buffer IO 是指 Redis 对持久化文件的写入和读取操作都会使用物理内存的 Page Cache,而大多数数据库系统会使用 Direct IO 来绕过这层 Page Cache 并自行维护一个数据的 Cache,而当 Redis 的持久化文件过大(尤其是快照文件),并对其进行读写时,磁盘文件中的数据都会被加载到物理内 存中作为操作系统对该文件的一层 Cache,而这层 Cache 的数据与 Redis 内存中管理的数据实际是重复存储的,虽然内核在物理内存紧张时会做 Page Cache 的剔除工作,但内核很可能认为某块 Page Cache 更重要,而让你的进程开始 Swap,这时你的系统就会开始出现不稳定或者崩溃了。我们的经验是当你的 Redis 物理内存使用超过内存总容量的3/5时就会开始比较危险了。

  总结:

1. 根据业务需要选择合适的数据类型,并为不同的应用场景设置相应的紧凑存储参数;

2. 当业务场景不需要数据持久化时,关闭所有的持久化方式可以获得最佳的性能以及最大的内存使用量;

3. 如果需要使用持久化,根据是否可以容忍重启丢失部分数据在快照方式与语句追加方式之间选择其一,不要使用虚拟内存以及 diskstore 方式;

4. 不要让你的 Redis 所在机器物理内存使用超过实际内存总量的3/5。


五、Redis的主从复制

持久化保证了即使redis服务重启也不会丢失数据,因为redis服务重启后会将硬盘上持久化的数据恢复到内存中,但是当redis服务器的硬盘损坏了可能会导致数据丢失,如果通过redis的主从复制机制就可以避免这种单点故障。

主从复制的特点:

1、master可以拥有多个slave;

2、多个slave可以连接同一个master外,还可以连接其他slave;

3、主从复制不会阻塞master,同步数据,master可以继续处理client;

4、提高系统的伸缩性。

主从复制的配置:

主机无需配置,下面来看看从机中的配置:

第一步:复制出一个从机
[root@pc redis19]# cp bin/ bin2 –r

第二步:修改从机的redis.conf
语法:Slaveof masterip masterport

第三步:在从机redis.conf中修改port地址为6380

第四步:清除从机中的持久化文件
[root@pc bin2]# rm -rf appendonly.aof dump.rdb

第五步:启动从机
[root@pc bin2]# ./redis-server redis.conf

第六步:启动6380的客户端
[root@pc bin2]# ./redis-cli -p 6380 

六、Redis集群

Redis 集群中内置了 16384 哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。

需要注意的几个点:

1、所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽

2、节点的fail是通过集群中超过半数的节点检测失效时才生效

3、客户端与redis节点直连,不需要中间proxy.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可;

4、redis-cluster把所有的物理节点映射到[0-16383]slot,cluster 负责维护node<->slot<->value。

  • redis-cluster投票:容错

1、集群中所有master参与投票,如果半数以上master节点与其中一个master节点通信超过(cluster-node-timeout),认为该master节点挂掉;

2、什么时候整个集群不可用(cluster_state:fail)? 

  • 如果集群任意master挂掉,且当前master没有slave,则集群进入fail状态。也可以理解成集群的[0-16383]slot映射不完全时进入fail状态。
  • 如果集群超过半数以上master挂掉,无论是否有slave,集群进入fail状态。
  • 安装ruby

集群管理工具(redis-trib.rb)是使用ruby脚本语言编写的。

第一步:安装ruby
[root@pc bin2]# yum install ruby
[root@pc bin2]# yum install rubygems

第二步:redis-3.0.0.gem文件上传到linux系统

第三步:安装ruby和redis接口
[root@pc ~]# gem install redis-3.0.0.gem

第四步:将redis-3.0.0包下src目录中的以下文件拷贝到redis01/redis-cluster/
[root@pc src]# cp redis-trib.rb  /usr/local/redis01/redis-cluster

  • 集群搭建

搭建集群最少也得需要3台主机,如果每台主机再配置一台从机的话,则最少需要6台机器。端口设计为:7001-7006。

第一步:复制出一个7001机器
[root@pc redis19]# cp bin ./redis-cluster/7001 –r

第二步:如果存在持久化文件,则删除
[root@pc 7001]# rm -rf appendonly.aof dump.rdb

第三步:设置集群参数  cluster-enabled yes

第四步:vim redis.conf中的端口:7001

第五步:用7001复制出7002-7006机器
[root@pc redis-cluster]# cp 7001/ 7002 -r
[root@pc redis-cluster]# cp 7001/ 7003 -r
[root@pc redis-cluster]# cp 7001/ 7004 -r
[root@pc redis-cluster]# cp 7001/ 7005 -r
[root@pc redis-cluster]# cp 7001/ 7006 -r

第六步:和第四步一样,修改7002-7006机器的端口

第七步:启动7001-7006这六台机器

第八步:修改start-all.sh文件的权限
[root@pc redis-cluster]# chmod u+x start-all.sh
[root@pc redis-cluster]# ./start-all.sh

第九步:创建集群
[root@pc redis-cluster]# ./redis-trib.rb create --replicas 1 192.168.242.137:7001 192.168.242.137:7002 192.168.242.137:7003 192.168.242.137:7004 192.168.242.137:7005  192.168.242.137:7006
  • 查看集群的消息:cluster  info
  • 查看集群的节点:cluster  nodes
  • 修改防火墙:[root@pc redis-cluster]# vim /etc/sysconfig/iptables

推荐及参考:

1、redis基础知识:https://blog.csdn.net/u012385190/article/details/53424931

2、Redis基本数据结构:https://www.cnblogs.com/metu/p/9615857.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值