胶州网站建设培训,wordpress模板剥离,手机视频制作软件,如何自己开网站引言nosql#xff0c;大规模分布式缓存遍天下#xff0c;Internet的时代在中国由其走得前沿#xff0c;这一切归功于我国特色的电商。因此nosql、大数据技术在中国应用的比国外还要前沿。从这一章开始我们将开始进入到真正的SOA、PAAS、SAAS、互联网的领域#xff0c;因此每… 引言nosql大规模分布式缓存遍天下Internet的时代在中国由其走得前沿这一切归功于我国特色的电商。因此nosql、大数据技术在中国应用的比国外还要前沿。从这一章开始我们将开始进入到真正的SOA、PAAS、SAAS、互联网的领域因此每一篇我都会加入一小段业务的基础知识让大家在学习技术的同时也可以了解一些业务这边的业务不是指的business logic不是让大家去做业务人员而是为大家带来IDEA”没有做不到只有想不到“阿里支付宝为什么发了。。。不是技术而是它的IDEA。业务基础知识-国内国外电商比较以及为什么电商技术在中国走得这么前沿14年1月时在上海参加过一个MagentoCom召集的电商峰会。会上一群LAO WAI在那边大谈自己的电商经验有LV有ADIDASbla...bla...bla...听着听着真是觉得好笑。休息时随便问一个LAO WAI一个问题”你们知道什么叫一元秒杀吗“”你们知道什么7天无理由退货吗“”你们知道什么叫0体验吗“”你们有没有双11双12有没有交易量过亿。。。“LAO WAI ”张嘴流哈喇子billions of transaction? billions“看着他这个样子我是硬忍住后来到WC一边抽烟一边笑笑得连手上的烟头都抖了唉。。。。。。不是说国外的电商不这么干而是经济体制决定了电商的发展道路不同因为国外的电商是基于他们的”信任“式经济的模式下的因此国外的电商基本都是信用卡、预先冲款、预售卡、充值卡这些这也决定了国外没有什么1元秒杀。。。这些哄人气的东东。另外一点就是国外人口也少呵呵这算是一个理由。还有就是国外基本无”不是名牌“这一说记得去法国onsite交流学习时如果你穿的一件ADIDAS或者是NIKE或者是阿玛尼如果不是正宗名牌是仿的话也会被警察抓住罚款因此国外是个商品基本都有牌子。这是一种”互信“机制。中国的电商虽然也是走线上、线下但是它多了一个”第三方资金委托“即支付宝、易宝、微信微信是后起之秀这种东东因此这样的体制决定了”先验货后付钱“的这种游戏规则。加上中国人多这下大数据、NOSQL、分布式这些技术当然成为了通向internet的重中之重了。进入Redis课程Redis是什么Redis是一个NOSQLNOSQL有许多种它们分为列存储如Hbase、Cassandra这种文档存储如MongoDB首推key-value存储如Berkeley DB、MemcacheDB、Redis其中Redis最强图存储这块基本不用有Neo4j、VersantXML存储如Berkeley DB Xml还有XBASEORACLE很早已经支持这种存储方式了光知道这些NOSQL的名词是没有用的关键在于要知道在哪种场景下选用哪种NOSQL才是我们真正要去掌握的。我们这边说Redis就拿Redis说事吧它能干什么呢Redis基础应用场景web间session共享即多个war工程共享一个session分布式缓存因为redis为键值对而且它提供了丰富的adapter可以支持到C、.net、java客户端因此对于异质平台间进行数据交换起到了作用因此它可以用作大型系统的分布式缓存并且其setnx的锁常被用于”秒杀“”抢红包“这种电商活动场景中。安装Redis我本来想在这儿写”Redis上的‘坑‘“最后我还是觉得把它放到后面章节中去写吧因为中国人的思维是先有感性再有理性的一种逆向思维其实这点很像美国人因此中国人在世界上是最聪明的民族之一所以我们还是先从动手搭一个Redis的环境来说起吧老规矩红色加粗很重要。一定要使用Linux来布署Redis请不要偷懒使用Redis 2.8.1 for windows那个版本如果你使用了这个版本你将无法跟上这一系列教程的步伐。因为Redis为GCC这样的东西开发出来的它天生就是运行在LINUX/Unix环境下的而那个windows版的Redis是一个”烟“割版而且是一个unofficial的版本非官方授权的哈。先从Docker开始如果已经有Linux/Unix环境的同协们可以直接跳过这一章。我们这边要开始变态了因为我们要真正开始踏上SOA、PAAS、互联网的脚步了。如果对于没有Linux/Unix环境的用户来说我在这边推荐使用docker即boot2docker windows版来安装它下载后是一个这样的文件安装前把你的网络连接中的IPV6协议前的勾去掉双击它在安装时记得选择Virtual-Box选项因为docker本为linux/unix下之物因此为了在windows下使用dockerboot2docker内嵌了一个virtualbox来虚拟docker的环境。装完后它会在你的桌面上生成一个蓝色的图标双击它它会打开一个绿色的字黑色的背景像matrix电影里的那种命令行窗口这就是Docker。装完后运行dockerboot2docker:~$ 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 bashFor more examples and ideas, visit: http://docs.docker.com/userguide/说明你的Docker安装成功了。在Docker中安装unix环境有了Docker我们就用Docker虚拟一个UbuntuUNIX环境吧在这边我们使用的是Ubuntu14。ubuntu14请下载这个包戳: 下载Ubuntu14包下载后直接在docker下运行下面这条命令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两个 “/” 哈如果你能看到类似于rootubuntu14_这样的命令行界面说明你的ubuntu14也已经安装成功了下面我们就要在这个docker-ubuntu14中安装和布署我们的Redis了这个过程和在linux下一样。在ubuntu14下先安装SSHD以便于我们使用WINSCP这样的SFTP工具来管理我们的ubuntu14中的文件系统在ubuntu14中安装SSHD第一步docker run -t -i ubuntu/mk:v1 /bin/bash进入我们的ubuntu环境这边的ubuntu/mk就是我本机的docker中ubuntu14 container容器的名字如果按照上面的延续此处可以替换成ubuntu:ubuntu14这个名字吧。第二步升级一下你的apt-get它就是一个命令行IE下载工具如果你不update那么你apt-get的源、内核都为旧的因此为了升级apt-get请键入下面的命令apt-get update这个过程很快依赖于你的网络环境第三步下载和安装openssh组件apt-get install openssh-server openssh-client第四步修改你的root密码passwd键入两次你的root密码我这边都为6个小写的a第五步退出容器并保存以上修改如果docker在退出后你接着退出docker环境或者是关机那么刚才的4步全部不生效你一定要commit它才能生效为此你先要知道你刚才用docker run命令运行的ubuntu14的容器的ID你可以使用docker ps -a来查到你latest的一次容器的ID它是一组16进制一样的编码如1edfb9aabde8890有了这个container id我们就可以commit我们刚才装的openssh的环境了commit刚才在容器中所做的修改docker commit 1edfb9aabde8890 ubuntu:ssh第六步运行带有openssh的ubuntu14以便于我们使用winscp这样的SFTP工具连入我们的ubuntu14中去依次输入下面的命令docker kill $(docker ps -q)杀掉正在运行的所有的container的进程docker rm $(docker ps -a -q)删除所有在进程中的容器以上2步又被称为docker大扫除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这条命令的意思为-d即把我们的image启动在后台进程它将会是一个daemon进程而不会像刚才我们使用-t一样一旦exit后该image进程也自动退出了-p为端口映射什么意思呢这边要说一下docker的端口映射问题。我们知道docker安装后它会利用virtualbox中的vhost only的nat机制来建立一个虚拟的IP可以打开我们的virtualbox中在菜单”全局-设定-网络”中进行查找所以我们可以知道一旦boot2docker环境运行后它的地址为192.168.56.*这个段一般为192.168.56.101这个地址你可以在boot2docker启动后直接使用winscp边入这个docker环境。地址192.168.56.101端口22用户名docker密码tcuser以上为默认值具体地址按照你的virtualbox中在boot2docker安装时自动给出的设置来做参考。而我们在这个docker中安装了一个ubuntu14:ssh的image然后用后台进程的方式打开了这个ubuntu14:ssh因此它自己也有一个IP可能是172也可能是169段具体不得而知一般来说它是每次启动镜像后自己变换的可以使用动态网络域名绑定docker中镜像的ip来达到域名不变的目的-集群环境下有用。我们都知道ssh是以端口22来进行TCP连接的因此我们把ubuntu14的IP上的22端口映射到了我们的docker主机192.168.56.101上的122端口。参数//usr/sbin/sshd -D代表该镜像启动会的entrypoint即启动后再启动一个什么命令在最后的-D大写的D告诉docker这是一个启动文件于是一旦该命令发出后显示image启动的提示后启动后你会得到一个image id你就可以直接打开你的winscp使用地址192.168.56.101端口122 此处是122不是22因为我们把image的22端口映射到了192.168.56.101-docker主机上的122端口了用户名root密码aaaaaa即可以连入我们的ubuntu14环境了如果此时你安装了putty还可以使用puttywinscp直接进入ubuntu14的命令行环境中去于是你就有ubuntu14的试验环境了。在ubuntu14下安装redis网上很多在ubuntu14下安装redis的教程都不对的大家看了要上当的原因在于如下请各位看完网上的redis环境搭建直接使用的是apt-get update完后用wget https://github.com/ijonas/dotfiles/raw/master/etc/init.d/redis-server 这样的方式来安装的这样装固然方便可是也因为方便所以取到的redis不是最新的redis版本一般为2.8.x版或者是redis3.0.rc这依赖于你的unit/linux所连接的wget库redis为c写成它的2.4-2.8版都为不稳定版或者是缺少功能或者是有bug而这些bug在你如果真正使用redis作为网站生产环境时将会因为这些bug而无法面对峰涌而来的巨大并发因此当有这样的redis运行了一段时间后你的生产环境会面临着巨大的压力还是redis不够新不够稳定的原因由于在redis3前redis还不支持集群、主备高可用方案的功能因此不得不依靠于繁杂的打补丁式的如linux/unix-keepalive或者是haproxy这种系统级层面然后写一堆的复杂脚本去维护你的redis集群还要用外部手段Linux/Unix Shell脚本去维护多个redis节点间的缓存数据同步。。。这这这。。。不复合我们的网站扩容、增量、运维和面对巨大用户万级并发-最高支持百万用户如新浪微博、微信的场景因此我在这边推荐大家使用下面我将要使用的“下载源码包结合你本机的Linux/Unix内核进行实时编译”的安装过程。第一步下载redis目前最稳定版本也是功能最完善集群支持最好并加入了sentinel哨兵-高可用功能的redis3.0.7版即redis-stable版为此我们需要获取redis-stable版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因此apt-get update显得很重要要不然你获取的gcc也将不是最新的版本目前我的gcc为5.3.1为这周刚做的升级。升级后我们开始编译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的主要原因。Redis3配置要领使用winscp通过122连入docker下的ubuntu14进行redis的配置。我们需要编辑的文件为/usr/local/redis1/bin/redis.conf这个文件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
我们把:daemonize设为yes使得redis以后台进程的方式来运行你可以认为为“server”模式如果redis以server模式运行的话它会生成一个pid文件 因此我们把它的路径放在/var/run/redis目录中并命名它为redis1.pid文件 为此你需要在/var/run目录下建立redis这个目录端口号我们把它设为7001这样好辩识因为将来我们会进一步做redis集群所以我们的redis都为redis1, redis2, redis3那么我们的端口号也为7001, 7002, 7003。。。这样来延续。那么很多同协这时要问了“为什么我们不把它命名成master, slave1, slave2这样的名字呢”理由很简单无论是现在的hadoop还是zookeeper它们的集群是跨机房的多个master间也有MASTER-SLAVE模式互为备份因为一些大型网站不仅仅只有一个IDC机房它们一般都会有2个3个IDC机房或者是在同一个IDC机房中有“跨机柜”的布署来形成超大规模集群就和ALI的TAOBAO网一样它在北美都有机房因此当你需要在LOCAL NATIVE建一个IDC机房在北美再做一个机房你不要想把一个MASTER设在中国SLAVE设到美国去而是多地甚至是多机柜都有MASTER一旦一个MASTER宕机了这种集群会通过一个叫“选举策略”选出一个节点把这个节点作为当前“群”的MASTER因此我们的命名才会是redis1, redis2, redis3...这样来命名的。此处把原来的save 900 1
save 300 10
save 60 10000中的300 10 和60 10000注释掉。这边代表的是redis以每900秒写一次、300秒写10次60秒内写1万次这样的策略把缓存放入一个叫.rdb的磁盘文件中这点和ehcache或者是memcache很像以便于redis在重启时可以从本地持久化文件中找出关机前的数据记录。如果按照默认的话此三个策略会轮流起效在大并发环境中这样的写策略将会对我们的性能造成巨大的影响因此我们这边只保留900秒写1次这条策略这边有人会问如果你这样会有数据丢失怎么办。。。别急这个问题我们后面会解答这涉及到redis的“正确”使用如果它只是一个缓存我相信5分钟内缓存的丢失此时程序直接访问数据库也不会有太大问题又要保证数据完整性又要保证性能这本身是一个矛与盾的问题除非你钱多了烧那我会给出你一个烧钱的配置策略连新浪都不会这么烧钱呵呵。dbfilename此处我们维持redis原有的缓存磁盘文件的原名dir /usr/local/redis1/data为rdb文件所在的目录这边大家要注意的是一个是只能写文件名另一个地方只能写目录名。为此我们需要在/usr/local/redis1下建立 data目录。把此处的appendonly设为no这样我们就关闭了Redis的AOF功能。AOF 持久化记录服务器执行的所有写操作命令并在服务器启动时通过重新执行这些命令来还原数据集。AOF是redis在集群或者是高可用环境下的一个同步策略它会不断的以APPEND的模式把redis的缓存中的数据从一个节点写给另一个节点它对于数据的完整性保证是要高于rdb模式的。RDB 是一个非常紧凑compact的文件它保存了 Redis 在某个时间点上的数据集。 这种文件非常适合用于进行备份 比如说你可以在最近的 24 小时内每小时备份一次 RDB 文件并且在每个月的每一天也备份一个 RDB 文件。 这样的话即使遇上问题也可以随时将数据集还原到不同的版本。RDB 非常适用于灾难恢复disaster recovery它只有一个文件并且内容都非常紧凑可以在加密后将它传送到别的数据中心如阿里的mysql异地机房间使用FTP传binlog的做法。按照官方的说法启用AOF功能可以在redis高可用环境中如果发生了故障客户的数据不会有高于2秒内的历史数据丢失它换来的代价为高昂的I/O开销有些开发者为了追求缓存中的数据100%的正确有时会碰到因为redis在AOF频繁刷新时整个环境如死机一的情况并且你会看到恶梦一般的”Asynchronous AOF fsync is taking too long “警告信息这是因为redis它是单线程的它在进行I/O操作时会阻塞住所有的操作包括登录。。。这个很可怕不过这个BUG/ISSUE已经在最新redis中进行了优化它启用了另一根进程来进行AOF刷新包括优化了RDB持久化功能这也是为什么我让大家一定一定要用最新最稳定版的redis的原因。一般默认情况下redis内的rdb和AOF功能同为开启如果RDB的数据不实时同时使用两者时服务器重启也只会找AOF文件。因为RDB文件只用作后备用途建议只在Slave上持久化RDB文件而且只要15分钟备份一次就够了所以我只保留save 900 1这条规则。如果Enalbe AOF好处是在最恶劣情况下也只会丢失不超过两秒数据启动脚本较简单只load自己的AOF文件就可以了。代价一是带来了持续的IO二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可应该尽量减少AOF rewrite的频率AOF重写的基础大小默认值64M太小了可以设到5G以上。默认超过原大小100%大小时重写这边可以设定一个适当的数值。如果不Enable AOF 仅靠Master-Slave Replication 实现高可用性也可以。能省掉极大的IO也减少了rewrite时带来的系统波动。代价是如果Master/Slave同时倒掉那你的网站基本也就歇了会丢失十几分钟的数据启动脚本也要比较两个Master/Slave中的RDB文件载入较新的那个。新浪微博就选用了这种架构。最后我们不要忘了设一个redis的log文件在此我们把它设到了/var/log/redis目录为此我们需要在/var/log目录下建立一个redis目录。好了保存后我们来启动我们的redis吧。我们使用以下这条命令来启动我们的redis server。然后我们在我们的windows机上装一个windows版的redis 2.8.1 for windows只用它来作为redis的client端然后我们在windows环境下使用redis-cli -p 7001 -h 192.168.56.101咦没反映连不上哈哈。。。。。。那是肯定连不上的因为我们刚才在用docker启动ubuntu14时使用docker -d -p 122:22 ubuntu:ssh //usr/sbin/sshd -D来启动的这边我们并未把redis服务的7001端口映射到192.168.56.101这台docker主机上怎么可以通过windows主机可能windows的ip为169.188.xx.xx来访问docker内的进程服务呢对吧为此我们先把刚才做了这么多的更改docker commit成一个新的image如redis:basic吧。然后我们对docker进行一次大扫除然后我们启动redis:basic这个image并使用以下命令docker -d -p 122:22 -p 7001:7001 redis:basic //usr/sbin/sshd -D看此处我们可以使用多个-p来作docker内容器的多端口映射策略它其实使用的就是iptables命令。好了用putty连入这个image的进程并启动redis服务然后我们拿windows中的redis-cli命令来连。如果在linux环境下还是没有连通可能的哦那是因为你没有禁用linux下的防火墙我们可以使用iptables -F来禁用linux的防火墙或者使用vi /etc/selinux/config然后把SELINUXenforcing 这句用”#“注释掉增加一句 SELINUXdisabled #增加这样每次启动后linux都不会有iptables的困扰了这是在本机环境下这么干哦如果你是生产环境请自行加iptables策略以允许redis服务端口可以被访问。看到下面这个PONG即代表你的redis服务已经在网络环境中起效了。下面我们要开始使用JAVA客户端来连我们的Redis Service了。使用Spring Data JEDIS来连接Redis ServiceSpringSessionRedispom.xml在此我们需要使用spring data和jedis下面给出相关的maven配置 dependencies!-- poi start --dependencygroupIdorg.apache.poi/groupIdartifactIdpoi/artifactIdversion${poi_version}/version/dependencydependencygroupIdorg.apache.poi/groupIdartifactIdpoi-ooxml-schemas/artifactIdversion${poi_version}/version/dependencydependencygroupIdorg.apache.poi/groupIdartifactIdpoi-scratchpad/artifactIdversion${poi_version}/version/dependencydependencygroupIdorg.apache.poi/groupIdartifactIdpoi-ooxml/artifactIdversion${poi_version}/version/dependency!-- poi end --!-- active mq start --dependencygroupIdorg.apache.activemq/groupIdartifactIdactivemq-all/artifactIdversion5.8.0/version/dependencydependencygroupIdorg.apache.activemq/groupIdartifactIdactivemq-pool/artifactIdversion${activemq_version}/version/dependencydependencygroupIdorg.apache.xbean/groupIdartifactIdxbean-spring/artifactIdversion3.16/version/dependency!-- active mq end --!-- servlet start --dependencygroupIdjavax.servlet/groupIdartifactIdservlet-api/artifactIdversion${javax.servlet-api.version}/versionscopeprovided/scope/dependencydependencygroupIdjavax.servlet.jsp/groupIdartifactIdjsp-api/artifactIdversion2.1/versionscopeprovided/scope/dependencydependencygroupIdjavax.servlet/groupIdartifactIdjstl/artifactIdversion1.2/version/dependency!-- servlet end --!-- redis start --dependencygroupIdredis.clients/groupIdartifactIdjedis/artifactIdversion2.7.2/version/dependencydependencygroupIdorg.redisson/groupIdartifactIdredisson/artifactIdversion1.0.2/version/dependency!-- redis end --dependencygroupIdorg.slf4j/groupIdartifactIdjcl-over-slf4j/artifactIdversion${slf4j.version}/version/dependencydependencygroupIdorg.slf4j/groupIdartifactIdslf4j-log4j12/artifactIdversion${slf4j.version}/version/dependency!-- spring conf start --dependencygroupIdorg.springframework.data/groupIdartifactIdspring-data-redis/artifactIdversion1.6.2.RELEASE/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-webmvc/artifactIdversion${spring.version}/versionexclusionsexclusiongroupIdcommons-logging/groupIdartifactIdcommons-logging/artifactId/exclusion/exclusions/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-tx/artifactIdversion${spring.version}/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-aop/artifactIdversion${spring.version}/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-context-support/artifactIdversion${spring.version}/version/dependencydependencygroupIdorg.springframework.data/groupIdartifactIdspring-data-redis/artifactIdversion1.6.2.RELEASE/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-orm/artifactIdversion${spring.version}/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-jms/artifactIdversion${spring.version}/version/dependencydependencygroupIdorg.springframework.session/groupIdartifactIdspring-session/artifactIdversion${spring.session.version}/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-core/artifactIdversion${spring.version}/version/dependency!-- spring conf end --/dependenciesredis-config.xml?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:phttp://www.springframework.org/schema/pxmlns:contexthttp://www.springframework.org/schema/contextxmlns:jeehttp://www.springframework.org/schema/jee xmlns:txhttp://www.springframework.org/schema/txxmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocation http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdcontext:property-placeholder locationclasspath:/spring/redis.properties /context:component-scan base-packageorg.sky.redis/context:component-scanbean idjedisConnectionFactoryclassorg.springframework.data.redis.connection.jedis.JedisConnectionFactoryproperty namehostName value${redis.host.ip} /property nameport value${redis.host.port} /property namepoolConfig refjedisPoolConfig //beanbean idjedisPoolConfig classredis.clients.jedis.JedisPoolConfigproperty namemaxTotal value${redis.maxTotal} /property namemaxIdle value${redis.maxIdle} /property namemaxWaitMillis value${redis.maxWait} /property nametestOnBorrow value${redis.testOnBorrow} /property nametestOnReturn value${redis.testOnReturn} //beanbean idredisTemplate classorg.springframework.data.redis.core.StringRedisTemplateproperty nameconnectionFactory refjedisConnectionFactory //bean!--将session放入redis --bean idredisHttpSessionConfigurationclassorg.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfigurationproperty namemaxInactiveIntervalInSeconds value1800 //beanbean idcustomExceptionHandler classsample.MyHandlerExceptionResolver /
/beans redis.propertiesredis.host.ip192.168.0.101
redis.host.port6379redis.maxTotal1000
redis.maxIdle100
redis.maxWait2000
redis.testOnBorrowfalse
redis.testOnReturntrue
web.xml?xml version1.0 encodingUTF-8?
web-app version2.5 xmlnshttp://java.sun.com/xml/ns/javaeexmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://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-paramparam-namecontextConfigLocation/param-nameparam-valueclasspath:/spring/redis-conf.xml/param-value/context-param!-- end::context-param[] --!-- tag::springSessionRepositoryFilter[] --filterfilter-namespringSessionRepositoryFilter/filter-namefilter-classorg.springframework.web.filter.DelegatingFilterProxy/filter-class/filterfilter-mappingfilter-namespringSessionRepositoryFilter/filter-nameurl-pattern/*/url-pattern/filter-mappingsession-configsession-timeout30/session-timeout/session-config!-- end::springSessionRepositoryFilter[] --filterfilter-nameencodingFilter/filter-namefilter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-classinit-paramparam-nameencoding/param-nameparam-valueUTF-8/param-value/init-paraminit-paramparam-nameforceEncoding/param-nameparam-valuetrue/param-value/init-param/filterfilter-mappingfilter-nameencodingFilter/filter-nameurl-pattern/*/url-pattern/filter-mappingservletservlet-namedispatcher/servlet-nameservlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-classinit-paramparam-namecontextConfigLocation/param-nameparam-valueclasspath:/spring/spring-mvc.xml/param-value/init-paramload-on-startup1/load-on-startup/servletservlet-mappingservlet-namedispatcher/servlet-nameurl-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[] --listenerlistener-classorg.springframework.web.context.ContextLoaderListener/listener-class/listener!-- end::listeners[] --servletservlet-namesessionServlet/servlet-nameservlet-classsample.SessionServlet/servlet-class/servletservlet-mappingservlet-namesessionServlet/servlet-nameurl-pattern/servlet/session/url-pattern/servlet-mappingwelcome-file-listwelcome-fileindex.jsp/welcome-file/welcome-file-list/web-app这边主要是一个 filterfilter-namespringSessionRepositoryFilter/filter-namefilter-classorg.springframework.web.filter.DelegatingFilterProxy/filter-class/filterfilter-mappingfilter-namespringSessionRepositoryFilter/filter-nameurl-pattern/*/url-pattern/filter-mappingsession-configsession-timeout30/session-timeout/session-config这个filter一定要写在一切filter之前SessionControllerpackage 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;}}
showSession.jsp文件% page languagejava contentTypetext/html; charsetutf-8pageEncodingutf-8%
!DOCTYPE html PUBLIC -//W3C//DTD HTML 4.01 Transitional//EN http://www.w3.org/TR/html4/loose.dtd
html
head
meta http-equivContent-Type contenttext/html; charsetutf-8
titleshowSession/title
/head
body
%String sessionValue(String)session.getAttribute(testSession);
%h1Session 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 *来查看存入的keyLOOKspring的session存入了redis中去了。再来看我们的eclipse后台由于我们是第一次访问这个controller因此这个session为空因此它显示如下我们在IE中再次访问该controller由于之前的session已经存在于redis了因此当用户在1800秒30分钟内再次访问controller它会从session中获取该session的key testSession的值因此eclipse后台打印为not null。SpringRedisTemplate Redis讲过了spring sessionredis我们来讲使用spring data框架提供的redisTemplate来访问redis service吧。说实话spring这个东西真强什么都可以集成cassandra, jms, jdbc...jpa...bla...bla...bla...Spring集成Barack Hussein Obama? LOL :)pom.xml不用列了上面有了redis-conf.xml不用列了上面有了web.xml也不用列了上面也有了SentinelController.java我们就先用这个名字吧后面我们会用它来做我们的redis sentinel哨兵的高可用HA集群测试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 {Autowiredprivate 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 {BoundHashOperationsString, 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;}}
打开IE输入http://localhost:8080/webpoc/setValueToRedis观察我们的后台然后使用redis client连入后进行查看看。。。这个值key1的就是我们通过spring的redisTemplate存入进去的值即使用下面这段代码进行存入的值 for (int i 0; i 1000; i) {mapValue.put(String.valueOf(i), String.valueOf(i));
}
try {BoundHashOperationsString, String, String boundHashOperations redisTemplate.boundHashOps(key);boundHashOperations.putAll(mapValue);如何你要存入一个简单的如keytest valuehello你可以这样使用你的redisTemplateredisTemplate.execute(new RedisCallbackObject() {Overridepublic Object doInRedis(RedisConnection connection)throws DataAccessException {connection.set(redisTemplate.getStringSerializer().serialize(test), redisTemplate.getStringSerializer().serialize(hello));return null;}
});是不是很方便的哈结束第一天的教程明天开始搭建redis集群。 转载于:https://www.cnblogs.com/aiwz/p/6154607.html