redis&nginx入门

Posted Lucky_龍

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis&nginx入门相关的知识,希望对你有一定的参考价值。

缓存简介

  • mybatis: 一级缓存(session) 二级缓存(同于一个mapper)

    openSession();

    .......

    commit();

    close();

    目的: 减少数据库的io访问

缓存

缓存就是数据存放在距离计算最近的位置以加快处理速度。缓存是改善软件性能的第一手段,缓存意在减少系统对数据库的过多访问,通过减少对数据库的访问次数,改用访问内存的方式,提升系统的性能。直接从内存获取数据,较之从数据库获取数据,效率可以得到显著的提升。提高客户端的体验。

系统由于多次查询数据库,消耗大量系统资源,且查询效率可能因为开发者的个人能力导致查询效率不高,或占用过多资源影响系统性能。使用缓存管理,系统只有第一次查询访问数据库,而后皆通过访问内存取得数据,不需要在计较这次查询的SQL是否过于复杂,是否效率低下,直接取得数据返回即可。

缓存的需求

缓存分类

  • 本地缓存:在应用服务器本地缓存着热点(频繁访问)数据,应用程序可以在本机内存中直接访问数据,而无需访问数据库。

  • 分布式缓存:在应用服务器的数据量非常庞大,即使只缓存一小部分,需要的内存空间也不是单机能承受的,所以除了本地缓存,还需要分布式缓存,将数据缓存在一个专门的分布式缓存集群中,应用程序通过网络通信访问数据。

主流的缓存技术介绍

主流缓存技术有Redis和Memcached。二者谁的性能更高?单纯从缓存命中的角度来说,是Memcached要高,Redis和Memcache的差距不大。但是,Redis提供的功能更加的强大。

区别

  • Memcache是多线程
  • Redis是单线程

redis介绍

Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库(数据结构),并提供多种语言的API。redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,phpjavascript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。

Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助

redis特点

  • 基于内存数据库(软件)
  • 存储数据的结构(key--value)
  • value提供了丰富的数据类型(string list set zset hash)

简单区分关系型数据库与非关系型数据库

  • 关系型数据库:mysql oracel db2 sqlserver ...

    规则的二维表:通过我们的主外键构建表关系

  • 非关系型数据库:Redis、Memcached、mongodb

    key-value(存储不规则数据)

redis的常用命令介绍

keys命令

用于显示当前库中匹配的key,如果为设置为*表示显示库中所有的key
192.168.18.200:6379> keys * 

exists命令

测试指定的key是否存在,如果存在返回1,不存在返回0。
192.168.18.200:6379> exists name
(integer) 1

192.168.18.200:6379> exists address
(integer) 0

del命令

删除库中指定的key的信息
192.168.18.200:6379> del name
> (integer) 1
> 可以一次性删除多个key的信息,同时返回被删除的个数。
> 192.168.18.200:6379> del name1 name2
> (integer) 2
> ```

## flushdb命令
```text
Flushdb 命令用于清空当前数据库中的所有 key,总是返回 OK。
192.168.18.200:6379> flushdb
OK

flushall命令

Flushall 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key)。
192.168.18.200:6379> flushall
OK

type命令

Type命令用于返回 key 所储存的值的类型。
192.168.18.200:6379> type name
string

redis的数据类型

Sring类型(做多的类型)

String类型介绍

string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。
string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。

String类型命令

set命令

设置key和value并保存到当前数据库中。
语法:set key  value
192.168.18.200:6379> set name zhangsan
OK

get命令

获取指定key的值
语法:get key
192.168.18.200:6379> get name
"zhangsan"

append命令

在原来的值的基础上追加新值,并返回总字符串的长度。
语法:append key value
192.168.18.200:6379> append name feng
(integer) 12

strlen命令

获取指定key的值的长度
语法:strlen  key
192.168.18.200:6379> strlen name
(integer) 12

getrange命令

获取指定key的值,从start位置开始,end位置结束
语法:getrange key  start  end
192.168.18.200:6379> getrange name 2 7
"angsan"

setrange命令

从起始位置替换值 
语法:setrange key offset value
192.168.18.200:6379> setrange name 2 abc
(integer) 12

setex命令

设置key的值并指定存活时间
语法:setex key second  value
192.168.18.200:6379> setex name2 100 lisi
OK

setnx命令

设置key的值并且永久有效
语法:setnx key value
192.168.18.200:6379> setnx address beijing
(integer) 1

incr命令

对key的值自增1
语法:incr key
192.168.18.200:6379>incr currentPage 

decr命令

对key的值自减1
语法:decr key
192.168.18.200:6379>decr currentPage

incrby命令

对key的值递增指定步长的值
语法:incrby key  number
192.168.18.200:6379>incrby currentPage 10

decrby命令

