Redis学习笔记
tips:redis
文章目录
一、Redis介绍及应用场景
(一)关系型数据库
以关系模型组织数据,关系模型即以二维行列形式存储数据。
(二)非关系型数据库
即NoSQL,其发展历程为:MySQL——NoSql——NewSQL(TiDBit)
(三)NoSQL分类
- 键值(Key-Value)存储数据库:
- 代表:Redis
- 主要应用:缓存,处理大量数据的高访问负载
- 优势:快速查询
- 列存储数据库
- 代表:HBase
- 主要应用:分布式的文件系统
- 优势:查询速度快,更容易进行分布式扩展
- 文档型数据库
- 代表:MongoDB
- 主要应用:web应用(类似于Document对象,包含两个变量,name和value,value只能为字符串)
- 优势:数据结构要求不严格
- 图形数据库
- 代表:Neo4J、InfoGrid、Infinite Graph
- 主要应用:社交网络
- 优势:利用图结构相关算法
(四)Redis介绍
-
c语言开发的key-value内存数据库
-
单进程单线程,不存在线程安全
-
支持10W QPS(每秒查询数),底层采用IO多路复用(NIO思想)
-
相较Memcache,拥有更优秀的读写性能,及丰富的数据结构
-
五中数据结构类型:字符串String、散列Hash、列表List、集合Set、有序结合SortedSet
-
Redis官网
(五)Redis应用场景
- 内存数据库(Session共享、购物车信息、用户浏览记录等)
- 缓存数据库(经常使用的数据)
- 任务队列(抢购、12306,利用单线程特性)
- 分布式锁的实现
- 支持发布订阅的消息模式
- 应用排行榜(有序集合)
- 访问统计(计数器)
- 数据过期处理(可以精确到毫秒)
二、Redis单机安装及连接
(一)yum源配置
[base]
name=CentOS-$releasever - Base
baseurl=https://mirrors.aliyun.com/centos/7/os/x86_64/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/centos/7/os/x86_64/RPM-GPG-KEY-CentOS-7
[updates]
name=CentOS-$releasever - Updates
baseurl=https://mirrors.aliyun.com/centos/7/updates/x86_64/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/centos/7/os/x86_64/RPM-GPG-KEY-CentOS-7
[extras]
name=CentOS-$releasever - Extras
baseurl=https://mirrors.aliyun.com/centos/7/extras//x86_64/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/centos/7/os/x86_64/RPM-GPG-KEY-CentOS-7
[centosplus]
name=CentOS-$releasever - Plus
baseurl=https://mirrors.aliyun.com/centos/7/centosplus//x86_64/
gpgcheck=1
enabled=1
gpgkey=https://mirrors.aliyun.com/centos/7/os/x86_64/RPM-GPG-KEY-CentOS-7
(二)安装所需软件
yum install -y gcc-c++
yum install -y wget
wget http://download.redis.io/releases/redis-5.0.4.tar.gz
tar -zxvf redis-5.0.4.tar.gz
cd redis-5.0.4
make && make install PREFIX=/root/redis/install_dir #目录不需要创建
(三)Redis服务启动和关闭
- 前端启动(可以看到默认端口是7379)
#启动命令
./redis-server
#关闭命令
#ctrl+C
#缺点
#客户端窗口不能关闭,否则redis-server进程就结束
- 后端启动
#第一步:拷贝redis配置文件到安装目录的bin目录下
cp /root/redis/redis-5.0.4/redis.conf /root/redis/install_dir/bin/
#第二步:打开redis.conf文件
vim redis.conf
#第三部:修改redis.conf文件
#将daemonize改为yes,守护进程改为启动
daemonize yes
#默认绑定的是回环地址,默认不能被其他机器访问
#bind 127.0.0.1
#是否开启保护模式,由yes改为no
protected-mode no
#第四步:启动服务
./redis-server redis.conf
#第五步:关闭服务
./redis-cli shutdown
-
其他命令说明
-
redis-server:启动redis服务
-
redis-cli:进入redis命令客户端
-
redis-benchmark:性能测试的工具
-
redis-check-aof:aof文件进行检查的工具
-
redis-check-dump:rdb文件进行检查的工具
注:aof和rdb都是redis持久化生成的工具,这俩命令用来对生成的文件进行检查
- redis-sentinel:启动哨兵监控服务
-
(四)Redis客户端
- Redis命令行
#单机模式以下两个命令等效,默认ip是本地,端口是6379
./redis-cli
./redis-cli -h 127.0.0.1 -p 6379
#测试
keys *
set test test
del keyname
-
Java客户端Jedis
- Jedis托管在github上,地址为https://github.com/xetorthio/jedis
- 添加maven依赖:
<dependencies> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.7.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.7.RELEASE</version> </dependency> <!-- 单元测试Junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies> <build> <plugins> <!-- 配置Maven的JDK编译级别 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build>
-
三种连接方式:
-
Jedis单实例
@Test public void testJedis() { //创建一个Jedis的连接 Jedis jedis = new Jedis("127.0.0.1", 6379); //执行redis命令 jedis.set("mytest", "hello world, this is jedis client!"); //从redis中取值 String result = jedis.get("mytest"); //打印结果 System.out.println(result); //关闭连接 jedis.close(); }
-
Jedis连接池
@Test public void testJedisPool() { //创建一连接池对象 JedisPool jedisPool = new JedisPool("127.0.0.1", 6379); //从连接池中获得连接 Jedis jedis = jedisPool.getResource(); String result = jedis.get("mytest") ; System.out.println(result); //关闭连接 jedis.close(); //关闭连接池 jedisPool.close(); }
-
Jedis集群
@Test public void testJedisCluster() throws Exception { //创建一连接,JedisCluster对象,在系统中是单例存在 Set<HostAndPort> nodes = new HashSet<>(); nodes.add(new HostAndPort("192.168.242.129", 7001)); nodes.add(new HostAndPort("192.168.242.129", 7002)); nodes.add(new HostAndPort("192.168.242.129", 7003)); nodes.add(new HostAndPort("192.168.242.129", 7004)); nodes.add(new HostAndPort("192.168.242.129", 7005)); nodes.add(new HostAndPort("192.168.242.129", 7006)); JedisCluster cluster = new JedisCluster(nodes); //执行JedisCluster对象中的方法,方法和redis一一对应。 cluster.set("cluster-test", "my jedis cluster test"); String result = cluster.get("cluster-test"); System.out.println(result); //程序结束时需要关闭JedisCluster对象 cluster.close(); }
-
-
Jedis整合Spring
- 配置spring配置文件applicationContext.xml及测试代码
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 连接池配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <!-- 最大连接数 --> <property name="maxTotal" value="30" /> <!-- 最大空闲连接数 --> <property name="maxIdle" value="10" /> <!-- 每次释放连接的最大数目 --> <property name="numTestsPerEvictionRun" value="1024" /> <!-- 释放连接的扫描间隔(毫秒) --> <property name="timeBetweenEvictionRunsMillis" value="30000" /> <!-- 连接最小空闲时间 --> <property name="minEvictableIdleTimeMillis" value="1800000" /> <!-- 连接空闲多久后释放, 当空闲时间>该值&&空闲连接>最大空闲连接数=>直接释放 --> <property name="softMinEvictableIdleTimeMillis" value="10000" /> <!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 --> <property name="maxWaitMillis" value="1500" /> <!-- 在获取连接的时候检查有效性, 默认false --> <property name="testOnBorrow" value="true" /> <!-- 在空闲时检查有效性, 默认false --> <property name="testWhileIdle" value="true" /> <!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true --> <property name="blockWhenExhausted" value="false" /> </bean> <!-- redis单机 通过连接池 --> <bean id="jedisPool" class="redis.clients.jedis.JedisPool" destroy-method="close"> <constructor-arg name="poolConfig" ref="jedisPoolConfig" /> <constructor-arg name="host" value="192.168.10.135" /> <constructor-arg name="port" value="6379" /> </bean> <!-- redis集群 --> <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster"> <constructor-arg index="0"> <set> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.10.135"></constructor-arg> <constructor-arg index="1" value="7001"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.10.135"></constructor-arg> <constructor-arg index="1" value="7002"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.10.135"></constructor-arg> <constructor-arg index="1" value="7003"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.10.135"></constructor-arg> <constructor-arg index="1" value="7004"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.10.135"></constructor-arg> <constructor-arg index="1" value="7005"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg index="0" value="192.168.10.135"></constructor-arg> <constructor-arg index="1" value="7006"></constructor-arg> </bean> </set> </constructor-arg> <constructor-arg index="1" ref="jedisPoolConfig"></constructor-arg> </bean> </beans>
import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisCluster; import redis.clients.jedis.JedisPool; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:application.xml") public class TestJedis2 { @Autowired private JedisPool jedisPool; @Resource private JedisCluster cluster; @Test public void testJedisPool() { // 从连接池中获得连接 Jedis jedis = jedisPool.getResource(); String result = jedis.get("mytest"); System.out.println(result); // 关闭连接 jedis.close(); } @Test public void testJedisCluster() throws Exception { // 执行JedisCluster对象中的方法,方法和redis一一对应。 cluster.set("cluster-test", "my jedis cluster test"); String result = cluster.get("cluster-test"); System.out.println(result); } }
三、Redis数据类型
注:redis单个命令执行,不管有多少个进程,都能保证原子性,但是多个命令执行的时候不能保证原子性,需要通过事务控制。
(一)String类型
get key
set key value
setnx key value
incr key
(二)Hash类型
hset key field value
hget key field
hmget key field [field...]
del key
hdel key field [field...]
(三)List类型
lpush key value [value...]
rpush key value [value...]
lpop key
rpop key
lrange key left right/-1 查询所有的
lrem key value
(四)Set类型(无序不重复)
sadd/srem key member [member....]
smembers key
sismember key member
sdiff key key (差集)
sinter key key (交集)
sunion key key (并集)
scard key 获取数量
spop key(随机选择一个元素弹出)
(五)SourtedSet类型
zadd key score member [score member...]
zrange/zrevrange key start stop ( 从小到大、从大到小 )
zscore key member
zrem key member
用于销售排行榜
(六)通用命令
keys pattern
del key
exists key
expire(重点,缓存使用)
rename
type
四、Redis消息模式
(一)队列模式
(二)发布订阅模式
五、Redis事务
确保多个命令事务一致,redis没有事务回滚
multi ——> 命令队列 ——> exec 去除队列中的命令进行执行
watch可以对某一个或多个key进行监控,如果监控key数据发生变化,则事务不会执行,否则事务执行。
为什么不支持回滚(面试问题)
为了性能,同时大部分情况是由于语法错误或者类型错误导致的事务失败。