1》什么是redis:
redis是一个开源的,支持网络交互的,可基于内存也可以持久化的key-value的数据库。
redis官网是redis.io
2》安装redis:
从redis.io下载最新版redis-X.Y.Z.tar.gz后解压,然后进入redis-X.Y.Z文件夹后直接make即可,安装非常简单。
make成功后会在src文件夹下产生一些二进制可执行文件,包括redis-server、redis-cli等等:
$ find . -type f -executable./redis-benchmark //用于进行redis性能测试的工具./redis-check-dump //用于修复出问题的dump.rdb文件./redis-cli //redis的客户端./redis-server //redis的服务端./redis-check-aof //用于修复出问题的AOF文件./redis-sentinel //用于集群管理
3》redis的使用:
3.1 启动redis:
1) redis-server /usr/root/bin/redis.conf 启动服务端的命令,但是需要保持当前窗口状态。 打开新的窗口,使用clone session方法。
2) redis-cli -p 6379 启动客户端的命令,需要通过参数-p 指定端口号 输入ping 会返回pong 代表连接ok
3) set key1 “hello world” 设置key1的值为“hello world” 返回ok。
4) get key1 返回“hello world” ,说明数据可以正常的存取。
5) exit 退出当前的连接
6) shutdown 关闭当前的服务 然后再执行一次exit完全退出
7) redis-benchmark 压测命令 测试在不同命令下 10w次请求在多长时间内完成 官方标准是达到10w/s 的get/set
3.2 redis 数据库命令:
1) keys * 查看当前数据库所有的key值
系统会设置3个默认key额外使用
2) keys ? 匹配方式的使用 对于存在key1 key2 key3形式的key时 keys key? 可以找到 keys k??? 也可以找到 说明?是一个匹配符,并且有占位的作用
3) select 1 切换到1号数据库 get key1 返回nil,空的意思 通过127.0.0.1:6379[?]后面的括号中的值,可以判断当前所在的数据库编号
4) dbsize 展示数据库中key的个数
5) flushdb 删除当前数据库的数据 “慎用!”
6) flushall 删除所有数据库的数据 要怎么用 看着办
3.3 redis键值操作命令:
1)exists + key 判断键值是否存在
2)type + key 显示当前键值存储的数据类型
3)expire + key + n 设置可以值得有效时间为n秒,过了有效期,此key的值置为空
pexpire + key +n 有效时间单位为毫秒
4)ttl + key 查看还剩多长时间有效,正数代表未过期的剩余时间,单位为秒。
pttl + key 返回剩余时间为毫秒
负数情况下:
当返回为-2时,说明key不存在
当返回为-1时,说明没有设置时间
5) persist + key 设置数据一直有效,特别作用于错误设置了有效期之后。
6)del + key 删除一个key
7)rename + key + newKey 可以重命名key的值
8)randomkey 随机出一个key
9) move key + dbID 移动指定key到另一个数据库中,dbID是数据库编号 eg: move key5 1
4》Redis的数据类型:
4.1 String 字符串类型:
1) set key1 “hello world” 设置key1的值为“hello world” 返回ok。
2) get key1 返回“hello world” ,说明数据可以正常的存取。
3)strlen 查看字符串的长度
4)append 增加后缀,返回字符串的长度
eg: append key1 “222” -> “hello111222”
eg: set key1 “hello111222”
5) 当value的值是整数时,可以通过命令直接进行数学运算
incr 自增 ,返回最新的值。
decr 自减, 也返回最新的值。
incrby 增加,区别是增加计算的参数
如:incrby key11 3。 decrby 减少,同上。
6) 范围内操作的命令 getrange key start end 获取从初始位置到结束位置的值,从0计数 ==》 类似subString setrange key start newStr 设置从起始位置开始,替换指定位置为新的字符串
eg : “hello111222” -> setrange key1 5 333 -> “hello333222”
7)整合命令
setex = set + expire
使用方式: setex + key + 时间 + value
setnx = set + exists = set if not exists
使用方式: setnx + key + value 如果key不存在,则设置数据,返回1。如果存在,不设置,返回0。
getset 先取出原来的值,再设置为新值
使用方式: getset + key + value 返回旧值。
8) 批量操作
mget = more get
使用方式 : mget + key1 + key2 + key3 参数接收多个key, 结果返回多个value
mset = more set 使用方式:mset + key1 + value1 + key2 + value2 一次设置多个key和value, 参数本身是个map msetnx 使用方式同上。
2 原理:
redis的字符串是动态字符串,内部结构类似ArrayList。采用预分配冗余空间的方式减少内存的频繁分配。内部为字符串分配的实际空间一般高于字符串长度,当字符串长度<1MB时,扩容方式是直接加倍,如果>1MB,一次扩容只扩1MB,直到扩大到512MB。
4.2 list(列表):
PS:redis中的lists在底层实现的并不是数组,而是链表优势是在头部和尾部的插入新的元素,复杂度是常数级别,速度快,弊端是链表型lists定位速度比较慢
4.2.1 存取操作 push pop range:
1) lpush : 从左侧存入数据 —》 栈结构
2) lpop (从左侧弹出)
3)rpush: 从右侧存入数据 —》 队列结构
4)lpop (从左侧弹出)
5)lrange: 范围内查看数据 使用方式:lrange key start end
4.2.2 对list本身的操作 :
1) llen 查看长度 lindex 获取某一个位置的值,下角标从0开始
2) lrem 删除n个value的值
使用方式: lrem key N value
3)ltrim 截取某个范围的数据重新赋值给key
使用方式: ltrim key start end (下角标从0开始)
4)linsert 插入数据到某个位置的前后
使用方式: linsert key before/after oldValue newValue
如果要插入数据到头部,还可以使用 lpushx,
使用方式:lpushx key value 同理,如果要插入数据到尾部,可以使用 rpushx, 使用方式同上。
5)lset 可以更改指定位置的值 使用方式: lset key index value
4.2.3 lists的应用相当广泛,例子:
1.我们可以利用lists来实现一个消息队列,而且可以确保先后顺序,不像MySQL那样还需要通过ORDER BY来进行排序。
2.利用LRANGE还可以很方便的实现分页的功能。
3.在博客系统中,每片博文的评论也可以存入一个单独的list中。
4.3 Hash (哈希):
HashMap
HashMap
HashMap
HashMap
HashMap
4.3.1 Hash命令:
4.3.1.1 存取数据:
1)hset :
使用方式:hset hashname key1 value1
2)hget:
使用方式:hget hash1 key1 => “value1”
3) hsetnx :
如果不存在即set新的key值
使用方式:hsetnx hashname key1 value1
4)hmset/hmget :
批量处理更便捷
使用方式:hmset hashname key1 value1 key2 value2
hmget hashname key1 key2
4.3.1.2 遍历数据:
1)hkeys:查看所有的key值
2)hvals:查看所有的value值
3)hlen :查看数据长度
4)hgetall: 返回全部的key和value
5)hexists :判断是否存在某个key, 存在返回1,不存在返回0
4.3.1.3 变更数据:
1)hdel: 删除数据 ,
使用方式 :hdel hashname key
2)hincrby :对整数的增加操作,指定增加的范围
使用方式: hincrby hashname field_key num
4.4 set(集合):
java的集合中有list/set/map list可以存储有序的重复数据, 而set可以存储无序的不重复数据。
4.4.1 set集合 命令:
4.4.1.1 读写操作:
1)sadd :创建set类型的value,
eg: sadd setName 1 2 3 4 4 3 2 1
2)scard keyName :查看set的大小
eg:scard setName
3)smembers keyName: 查询set中的所有值
eg:smembers keyName
4)sismember keyName value: 判断value是否在key所对应的set中, 如果在返回1,如果不在返回0
eg:sismember keyName value
4.4.1.2 更新操作:
1)srem keyName value1 value2: 删除set中一至多个数据的值
2)srandmember keyName num :可以在set中随机出num个元素
3)spop keyName num :可以随机弹出num个元素返回
4.4.1.3 交互操作:
1) smove keyName1 keyName2 value: 移动元素value从key1到key2
4.4.1.4 并集、交集和差集:
1)**sinter keyName1 keyName2 :**代表求两个集合的交集(两者都有的元素)。 <br /> 2)**sdiff keyName1 keyName2 :**返回存在在key1中但不存在在key2中的元素,两者的差集 <br /> 3) **sunion keyName1 keyName2:** 返回并集(两个集合中的所有元素)<br />
4.5 ZSet (有序集合):
4.5.1 命令:
4.5.1.1 读取操作:
1)zadd :创建或增加zset的元素值,每一个元素值都包含 <分数,value>
使用方式: zadd keyName score1 value1 score2 value2 …
2)zrange keyName start end :指定在start到end的范围内查看元素 如果要查看分数 ,加上withscores
3)zrangebyscore keyName minScore maxScore :指定分数范围内查询 元素 参数说明 分数前增加“(” 代表开区间(不包含当前值) 支持limit分页 limit + offset(偏移量) + num(返回的数量)
4)zrem keyName + value: 删除指定的value值
4.5.1.2 统计操作:
1)zcard + keyName: 统计元素个数
2)zcount + keyName + minScore + maxScore:统计给定分数范围内的元素个数 比如统计及格人数等需求。
3)zscore + keyName + member :查询指定成员的分数
4)zrank + keyName + member :返回指定成员的索引位置(因为有序,所以位置代表排名)
5)zrevrank + keyName + member: 默认从低到高排序,逆序正好代表排名
6)zrevrange + keyName: 原来是从小到大排列,逆序后从大到小排列
4.6 Geo (位置信息):
4.6.1 命令:
1) geoadd + key + 经度 + 维度 + 成员名 : 通过经纬度存储地址,支持存储多个
2) geodist + key + member1 + member2 + 距离单位 :查询两个地点之间的相对距离 距离单位支持:m(米)、km(千米)、mi(英里)、ft(英尺)
3)geopos :查询成员经纬度数据
4)geohash :进行哈希编码 ,得到编码结果
5)georadius :以某个经纬度的位置为中心,划一个指定距离的半径,返回集合中满足条件的地址。 这就是“附近的XXX”的一种实现方式。 使用方式: georadius + key + 中心的经度 + 中心的纬度 + 半径的距离 + 半径的单位 可选参数: withdist 返回距离; withcoord 返回经纬度 ; withhash 返回哈希编码;
5》Redis配置:
5.1 linux命令:
1) cd: 更改目录
cd ~ 回到初始目录
cd .. 回到上级目录
2) mkdir 创建目录 eg: mkdir myredis
3) cp 拷贝文件 eg: cp redis-5.0.6/redis.conf myredis/
4) ll 查看目录内的文件
5) vim 文本编辑器 两种模式: 命令模式 、 编辑模式 打开文件时,默认是命令模式,可以查看文件的内容。
输入i(insert),可以切换为编辑模式,此时才可以更改文件。
按ESC,可以从编辑模式再切换为命令模式 (此时才可以退出)。
退出方式:
输入 : q (如果文件被修改,会提醒未保存) 不保存,
输入 : q! 保存,
输入 : wq
5.2 redis.conf配置文件:
1) 单位的问题: 1k / 1kb / 1m / 1mb / 1g / 1gb 是不同的,没有b的时候取整。 单位的大小写是不敏感的 1GB=1gB=1Gb
网络相关:
2) bind 127.0.0.1 绑定ip地址(能够访问服务端的地址) 当前的redis服务只能被本机访问
3) protect-mode yes 开启保护模式 当bind没有配置且登录不需要密码时,启动保护模式(只能被本地访问)
4) port 6379 端口号
5) timeout 0 客户端超时时间 ,0代表一直保持
6) tcp-keepalive 300 单位是秒,每300s去检查一次客户端是否健康,避免服务端阻塞。
7) tcp-backlog 511 队列数量(未完成握手和已完成握手的)
通用相关:
8) daemonize no 后台运行开关 改为yes后,重启redis验证。 redis启动指定配置文件的方式为: redis-server /root/myredis/redis.conf
9) pidfile /var/run/redis_6379.pid 当守护进程开启时,写入进程id的文件地址
10) loglevel notice 四种级别,notice对应生产环境
11) logfile “” 日志存储的位置
12) databases 16 初始化数据库是16个
5.3 安全和限制
config命令是一种从客户端查看配置项信息的方式,使用config get属于危险命令,可以限制使用。
安全校验配置 requirepass 代表是否设置密码 如果需要
设置密码 config set requirepass +
校验 anth +
5.4 危险命令限制 :
包含 config / flushdb / flushall / keys
rename-command + 命令 + “” 将此命令置为不可用
5.5 其他限制 :
maxclients 10000 客户端并发数的限制
maxmemory 最大内存
maxmemory-policy 缓存淘汰策略
默认值 noeviction (不删除只报错)
其他策略主要分为两种情况
allkeys(所有的键值都可能删除)
volatile(只删除设置了过期时间的键值)
6》 Redi s缓存淘汰策略 :
六种策略:
1) noeviction:
不删除策略, 达到最大内存限制时, 如果需要更多内存, 直接返回错误信息。 大多数写 命令都会导致占用更多的内存(有极少数会例外, 如 DEL )。
2) allkeys -lru:
所有key通用; 优先删除最近最少使用(less recently used ,LRU) 的 key。
3)volatile-lru:
优先删除最近最少使用(less recently used ,LRU) 的 key(限于会过期的key)。
4)allkeys -random:
5)volatile-random:
6)volatile-ttl:
优先删除剩余时间(time to live,TTL) 短的key(限于会过期的key)。 ps:Redi s缓存淘汰策略 如果分为热数据与冷数据, 推荐使用 allkeys-lru 策略
7》Redis持久化(RDB&AOF):
7.1 什么是持久化:
持久化——将数据(如内存中的对象)保存到可永久保存的存储设备中
7.2 持久化的两种方式:
7.2.1 RDB持久化:
含义: 在指定的时间间隔内对数据进行快照存储。先将数据集写入临时文件,写入成功后, 再替换之前的文件,用二进制压缩存储,是一次的全量备份。
7.2.1.1 命令触发:
- save,会阻塞当前Redis服务器,直到持久化完成,线上应该禁止使用。
2. bgsave,该触发方式会fork一个子进程,由子进程负责持久化过程,因此阻塞只会发生在fork 子进程的时候7.2.1.2 自动触发:
- 根据我们的 save m n 配置规则自动触发;
2. 从节点全量复制时,主节点发送rdb文件给从节点完成复制操作,主节点会触发 bgsave;
3. 执行 debug reload 时;
4. 执行 shutdown时,如果没有开启aof,也会触发7.2.1.3 恢复方式:
将备份文件(dump.rdb)移动到redis安装目录并启动服务即可