对key的值递减指定步长的值
语法:decrby key  number
192.168.18.200:6379>decrby currentPage 5

mset命令

一次性设置多个key-value键值对
语法:mset key1 value1 key2 value2 ....
192.168.18.200:6379>mset name1 zhangsan name2 lisi name3 wangwu

mget命令

一次性获取多个key的值
语法:mget key1 key2 ....
192.168.18.200:6379>mget name1 name2

expire命令

设置key的存活时间  seconds秒数
语法:ttl key 
192.168.18.200:6379>expire address 30

persist命令

设置指定的key永久有效 
语法: persist key 
192.168.18.200:6379>persist address

List类型

List类型介绍

Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
List  list = new ArrayList();
16个空间

List类型命令

lpush命令

向key集合的左边依次添加值
语法:lpush key value1 value2.... 
192.168.18.200:6379>lpush ages 22 34 21 45 20

rpush命令

向key集合的右边依次添加值
语法:rpush key value1 value2....
192.168.18.200:6379>192.168.18.200:6379>rpush names zhangsan lisi wangwu zhaoliu zhangsan

lrange命令

取key集合中指定的start位置到stop位置的内容(-1代表集合结束)
语法:lrange key start stop
192.168.18.200:6379>lrange ages 0 2
192.168.18.200:6379>lrange ages 0 -1
192.168.18.200:6379>lrange ages 0 100

llen命令

查看key集合的长度
语法:llen   key
192.168.18.200:6379>llen ages

lpop命令

删除key集合的第一个元素
语法:lpop   key
192.168.18.200:6379>lpop  ages

rpop命令

删除key集合的最后一个元素
语法:rpop   key
192.168.18.200:6379>rpop   ages

lindex命令

获取key集合的index索引的元素
语法:lindex  key  index
lindex   ages  2

lrem命令

删除key集合的count个索引的元素(集合中有重复值)  
语法:lrem key count value
192.168.18.200:6379>lrem ages 2  45

Hash类型

Hash类型介绍

Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。
比较适合存储java对象: key :  value([(属性名:属性值),(key:value)]);
map("key":Map<String,value>)

Hash类型命令

hset命令

设置key的field字段的值
语法:hset key  field  value
192.168.18.200:6379>hset person name lisi
192.168.18.200:6379>hset person address changsha
192.168.18.200:6379>hset person birthday 1997-10-10

hget命令

获取key的field字段的值
语法:hget key field
192.168.18.200:6379>hget person name

hmset命令

一次设置key的多个字段的值
语法:hmset key field1 value1  field2 value2 ....
192.168.18.200:6379>hmset student name wagnwu age 22 gender man

hmget命令

一次获取key的多个字段的值
语法:hmget key  field1 field2 ....
192.168.18.200:6379>hmget student name age gender

hgetall命令

获取key的多个字段的值(包括键和值)
语法:hgetall key  
192.168.18.200:6379>hgetall student

hkeys命令

获取key的所有字段
语法:hkeys key  
192.168.18.200:6379>hkeys student

hvals命令

获取key的所有字段的值
语法:hvals key  
192.168.18.200:6379>hvals student

hdel命令

删除大key小中指定的多个小key的值
语法:hdel key field1 field2 ... 
192.168.18.200:6379> hdel student name gender age

hlen命令

返回key的所有键值对的个数
语法: hlen key
192.168.18.200:6379>hlen student

hexists命令

返回key的field字段是否存在
语法:hexists key field 
192.168.18.200:6379>hexists student name

Set类型

Set类型介绍

Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。集合中最大的成员数为 232  - 1 (4294967295, 每个集合可存储40多亿个成员)。

Set类型命令

sadd命令

向为key的集合中添加多个值(去重)
语法:sadd  key  value1 value2 ...
192.168.18.200:6379>sadd empNames zhangsan lisi wangwu zhaoliu lisi

smembers命令

循环key集合中的所有值
语法:members   key
192.168.18.200:6379>smembers empNames

scard命令

统计key集合中的元素个数 
语法:scard   key 
192.168.18.200:6379> scard empNames

srem命令

删除key集合中的value值 
语法:srem    key   value 
192.168.18.200:6379>srem empNames  lisi

spop命令

 随机删除key集合中的某个值 
 语法:spop    key 
 192.168.18.200:6379>spop empNames
 

smove命令

将集合中的某个值赋给另外一个集合: SMOVE 源集合  目的集合  值 
语法:smove source destination member
192.168.18.200:6379>smove empNames works zhangsan

Sdiff命令

求差集  
语法:Sdiff   集合1  集合2 
192.168.18.200:6379>sadd seta a b c d e
192.168.18.200:6379> sadd setb c d e f g
192.168.18.200:6379>sdiff seta setb
1) "a"
2) "b"
sdiff setb seta
1) "f"
2) "g"

sinter命令

