Redis

Redis

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。

# 操作系统:CentOS 6.8
# Redis 版本:redis-3.2.5
# 虚拟机网路:Nat模式

0 安装

​ 访问Redis官方网站Reids中文网下载对应版本的Redis。

0.1 解压

​ 解压下载的tar包

tar -zxcf redis-3.2.5.tar.gz

安装C、C++支持

yum install -y gcc gcc-c++

​ 进入解压后的目录中的src目录执行make && make install命令

0.2 启动

​ 进入解压的目录,执行redis-server命令

​ 使用redis-server [配置文件位置]即可启动一个redis的数据库,命令默认为当前目录下的配置文件redis.conf 命令可以在任意目录执行,当启动时需要指定配置文件。

0.3 连接

​ 使用redis-cli命令即可连接已启动的redis数据库。

1 基本命令

1.1 启动命令

redis-server  redis.conf 启动命令  后跟配置文件位置
redis-cli -p 6379 默认端口为6379

1.2 数据库基本操作

redis-cli -p 6379 进入数据库
select [num]      选择库
DBSIZE            查看key数量
FLUSHDB           清空当前库
FLUSHALL          清空所有库

默认端口6379 默认16个库

1.3 五大数数据类型

String

  • 基本数据类型,一个key对应一个value
  • 二进制安全,可以包含任何数据(图片或序列化对象)
  • 最大值为512M

Hash

  • 键值对集合
  • String类型的field和value的映射表,适合存储对象
  • 类似Java中的 Map<String,Object>

List

  • 简单的字符串列表,按照插入顺序排序。
  • 可以添加元素到头部或尾部
  • 底层为链表

Set

  • 无序无重复集合
  • 通过底层为HashTable

Zset

  • sorted set
  • 每个元素关联一个double类型的分数排序

1.4 常用命令

​ key

keys *
#查看所有key
exists [key_name]
#判断key是否存在
move   [key_name] [db_num]
#移动key到某个库
expire [key_name] [时间s]
#设置key过期时间 单位秒
ttl    [key_name]
#查看过期时间
type   [key_name]
#查看key类型

​ String

set/get/del/append/strlen
#数据操作
Incr/decr/incrby/decrby
#自增自减 自增自减某值 数字
getrange/setrange
#设置/获取子串
setex <setex k1 10 v4>
#设置过期时间
sentnx
#避免覆盖添加值
mset/mget/msetnx
#批量设置获取(重复失效)

​ List

 Lpush/Rpush/Lrange
 #左右进入\查看 左栈右队
 Lpop/rpop
 #出栈\出队
 Lindex
 #按照索引获取
 Llen
 #获取长度
 Lren key [n] [value]
 #删除多个值
 Ltrim key
 #截取子串
 Rpoplpush [list_org] [list_dist]
 #出队压栈
 Lset key index value
 #给某位置赋值
 Linsert key befor/after ""
 #在某字符前/后插值

​ Set

sadd								
#不重复/重复自动去除
smemebers						
#查看集合所有元素
sismember							
#检测是否为成员
scard								
#获取集合元素个数
srem key value						
#删除元素
srandmember key int					
#随机出N个整数
spop key							
#随机出栈
smove key1 key2						
#随机出一个值给集合
sdiff/sinter/sunion					
#差集/交集/并集

​ Hash

hset/hget/hmset/hmget/hgetall/hdel	
#获取添加移除单个/多个
customer:
		id: 11
		name: Lee
		age: 20
hmset customer id 11 name Lee age 20
hle									
#获取长度
hexists key							
#获取某个key
hkeys/hvals							
#获取键\值
hincrby/hincrbyfloat				
#自增某个值
hstnx								#避免覆盖插值

​ Zset

zadd/zrange							
#添加/查看
zdd zset 1 v1 2 v2 3 v3
zrangbyscore [begin_s] [end_s]		
#区域查看(不包含 limit
zrem key							
#删除某个值
zcard/zcount						
#统计个数
zrank								
#取值的下表
zscore								
#取值的分数
zrevrank							
#取下标
zrevrange
zrevrangebyscore					
#结束分数到开始分数

1.5 配置文件

#守护进程方式
daemonize yes

#默认写入pid
pidfile /var/run/redis_6379.pid
#默认端口
port 6379

# include /path/to/other.conf
bind 127.0.0.1

#超时关闭连接
timeout 0

#日志级别
# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for 
# development/testing)
# verbose (many rarely useful info, but not a mess like the # debug level)
# notice (moderately verbose, what you want in production  
# probably)
# warning (only very important / critical messages are 
# logged)
loglevel notice

# output for logging but daemonize, logs will be sent to 
# /dev/null
logfile ""
#默认数据库数量
databases 16

#同步数据文件
save <seconds> <changes>
#默认提供三个条件 1 in 900s  10 in 300 1000 in 60
save 900 1
save 300 10
save 60 10000

