nosql,大规模分布式缓存遍天下,Internet的时代在中国由其走得前沿,这一切归功于我国特色的电商。因此nosql、大数据技术在中国应用的比国外还要前沿。从这一章开始我们将开始进入到真正的SOA、PAAS、SAAS、互联网的领域,因此每一篇我都会加入一小段业务的基础知识,让大家在学习技术的同时也可以了解一些业务,这边的业务不是指的business logic不是让大家去做业务人员,而是为大家带来IDEA,”没有做不到只有想不到“,阿里支付宝为什么发了。。。不是技术,而是它的IDEA。
14年1月时在上海参加过一个MagentoCom召集的电商峰会。会上一群LAO WAI在那边大谈自己的电商经验,有LV,有ADIDAS,bla...bla...bla...听着听着,真是觉得好笑。休息时随便问一个LAO WAI一个问题:
”你们知道什么叫一元秒杀吗?“
”你们知道什么7天无理由退货吗?“
”你们知道什么叫0体验吗?“
”你们有没有双11,双12,有没有交易量过亿。。。“
LAO WAI ”张嘴,流哈喇子,billions of transaction? billions“
看着他这个样子,我是硬忍住后来到WC一边抽烟一边笑,笑得连手上的烟头都抖了,唉。。。。。。
不是说国外的电商不这么干,而是经济体制决定了电商的发展道路不同,因为国外的电商是基于他们的”信任“式经济的模式下的,因此国外的电商基本都是信用卡、预先冲款、预售卡、充值卡这些,这也决定了国外没有什么1元秒杀。。。这些哄人气的东东。
另外一点就是国外人口也少,呵呵,这算是一个理由。
还有就是国外基本无”不是名牌“这一说,记得去法国onsite交流学习时,如果你穿的一件ADIDAS或者是NIKE或者是阿玛尼如果不是正宗名牌,是仿的话也会被警察抓住罚款,因此国外是个商品基本都有牌子。这是一种”互信“机制。
中国的电商虽然也是走线上、线下但是它多了一个”第三方资金委托“即支付宝、易宝、微信(微信是后起之秀)这种东东,因此这样的体制决定了”先验货,后付钱“的这种游戏规则。
加上中国人多,这下大数据、NOSQL、分布式这些技术当然成为了通向internet的重中之重了。
Redis是一个NOSQL,NOSQL有许多种,它们分为:
光知道这些NOSQL的名词是没有用的,关键在于要知道在哪种场景下选用哪种NOSQL才是我们真正要去掌握的。
我们这边说Redis就拿Redis说事吧,它能干什么呢?
docker@boot2docker:~$ docker run hello-world
Hello from Docker. This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the “hello-world” image from the Docker Hub. (Assuming it was not already locally available.) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash For more examples and ideas, visit: http://docs.docker.com/userguide/
cat ubuntu-14.04-x86_64.tar.gz |docker import - ubuntu:ubuntu14
这个过程会很快,完成后查看自己的image:
成功导入了ubuntu,这样我们就可以在docker中运行出一个自己的ubuntu了。
docker run -i -t ubuntu:ubuntu14 /bin/bash
以上运行后,进入了该ubuntu的bash环境。
注:如果上述命令出错,可以使用下面这条命令:
docker run -i -t ubuntu:ubuntu14 //bin/bash
两个 “/” 哈
如果你能看到类似于root@ubuntu14_这样的命令行界面说明你的ubuntu14也已经安装成功了,下面我们就要在这个docker->ubuntu14中安装和布署我们的Redis了,这个过程和在linux下一样。
在ubuntu14下先安装SSHD,以便于我们使用WINSCP这样的SFTP工具来管理我们的ubuntu14中的文件系统
docker run -t -i ubuntu/mk:v1 /bin/bash
第二步:
升级一下你的apt-get,它就是一个命令行IE下载工具,如果你不update,那么你apt-get的源、内核都为旧的,因此为了升级apt-get请键入下面的命令
apt-get update
第三步:
下载和安装openssh组件
apt-get install openssh-server openssh-client
修改你的root密码
passwd
第五步:
退出容器,并保存以上修改,如果docker在退出后你接着退出docker环境或者是关机那么刚才的4步全部不生效,你一定要commit它才能生效,为此:
docker ps -a来查到你latest的一次容器的ID,它是一组16进制一样的编码如:1edfb9aabde8890,有了这个container id我们就可以commit我们刚才装的openssh的环境了
docker commit 1edfb9aabde8890 ubuntu:ssh
运行带有openssh的ubuntu14以便于我们使用winscp这样的SFTP工具连入我们的ubuntu14中去,依次输入下面的命令:
docker kill $(docker ps -q)
docker rm $(docker ps -a -q)
Docker是这样的机制的,它可以开启多个容器,每个容器带着一堆的image(镜像),要删一个镜像必须先停止这个镜像所在的容器,再把这个镜像删除,因此我们使用上面这两条命令对于Docker来一个大扫除。
接着我们先查一下我们目前手头有的镜像
docker images你会看到一个images列表,里面有我们的ubuntu:14,有我们的ubuntu:ssh也有一个hello-world,我们把ubuntu:14这个镜像删了吧(为了保持干净哈)
每个image也它自己的id,即image id,因此你用docker images命令查到该镜像的id后可以使用:
docker rmi imageid这条命令把一个不用的镜像给删了。
接下去我们要启动我们的ubuntu14:ssh了,可以使用下面这条命令:
docker -d -p 122:22 ubuntu:ssh //usr/sbin/sshd -D
网上很多在ubuntu14下安装redis的教程都不对的,大家看了要上当的,原因在于如下,请各位看完:
就是用的这个redis-stable.tar.gz包,这是我在写博客时目前最新最稳定版本,修复了大量的BUG和完善了功能。
第二步:
下载后我们把该包上传到我们的docker中的ubuntu14中,我们把它放在/opt目录下
然后我们使用tar -zxvf redis-stable.tar.gz对它进行解压
解压后它就会生成一个redis-stable目录,进入该目录 cd redis-stable
别急,我们先一会编译和安装它
第三步:编译安装redis
我们先输入gcc -v 这个命令来查看我们的gcc版本,如果它低于4.2以下那么你在编译redis3.0.7时一定会碰到大量的出错信息,如前面所述,redis为gcc写成,最新的redis需要gcc4.2-5这个版本才能进行编译,而一般去年或者之前装的linux/unix 的 gcc都为4.0以下或者甚至是3.x版。
升级GCC先
apt-get install build-essential
升级后我们开始编译redis3.0.7了,为此我们需要在redis-stable目录下
键入如下命令:
make PREFIX=/usr/local/redis1 install
我们告知我们的GCC把redis-stable编译并同时安装在/usr/local/redis1目录下
这个过程很快,可能只有10秒钟时间(依据你的机器来说,建议使用>=8gb, 4核CPU的PC机),然后我们就可以看到everything ok了。我们进入/usr/local/redis1就可以看到我们刚才安装的redis3.0.7稳定版了。
我们进入我们的redis目录 cd /usr/local/redis1/bin
在此目录下我们即可以运行我们的redis server了,不过请别急,在启动前我们需要对redis进行一些配置。
我的博客面对的是“全栈式”工程师的,架构师只是成为全栈式工程师中的一个起点,如果你不会搭环境那么你就不能接触到最新的技术,因此这就是许多程序员工作了近5年,7年结果发觉也只会一个SSH的主要原因。
daemonize yes # When running daemonized, Redis writes a pid file in /var/run/redis.pid by # default. You can specify a custom pid file location here. pidfile "/var/run/redis/redis1.pid" # Accept connections on the specified port, default is 6379. # If port 0 is specified Redis will not listen on a TCP socket. port 7001我们把:
save 900 1 save 300 10 save 60 10000中的300 10 和60 10000注释掉。这边代表的是:
docker -d -p 122:22 -p 7001:7001 redis:basic //usr/sbin/sshd -D
好了,用putty连入这个image的进程并启动redis服务,然后我们拿windows中的redis-cli命令来连。
如果在linux环境下还是没有连通(可能的哦),那是因为你没有禁用linux下的防火墙,我们可以使用iptables -F来禁用linux的防火墙或者使用:
vi /etc/selinux/config
然后把
SELINUX=enforcing 这句用”#“注释掉
增加一句: SELINUX=disabled #增加
这样每次启动后linux都不会有iptables的困扰了(这是在本机环境下这么干哦,如果你是生产环境请自行加iptables策略以允许redis服务端口可以被访问)。
看到下面这个PONG即代表你的redis服务已经在网络环境中起效了。
下面我们要开始使用JAVA客户端来连我们的Redis Service了。
在此我们需要使用spring data和jedis,下面给出相关的maven配置
<dependencies> <!-- poi start --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>${poi_version}</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>${poi_version}</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-scratchpad</artifactId> <version>${poi_version}</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>${poi_version}</version> </dependency> <!-- poi end --> <!-- active mq start --> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-all</artifactId> <version>5.8.0</version> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-pool</artifactId> <version>${activemq_version}</version> </dependency> <dependency> <groupId>org.apache.xbean</groupId> <artifactId>xbean-spring</artifactId> <version>3.16</version> </dependency> <!-- active mq end --> <!-- servlet start --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>${javax.servlet-api.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- servlet end --> <!-- redis start --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.7.2</version> </dependency> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>1.0.2</version> </dependency> <!-- redis end --> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <!-- spring conf start --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.6.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.6.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session</artifactId> <version>${spring.session.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <!-- spring conf end --> </dependencies>
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- - Location of the XML file that defines the root application context - Applied by ContextLoaderListener. --> <!-- tag::context-param[] --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:/spring/redis-conf.xml </param-value> </context-param> <!-- end::context-param[] --> <!-- tag::springSessionRepositoryFilter[] --> <filter> <filter-name>springSessionRepositoryFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSessionRepositoryFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> <!-- end::springSessionRepositoryFilter[] --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/spring/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- - Loads the root application context of this web app at startup. - The application context is then available via - WebApplicationContextUtils.getWebApplicationContext(servletContext). --> <!-- tag::listeners[] --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- end::listeners[] --> <servlet> <servlet-name>sessionServlet</servlet-name> <servlet-class>sample.SessionServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>sessionServlet</servlet-name> <url-pattern>/servlet/session</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
这边主要是一个:
<filter> <filter-name>springSessionRepositoryFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSessionRepositoryFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <session-config> <session-timeout>30</session-timeout> </session-config>这个filter一定要写在一切filter之前
package sample; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * Created by mk on 15/1/7. */ @Controller @EnableRedisHttpSession public class SessionController { @RequestMapping("/mySession") public String index(final Model model, final HttpServletRequest request) { if (request.getSession().getAttribute("testSession") == null) { System.out.println("session is null"); request.getSession().setAttribute("testSession", "yeah"); } else { System.out.println("not null"); } return "showSession"; } }
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>showSession</title> </head> <body> <% String sessionValue=(String)session.getAttribute("testSession"); %> <h1>Session Value From Servlet is: <%=sessionValue%></h1> </body> </html>
保证我们的redise-server是启动的,然后我们启动起这个web工程后使用:
http://localhost:8080/webpoc/mySession访问一下这个controller
此时我们使用redis客户端工具连入查看spring session是否已经进入到了redis中去。
在redis客户端工具连入后我们可以在redis console中使用keys *来查看存入的key,LOOK,spring的session存入了redis中去了。
再来看我们的eclipse后台,由于我们是第一次访问这个controller,因此这个session为空,因此它显示如下:
我们在IE中再次访问该controller
由于之前的session已经存在于redis了,因此当用户在1800秒(30分钟)内再次访问controller,它会从session中获取该session的key testSession的值,因此eclipse后台打印为not null。
讲过了spring session+redis我们来讲使用spring data框架提供的redisTemplate来访问redis service吧。说实话,spring这个东西真强,什么都可以集成,cassandra, jms, jdbc...jpa...bla...bla...bla...Spring集成Barack Hussein Obama? LOL :)
不用列了,上面有了
不用列了,上面有了
也不用列了,上面也有了
package sample; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.data.redis.core.BoundHashOperations; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisSentinelPool; import util.CountCreater; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * Created by xin on 15/1/7. */ @Controller public class SentinelController { @Autowired private StringRedisTemplate redisTemplate; @RequestMapping("/sentinelTest") public String sentinelTest(final Model model, final HttpServletRequest request, final String action) { return "sentinelTest"; } @ExceptionHandler(value = { java.lang.Exception.class }) @RequestMapping("/setValueToRedis") public String setValueToRedis(final Model model, final HttpServletRequest request, final String action) throws Exception { CountCreater.setCount(); String key = String.valueOf(CountCreater.getCount()); Map mapValue = new HashMap(); for (int i = 0; i < 1000; i++) { mapValue.put(String.valueOf(i), String.valueOf(i)); } try { BoundHashOperations<String, String, String> boundHashOperations = redisTemplate .boundHashOps(key); boundHashOperations.putAll(mapValue); System.out.println("put key into redis"); } catch (Exception e) { e.printStackTrace(); throw new Exception(e); } return "sentinelTest"; } }
观察我们的后台
然后使用redis client连入后进行查看
看。。。这个值key=1的,就是我们通过spring的redisTemplate存入进去的值,即使用下面这段代码进行存入的值:
for (int i = 0; i < 1000; i++) { mapValue.put(String.valueOf(i), String.valueOf(i)); } try { BoundHashOperations<String, String, String> boundHashOperations = redisTemplate.boundHashOps(key); boundHashOperations.putAll(mapValue);
redisTemplate.execute(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { connection.set( redisTemplate.getStringSerializer().serialize( "test"), redisTemplate .getStringSerializer() .serialize("hello")); return null; } });
原文:http://blog.csdn.net/lifetragedy/article/details/50628820