求交集
语法:sinter  集合1  集合2 
192.168.18.200:6379>sinter seta setb
1) "d"
2) "c"
3) "e"

sunion命令

求并集
语法:sunion  集合1  集合2 
192.168.18.200:6379>
sunion seta setb
1) "d"
2) "a"
3) "b"
4) "c"

sortedSet类型(zset)

sortedSet类型介绍

Redis 有序集合和list集合一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

sortedSet类型命令

zadd命令

向为key的集合中添加多个(score-value)
语法:zadd  key   score value ...
192.168.18.200:6379>zadd students 1 zhangsan 3 lisi 2 wangwu 5 zhaoliu

zrange命令

循环key的集合从start位到stop位置的值
语法:zrange key start stop [WITHSCORES]
192.168.18.200:6379>zrange students 0 -1
1) "zhangsan"
2) "wangwu"
3) "lisi"
4) "zhaoliu" 

zrem命令

删除key集合中指定的value元素。
语法:zrem key value
192.168.18.200:6379>zrem students lisi

zrevrange命令

逆序显示key集合中的元素。
语法:zrevrange key start stop   [WITHSCORES]
192.168.18.200:6379>zrevrange students 0 -1
192.168.18.200:6379>zrevrange students 0 -1 withscores

zrangebyscore命令

根据分数区间查询内容
语法:zrangebyscore key min max 
192.168.18.200:6379>zrangebyscore students 2 5

zcard命令

统计key集合中有多少个键值对
语法:zcard key  
192.168.18.200:6379> zcard students

zcount命令

统计key集合中min到max区间元素。
语法:zcount key min max 
zcount students 1  4 

zrank命令

统计key集合中指定元素索引。
语法:zrank students wangwu     
192.168.18.200:6379>zrank students wangwu 

zscore命令

统计key集合中指定元素的分数
语法:zscore key value
192.168.18.200:6379>zscore students zhangsan 

java操作redis(jedis)

单实例方式

构建maven工程添加依赖

<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

创建Jedis连接对象

Jedis jedis=new Jedis("192.168.18.200",6379);

操作redis数据库

 @Test
   public void testJedis() {
		Jedis jedis=new Jedis("192.168.18.131",6379);
		jedis.set("birthday", "1991-10-30");
		jedis.set("address", "beijing");
		String address=jedis.get("address");
		String birthday=jedis.get("birthday");
		System.out.println("address:"+address);
		System.out.println("birthday:"+birthday);
		jedis.close();
	}

连接池方式

Connection con 
c3p0连接

构建maven工程添加依赖

<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

构建连接池对象

//创建JedisPoolConfig对象
JedisPoolConfig poolConfig=new JedisPoolConfig();
//最大空闲连接数
poolConfig.setMaxIdle(3);
//大连接数
poolConfig.setMaxTotal(5);
//连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
poolConfig.setBlockWhenExhausted(true);
//获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常
poolConfig.setMaxWaitMillis(30000);
//在获取连接的时候检查有效性
poolConfig.setTestOnBorrow(true);
JedisPool jedisPool=new JedisPool(poolConfig,"192.168.18.200",6379,30000,"123456");

操作redis数据库

Jedis jedis=jedisPool.getResource();
jedis.set("name", "wangxiaobing");
jedis.set("age", "22");
String name=jedis.get("name");
String age=jedis.get("age");
System.out.println("name:"+name);
System.out.println("age:"+age);

Spring整合redis

整合思路分析

spring和redis的整合,其它就是把redis的实例化过程交给spring容器来实例化,现在我们创建Jedis对象是通过JedisPool获取的,而创建JedisPool就必须实体化JedisPoolConfig对象,所以我们把JedisPoolConfig、JedisPool都交给spring容管理,我们只从容器取获取JedisPool对象进行注入即可。

构建maven工程添加依赖

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.7</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
    </dependencies>

配置spring配置文件整合redis

<!-- 连接池的配置对象 -->
  <bean id="config" class="redis.clients.jedis.JedisPoolConfig">
      <property name="maxTotal" value="5"></property>
      <property name="maxIdle" value="3"></property>
      <property name="blockWhenExhausted" value="true"></property>
      <property name="maxWaitMillis" value="3000"></property>
      <property name="testOnBorrow" value="true"></property>
  </bean>
  <!-- 连接池的对象 -->
  <bean id="pool" class="redis.clients.jedis.JedisPool">
      <constructor-arg name="poolConfig" ref="config"></constructor-arg>
     <constructor-arg name="host" value="192.168.11.113"></constructor-arg>
     <constructor-arg name="port" value="6379"></constructor-arg>
     <constructor-arg name="timeout" value="3000"></constructor-arg>
      <constructor-arg name="password" value="123456"></constructor-arg>
  </bean>