#缓存级别
# volatile-lru -> Evict using approximated LRU among the 
# keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU among the 
# keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key among the ones with
# an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire
# time (minor TTL)
# noeviction -> Don't evict anything, just return an error
# on write operations.
# maxmemory-policy noeviction

#数据库路径
dir ./

#默认密码
# requirepass foobared

#默认最大连接数
# maxclients 10000

#最大内存
# maxmemory <bytes>


2 持久化

2.1 RDB(Redis Database)

在指定时间间隔内将内存中的数据集快照写入磁盘中即Snapshot快照,恢复时直接将快照导入内存。

持久化由Fork进程进行,主进程不进行IO擦破做,对数据完整性不敏感,最后一次持久化的数据可能丢失。

Fork为原进程的复制,所有数据与原进程完全一致,并作为原进程的子进程。

保存形式为 dump.rdb

配置
############### SNAPSHOTTING ##########################
#
# Save the DB on disk:
#
#   save <seconds> <changes>
#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
#
#	Note: you can disable saving completely by commenting
#	out all "save" lines.
#
#	It is also possible to remove all the previously 
#	configured save
#	points by adding a save directive with a single empty 
#	string argument like in the following example:
#   save ""  #save 命令可手动保存(阻塞式) bgsave 异步不阻塞
#	在设置时间内改动后自动分片存储,触发快照,备份文件自动恢复
save 900 1
save 300 10
save 60 10000

#恢复文件位置
dir ./

#默认恢复文件
# The filename where to dump the DB
dbfilename dump.rdb

#数据一致性
stop-writes-on-bgsave-error yes

#压缩算法使用
rdbcompression yes

#数据校验(为增加性能可关闭 不推荐关闭)
rdbchecksum yes

优点:适合大规模的数据恢复,对数据完整性和一致性要求不高

缺点:意外宕机只有最后一次快照,fork进程导致两倍程序消耗


2.2 AOF(Append Only File)

通过日志的形式记录每个写操作。
#默认关闭
appendonly no

#默认文件名
appendfilename "appendonly.aof"

# Redis supports three different modes:
#
# no: don't fsync, just let the OS flush the data when it 
# wants. Faster. #不设置
# always: fsync after every write to the append only log.
# Slow, Safest.	 #总是使用
# everysec: fsync only one time every second. Compromise.
# The default is "everysec" #默认。
appendfsync everysec

#重写时运用appendsync
no-appendfsync-on-rewrite no

#重写比例和重写日志大小
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb #通常3GB+

优点:每秒同步 修改同步 不同步

缺点:恢复速度慢 存储空间大


推荐使用两种共用,启动时优先载入AOF备份,AOF数据丢失不超过2秒的数据


3 事务

串行执行一组命令,命令会被序列化,不许阻塞,即一个事务。没有隔离级别的概念,不保证原子性,没有回滚,部分支持事务。

3.1 基本命令

DISCARD					放弃事务
EXEC					执行事务块
MULTI					标记开始
UNWATCH					取消监视所有键
WATCH KEY [key ...]		开启监视

3.2 事务使用步骤

MULTI   			 //开启事务,返回OK

Operationes  	//入队不操作,返回QUEUE,出现错误直接取消

EXEC/MULTI	//执行或取消执行,单个语句出错,其他可以执行

3.3 WATCH监控

悲观锁:如表级锁,当修改时加锁,其他修改无法执行(高一致,低并发)

乐观锁:不锁+版本号 在修改时读取版本号,执行修改时版本号>=读取时版本

CAS:即compare and swap 或者 compare and set,涉及到三个操作数,数据所在的内存值,预期值,新值。
当需要更新时,判断当前内存值与之前取到的值是否相等,若相等,则用新值更新,若失败则重试,一般情况下
是一个自旋操作,即不断的重试。

WATCH使用步骤

	WATCH balance

	MULTL

	Operations

	EXEC

	//乐观锁已经被修改的版本将无法执行事务 

	//执行后锁已被清除

	已被修改  -->  UNWATCH取消监控 --> WATCH  -->

4 发布与订阅

进程间的一种消息通信模式:发送者(pub)与订阅者(sub) 主题模式

使用命令

PSBUSCRIBE pattern[pattern ...]			订阅
PUBSUB subcommand[arg [arg]]			查看订阅状态
PUBLISH channel message					发布消息到主题
PUNSUBSCRIBE pattern					取消订阅
SUBSCRIBE channel[channel ...]			订阅多个
UNSUBSCRIBE[channel[channel]]			退订多个

使用步骤

订阅消息即进入消息监听状态,消息发布时自动接收消息

发布者发布消息到对应频道,消息监听处即受到消息

5 主从复制

5.1 配置方法

info replication			查看数据库信息
SLAVEOF IP Port				隶属于主机

5.2 info replication