7.2.1.4 RDB性能分析(优缺点):
优点:
1)通过rdb文件恢复数据比较快。
2) rdb文件非常紧凑,适合于数据备份。
3)通过RDB进行数据备份,由于使用 子进程生成,所以对Redis服务器性 能影响较小 。
缺点:
1)采用RDB的方式可能会造成某个时段内数据的丢失,比如还没达到 触发条件时服务器死机了,那么这个时间段的数据会丢失。
2)使用save命令会造成服务器阻塞,直接数据同步完成才能接收后 续请求。
3)使用bgsave命令在forks子进程时,如果数据量太大,forks的过 程也会发生阻塞,另外,forks子进程会耗费内存。
7.2.2 AOF 持久化:
含义: 以日志文本的形式记录服务器所处理的每一个数据更改指令,然后通过重放来恢复 数据,是连续的增量备份 。



8》Jedis的使用:
8.1 修改redis.conf配置文件:
首先需要在redis.conf配置文件中修改配置。需要重启Redis服务才可以生效:
bind 192.168.31.329 =>绑定本机Linux的IP地址
8.2 绑定主机地址:
修改之后,必须指定绑定的主机地址方可使用Redis
redis-cli -h 192.168.31.329 -p 6379 =>启动时指定绑定的主机地址
8.3 开放6379端口:
firewall-cmd —permanent —add-port=6379/tcp
firewall-cmd —reload
firewall-cmd —query-port=6379/tcp
8.4 创建java项目并导入jar包:
8.5 创建redis.properties配置文件:
#最大连接数redis.maxTotal=50#默认开启的活跃连接数redis.maxIdel=10#Linux的ip地址redis.host=192.168.200.130#redis的端口号redis.port=6379
8.6 创建Jedis的工具类 JedisUtils:
public class JedisUtils {// 将从配置文件读取的配置信息赋予如下变量private static int maxTotal;private static int maxIdel;private static String host;private static int port; // 端口号为int类型// Jedis的连接池配置private static JedisPoolConfig jedisPoolConfig;// Jedis连接池private static JedisPool jedisPool;static {// 读取redis.properties配置文件ResourceBundle bundle = ResourceBundle.getBundle("redis");maxTotal = Integer.parseInt(bundle.getString("redis.maxTotal"));maxIdel = Integer.parseInt(bundle.getString("redis.maxIdel"));host = bundle.getString("redis.host");port = Integer.parseInt(bundle.getString("redis.port"));// Jedis连接池配置jedisPoolConfig = new JedisPoolConfig();jedisPoolConfig.setMaxTotal(maxTotal);jedisPoolConfig.setMaxIdle(maxIdel);jedisPool = new JedisPool(jedisPoolConfig, host, port);}public static Jedis getJedis() {return jedisPool.getResource();}}
8.7 测试:
public class JedisTest {public static void main(String[] args) {// 1. 获取Jedis对象Jedis jedis = JedisUtils.getJedis();// 2. 执行操作,Jedis中操作的方法名与Linux中命令行工具中的指令同名jedis.sadd("key1", "abc", "abc", "def");Long key1 = jedis.scard("key1");System.out.println("运行结果:" + key1);// 3.关闭连接jedis.close();}}
9》Redis主从复制:
9.1 主从复制的概念:
1)为了避免单点Redis服务器故障,准备多台服务器,互相连通。将数据复制多个副本保存在不同的服务器上,连接在一起,并保证数据是同步的;即使有其中一台服务器宕机,其他服务器依然继续提供服务,实现redis高可用,同事实现数据的备份。
2)多台服务器的连接方案:
3)主从复制即将master中的数据即时、有效的复制到slave中
4)一个master可以拥有多个slave,一个slave只对应一个master
5)master和slave各自的职责不一样
6)master:写数据、执行写操作时,将出现变化的数据自动同步到slave
7)slave:读数据
9.2 主从复制的作用:
(1) 读写分离:master写、slave读,提高服务器的读写负载能力
(2) 负载均衡:slave分担master负载,并根据需求的变化,可改变slave的数量,大大提高Redis服务器并发量与数据吞吐量
(3) 故障恢复:当master出现问题时,由slave提供服务,实现快速的故障恢复
(4) 数据冗余:实现数据热备份,是持久化之外的一种数据冗余方式
(5) 高可用基石:基于主从复制,构建哨兵模式与集群,实现Redis的高可用方案
9.2 主从复制的流程:
9.2.1 建立连接(slave主动连接master):
9.2.1.1 建立slave到master的连接:
- 建立slave到master的连接,使master能够识别slave,并保存slave端口号。
S