编写测试代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JedisTest {

@Autowired
private JedisPool jedisPool;

@Test
public void testAddPerson(){
  Person person=new Person(100,"张三","男",22,new Date());
  Jedis jedis = jedisPool.getResource();
 // jedis.set("person", JsonUtils.objectToJson(person));
  jedis.hset("persons",person.getName(),JsonUtils.objectToJson(person));
  jedis.close();
}

@Test
public void testAddPerson2(){
Jedis jedis = jedisPool.getResource();
  String jsonData=jedis.get("person");
  Person person=JsonUtils.jsonToEntity(jsonData,Person.class);
  System.out.println(person);
  jedis.close();
  }
}

nginx的介绍

nginx概述

Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。

Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

Nginx是一款高性能的http 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。并且cpu、内存等资源消耗却非常低,运行非常稳定。

nginx的应用场景

  • http服务器。Nginx是一个http服务可以独立提供http服务。可以做网页静态服务器。

  • 虚拟主机。可以实现在一台服务器虚拟出多个网站。例如个人网站使用的虚拟主机(虚拟路径)。图片挂载:虚拟路径

  • 反向代理(nginx代理多台服务器),负载均衡(客户端压力平分到多个tomcat上)。当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。

nginx实现负载均衡

负载均衡介绍

负载均衡

负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。负载均衡构建在原有网络结构之上,它提供了一种透明且廉价有效的方法扩展服务器和网络设备的带宽、加强网络数据处理能力、增加吞吐量、提高网络的可用性和灵活性。

负载均衡设计思想

一台普通服务器的处理能力是有限的,假如能达到每秒几万个到几十万个请求,但却无法在一秒钟内处理上百万个甚至更多的请求。但若能将多台这样的服务器组成一个系统,并通过软件技术将所有请求平均分配给所有服务器,那么这个系统就完全拥有每秒钟处理几百万个甚至更多请求的能力。这就是负载均衡最初的基本设计思想。
负载均衡是由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须其他服务器的辅助。通过某种负载分担技术,将外部发送来的请求按照某种策略分配到服务器集合的某一台服务器上,而接收到请求的服务器独立地回应客户的请求。负载均衡解决了大量并发访问服务问题,其目的就是用最少的投资获得接近于大型主机的性能。

nginx实现动静分离

动静分离介绍

动静分离

动静分离是在web服务器架构中,将静态页面与动态页面或者静态内容接口和动态内容接口分开不同系统访问的架构设计方法,进而提升整个服务访问性能和可维护性。

动静分离优势

Tomcat处理静态资源的效率并没有Nginx高,我们可以通过动静分离将静态资源和动态资源分割开来,Tomcat处理动态资源,Nginx响应静态资源,从而减轻tomcat的压力,各自发挥自己的长处,从而提高响应速度,提高访问能力。

动静分离配置

创建文件名show.jsp的文件并在tomcat1上进行部署

<%@ page language="java" import="java.util.Date,java.text.SimpleDateFormat" ontentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>

<body>
<h1>这是tomcat1主页</h1>
	 <%
	      Date date=new Date();
		  SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		  String strDate=sdf.format(date);
	      out.println(strDate+"<br>");
	 %>
	 <img src="images/aaa.jpg">
</body>
</html>

在tomcat2上部署show.jsp文件

<%@ page language="java" import="java.util.Date,java.text.SimpleDateFormat" ontentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>

<body>
<h1>这是tomcat2主页</h1>
	 <%
	      Date date=new Date();
		  SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		  String strDate=sdf.format(date);
         out.println(strDate+"<br>");
	 %>
	 <img src="images/aaa.jpg">
</body>
</html>

在nginx上配置动静分离

 upstream tomcat{
	     server 192.168.18.201:8081 weight=2;
		 server 192.168.18.201:8082;
	}
server {
  listen    80;
  server_name  localhost;

  #charset koi8-r;

  #access_log  logs/host.access.log  main;

  location / {
      proxy_pass   http://tomcat;
      index  index.html index.htm;
  }

	 location ~\\.(jsp|do|action)$ {
     proxy_pass  http://tomcat;
  }

	 location ~\\.(html|css|js|gif|jpg|png|bmp|swf)$ {
      root  /usr/local/staticresources;
  }

将我们的静态资源存放到 /usr/local/staticresources位置中

测试

重新启动nginx

输入http://IP地址/show.jsp

以上是关于redis&nginx入门的主要内容,如果未能解决你的问题,请参考以下文章

Nginx学习---Nginx&&Redis&&hcache三层缓存架构总结

如何理解这段代码片段中的两对括号?

mq/mysql/redis/nginx常见服务&工具安装

Redis 笔记 01:入门篇

Redis入门实践

独家下载 | 《Redis+Nginx+设计模式+Spring全家桶+Dubbo》,附 PDF & 架构书籍 下载