#从机
role:slave
master_host:127.0.0.1
master_port:6379

#主机
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=1321,lag=0
slave1:ip=127.0.0.1,port=6380,state=online,offset=1321,lag=1
#主机可读可写、从机可读不可写
#只需要在从机上使用命令SLAVEOF IP port 命令即可
#从机可以访问所有缓存中数据 主机宕机后可重开 从机依旧 反之不行
中心化配置,主机宕机系统瘫痪,从机宕机需要重新配置,一主二从。

5.3 SLAVEOF no one

将从机转换为主机,从机需要重新配置

5.4 复制原理

首次全量复制,而后增量复制,重连全量复制。

5.5 哨兵模式

创建`sentinel.conf`配置文件,加入哨兵监视器
sentinel monitor host-main 127.0.0.1 6379    1
				 监视名		IP		端口	 票数
命令启动:`redis-sentinel sentinel.conf`

自动监视,当主机宕机自动选举主机,原主机恢复后自动设置为从机待机

缺点: 有延迟,当系统使用高时,延迟现象比较严重


6 创建集群

6.1 配置文件修改

​ 将解压目录中的redis.conf文件复制一份到存放集群配置文件的目录(任意目录中),并创建集群中的每一个数据库的配置文件(新建文件)。

​ 修改配置文件中集群相关的参数,将配置设置为集群模式,以目录中的redis-6379.conf为例如下书写。

include /opt/software/redis/cluster/configure/conf/redis.conf
# 引入默认配置文件
port 6379
# 端口号指定
dir /opt/software/redis/cluster/configure/dbdump
# dump 文件目录指定
dbfilename dump-6379.dump
# dump文件名称指定
pidfile /var/run/redis_6379.pid
# 指定pid
daemonize yes
# 守护进程(后台运行)
logfile /opt/software/redis/cluster/configure/log/redis-6379.log
# 日志存放目录
cluster-enabled yes
# 集群开启
cluster-config-file nodes-6379.conf
# 集群配置文件名称
cluster-node-timeout 15000

# 集群超时时间

6.2 安装ruby支持

​ 执行yum install ruby rubygems -y安装ruby支持。

​ 需要redis-3.2.0.gem包,下载地址

​ 在gem包所在目录执行gem install --local redis-3.2.0.gem命令

6.3 启动集群

6.3.1 启动redis

redis-server /opt/software/redis/cluster/configure/conf/redis-6379.conf
redis-server /opt/software/redis/cluster/configure/conf/redis-6380.conf
redis-server /opt/software/redis/cluster/configure/conf/redis-6381.conf
redis-server /opt/software/redis/cluster/configure/conf/redis-6389.conf
redis-server /opt/software/redis/cluster/configure/conf/redis-6390.conf
redis-server /opt/software/redis/cluster/configure/conf/redis-6391.conf

6.3.2 查看启动

​ 所有启动中的服务均为cluster即启动成功

6.3.3 组成集群

​ 进入redis解压目录中的src文件夹,执行命令

 ./redis-trib.rb create --replicas 1 192.168.111.3:6379 192.168.111.3:6380 192.168.111.3:6381 192.168.111.3:6389 192.168.111.3:6390 192.168.111.3:6391

​ 出现下图即创建成功。

redis-cli -c ...注意连接时需要添加一个-c参数。

7 Java中使用

Jedis jedis = new Jedis(url,port);

//事务
Transaction transaction = jedis.multi();

transaction.set();
   ...
transaction.discard();	//取消执行

//开启watch
int now;
jedis.watch("key");
int value = Integer.paraseInt(jedis.get("key"));
if(value < now){
  jedis.unwatch();
  soutp("redo");
  return false
}else{
  Transaction tr = jedis.multi();
  transaction.method("","");
  transaction.exex()
}
jedis.unwatch();

//主从复制
Jedis jedis_master = new Jedis(url,port);
Jedis jedis_salve  = new Jedis(url,port);

//主从复制 读写分离
jedis_salve.slaveof(url,port);
jedis_master.set(...);
String result = jedis_salve.get(...);

//JedisPool
public class JedisPoolUtil{
    private static volatile JedisPool jedisPool = null;
    private JedisPoolUtrl(){}
    public static JedisPool getJedisPoolInstance()
    {
	  if(null == jedisPool)
      {
        synchronized (JedisPoolUtil.class)
        {
          if(null == jedisPool)
          {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
            poolConfig.set(...);
        jedisPool = new JedisPool(poolConfig,url,port);
        return JedisPool;
          }
        }
      }
      
    }
  
  public static voie relase(JedisPool jedisPool,Jedis jedis)
  {
    if(null != jedis)
    {
      jedisPool.returnResourceObject(jedis);
    }
  }
}
posted @ 2018-09-07 22:28  图图突tu  阅读(166)  评论(0编辑  收藏  举报