摘要: 在金融行业的应用王 和全, 架构师简介: EDA 与 SOA 的融合已经成为一种趋势和务实的选择,但如何拨云见日,了解其中本质的思想?这正是本文想和你一起探讨的。发布日期: 2010 年 10 月 28 日 级别: 初级 访问情况 : 5393 次浏览 评论: 1 (查看 | 添加评论&n...  阅读全文
posted @ 2014-12-30 10:41 小马歌 阅读(276) | 评论 (0)编辑 收藏
 

1. 讓 Command Line 指令列顯示目前處在哪一個 Git Branch 分支,最早是在 RGBA 看到這一招,非常方便。另外我最近看到一個點子是顯示從上一次 commit 之後過了多久時間,這可以提醒你是不是該 commit 了 XD

請修改家目錄的 ~/.bash_profile 檔案 (我是用 Bash)。

1234567891011121314151617
function git_branch {
ref=$(git symbolic-ref HEAD 2> /dev/null) || return;
echo "("${ref#refs/heads/}") ";
}
 
function git_since_last_commit {
now=`date +%s`;
last_commit=$(git log --pretty=format:%at -1 2> /dev/null) || return;
seconds_since_last_commit=$((now-last_commit));
minutes_since_last_commit=$((seconds_since_last_commit/60));
hours_since_last_commit=$((minutes_since_last_commit/60));
minutes_since_last_commit=$((minutes_since_last_commit%60));
echo "${hours_since_last_commit}h${minutes_since_last_commit}m ";
}
 
PS1="[\[\033[1;32m\]\w\[\033[0m\]] \[\033[0m\]\[\033[1;36m\]\$(git_branch)\[\033[0;33m\]\$(git_since_last_commit)\[\033[0m\]$ "
view rawgistfile1.txt hosted with ❤ by GitHub

結果如下,各位可以看到目前處在 master 分支,並且這個專案已經過了 1821 個小時沒有 commit 了…. :p

2. 安裝 Git 的 Bash autocompletion,這樣按 tab 就會有自動完成的效果,它甚至包括 git checkout 時都可以抓到你的 branch 名稱。這裡我用 Homebrew 來安裝 bash-completion,這套件其實包括很多 autocompletion script,你可以去 /usr/local/etc/bash_completion.d 這個目錄找找看。

brew install bash-completion cp /usr/local/etc/bash_completion.d/git-completion.bash ~/.git-bash-completion.sh 

編輯 ~/.bash_profile 加入

[ -f ~/.git-bash-completion.sh ] && . ~/.git-bash-completion.sh 

3. 打開 Git 的 color 顏色設定,這樣 Git 指令的輸出結果才會加上顏色,像是 git status 等:

git config --global color.ui true 

4. 設定你偏好的文字編輯器和 diff 工具

git config --global core.editor git config --global merge.tool opendiff 

5. 最後,我個人喜歡以下的 alias:

git config --global alias.co checkout git config --global alias.ci commit git config --global alias.st status git config --global alias.br branch 

這樣只要輸入 git st 就是 git status 了。

FYI,以上 git 設定檔的位置在 ~/.gitconfig,你也可以直接修改這個檔案。

posted @ 2014-12-24 15:07 小马歌 阅读(214) | 评论 (0)编辑 收藏
 
     摘要: 时间:2014-04-14 11:49来源:blog.51cto.com 作者:“游响云停” 博客 举报 点击:6031次1 关于版本控制版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。有以下三种版本控制系统:1. 本地版本控制系统许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别...  阅读全文
posted @ 2014-12-19 10:40 小马歌 阅读(245) | 评论 (0)编辑 收藏
 

2013-05-18 10:02:31     我来说两句       作者:沉睡一千年
收藏    我要投稿
git在windows上配置ssh公钥
 
一 .设置git的user name和email:
 
$ git config --global user.name "lxyz"
 
$ git config --global user.email "1129103472@qq.com"
 
二 生成密钥
 
ssh-keygen -t rsa -C “1129103472@qq.com”
 
 按3个回车,密码为空。(不要输密码)
 
然后到.ssh下面将id_rsa.pub里的内容复制出来粘贴到github个人中心的账户设置的ssh key里面
 
git for windows下载地址:
 
http://code.google.com/p/msysgit/downloads/list
posted @ 2014-12-19 10:39 小马歌 阅读(395) | 评论 (0)编辑 收藏
 
from:http://blog.csdn.net/cooldragon/article/details/40212761


现象是:

Windows下Eclipse可以连接Device里能显示设备名称,但是在Mac OS X下的Eclipse Device始终不能显示连接。


解决方法:
1.把Android手机开启调试模式,然后连接在我们的Mac OS上。
2.选择Mac的 关于本机->更多信息-> 系统报告->找到usb选项,右边会出现一系列和usb相关的设备我们找到自己的Android设备并选中。
3.选中后找到 供应商ID或叫厂商ID,我的MX4手机显示的供应商ID是:0x2a45


4.打开Mac终端 输入: echo 0x2a45 >> ~/.android/adb_usb.ini

然后重启adb(我是重启Mac系统)后再打开eclipse 你会发现Android手机的设备显示了。这样的办法还可以解决Mac上其他android设备不显示的问题。


感谢魅族的冤家对手小米论坛提供了解决方法,原文:点击打开链接



posted @ 2014-12-16 16:19 小马歌 阅读(1677) | 评论 (0)编辑 收藏
 
     摘要: spring 集成测试中 对mock 的集成实在是太棒了!但是使用请注意一下3个条件。 junit 必须使用4.9以上同时您的框架必须是用spring mvc spring 3.2以上才完美支持 目前使用spring MVC 取代struts2 的很多,spring MVC 的各种灵活让人无比销魂!所以使用spring MVC吧!以前在对接口(主要是java服务端提供...  阅读全文
posted @ 2014-12-08 18:26 小马歌 阅读(1153) | 评论 (0)编辑 收藏
 
Bug #70588 Index merge used on partitionned table can return wrong result set
Submitted: 10 Oct 2013 12:09 Modified: 5 Nov 2013 17:05
Reporter: Joffrey MICHAIE Email Updates:
Status: Closed Impact on me:
None 
Category: Server: Partition Severity: S2 (Serious)
Version: 5.6.14,5.5 OS: Any
Assigned to: Target Version:
Tags: index merge, intersect, partition, wrong resultset
Triage: Needs Triage: D2 (Serious)
ViewAdd CommentFilesDeveloperEdit SubmissionView Progress LogContributions
[10 Oct 2013 12:09] Joffrey MICHAIE
Description:
Simple query where 
indexed_col = 'x' and indexed_date_column = 'yyyy-mm-aa'
 returns wrong resultset, when run on partitionned table, and using index_merge (indexed_col,indexed_date_column)
Found on 5.5, repeated on 5.6.14, didn't test on 5.1
How to repeat:
Start MySQL with 100% default settings.
CREATE TABLE `poll` (
  `id_key` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `id` int(6) NOT NULL DEFAULT '0',
  `id_poll` int(6) NOT NULL DEFAULT '0',
  `date_long` datetime NOT NULL,
  `date_short` date NOT NULL,
  PRIMARY KEY (`id_key`,`id_poll`),
  KEY `id` (`id`),
  KEY `date_creation` (`date_short`)
) ENGINE=InnoDB AUTO_INCREMENT=14101389 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY HASH (id_poll)
PARTITIONS 20 */;
INSERT INTO `poll` VALUES (NULL,1718848,580660,'2013-10-09 18:21:00','2013-10-09');
INSERT INTO `poll` VALUES (NULL,39369,869049,'2013-10-09 18:21:02','2013-10-09');
INSERT INTO `poll` VALUES (NULL,70,1916580,'2013-10-09 18:21:09','2013-10-09');
INSERT INTO `poll` VALUES (NULL,70,1333222,'2013-10-09 18:20:31','2013-10-09');
INSERT INTO `poll` VALUES (NULL,1557405,869555,'2013-10-09 18:20:32','2013-10-09');
INSERT INTO `poll` VALUES (NULL,70,1343938,'2013-10-09 18:20:32','2013-10-09');
INSERT INTO `poll` VALUES (NULL,70,1157259,'2013-10-09 18:20:40','2013-10-09');
INSERT INTO `poll` VALUES (NULL,70,1800441,'2013-10-09 18:20:50','2013-10-09');
INSERT INTO `poll` VALUES (NULL,70,60,'2013-10-09 18:20:53','2013-10-09');
INSERT INTO `poll` VALUES (NULL,1718848,580660,'2013-10-09 18:21:00','2013-10-09');
INSERT INTO `poll` VALUES (NULL,39369,869049,'2013-10-09 18:21:02','2013-10-09');
INSERT INTO `poll` VALUES (NULL,70,1916580,'2013-10-09 18:21:09','2013-10-09');
INSERT INTO `poll` VALUES (NULL,70,1916580,'2013-10-0Query OK, 1 row affected (0,01 sec)
explain SELECT date_short FROM poll WHERE id =70 AND date_short =  '2013-10-10';                                                                                                                                                      +----+-------------+-------+-------------+------------------+------------------+---------+------+------+-------------------------------------------------------------+
| id | select_type | table | type        | possible_keys    | key              | key_len | ref  | rows | Extra                                                       |
+----+-------------+-------+-------------+------------------+------------------+---------+------+------+-------------------------------------------------------------+
|  1 | SIMPLE      | poll  | index_merge | id,date_creation | date_creation,id | 3,4     | NULL |    2 | Using intersect(date_creation,id); Using where; Using index |
+----+-------------+-------+-------------+------------------+------------------+---------+------+------+-------------------------------------------------------------+
1 row in set (0,00 sec)
(data sample is small, you can run ANALYZE TABLE if intersect is not shown)
mysql>  SELECT date_short FROM poll WHERE id =70 AND date_short =  '2013-10-10';
Empty set (0,01 sec)
mysql>  SELECT date_short FROM poll WHERE id =70 AND date_short like  '2013-10-10';
+------------+
| date_short |
+------------+
| 2013-10-10 |
+------------+
1 row in set (0,00 sec)
Other examples:
mysql>  SELECT date_short FROM poll IGNORE INDEX (date_creation) WHERE id =70 AND date_short =  '2013-10-10';
+------------+
| date_short |
+------------+
| 2013-10-10 |
+------------+
1 row in set (0,00 sec)
mysql>  SELECT date_short FROM poll IGNORE INDEX (id) WHERE id =70 AND date_short =  '2013-10-10';
+------------+
| date_short |
+------------+
| 2013-10-10 |
+------------+
1 row in set (0,00 sec)
mysql> alter table poll remove partitioning;
Query OK, 13 rows affected (0,08 sec)
Records: 13  Duplicates: 0  Warnings: 0
mysql>  SELECT date_short FROM poll WHERE id =70 AND date_short =  '2013-10-10';
+------------+
| date_short |
+------------+
| 2013-10-10 |
+------------+
1 row in set (0,00 sec)
Suggested fix:
Return correct resultset, or do not use intersection merge on hash partitionned tables
[10 Oct 2013 12:30] Miguel Solorzano
Thank you for the bug report.
C:\dbs>c:\dbs\5.6\bin\mysql -uroot --port=3560 --prompt="mysql 5.6 > "
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.6.15 Source distribution
Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql 5.6 > use xd
Database changed
mysql 5.6 > CREATE TABLE `poll` (
    ->   `id_key` int(10) unsigned NOT NULL AUTO_INCREMENT,
    ->   `id` int(6) NOT NULL DEFAULT '0',
    ->   `id_poll` int(6) NOT NULL DEFAULT '0',
    ->   `date_long` datetime NOT NULL,
    ->   `date_short` date NOT NULL,
    ->   PRIMARY KEY (`id_key`,`id_poll`),
    ->   KEY `id` (`id`),
    ->   KEY `date_creation` (`date_short`)
    -> ) ENGINE=InnoDB AUTO_INCREMENT=14101389 DEFAULT CHARSET=latin1
    -> /*!50100 PARTITION BY HASH (id_poll)
    -> PARTITIONS 20 */;
Query OK, 0 rows affected (4.76 sec)
mysql 5.6 >
mysql 5.6 > INSERT INTO `poll` VALUES (NULL,1718848,580660,'2013-10-09 18:21:00','2013-10-09');
Query OK, 1 row affected (0.20 sec)
<CUT>
mysql 5.6 > SELECT date_short FROM poll WHERE id =70 AND date_short =  '2013-10-10';
Empty set (0.00 sec)
mysql 5.6 > alter table poll remove partitioning;
Query OK, 13 rows affected (3.76 sec)
Records: 13  Duplicates: 0  Warnings: 0
mysql 5.6 > SELECT date_short FROM poll WHERE id =70 AND date_short =  '2013-10-10';
+------------+
| date_short |
+------------+
| 2013-10-10 |
+------------+
1 row in set (0.02 sec)
mysql 5.6 >
[10 Oct 2013 12:55] Joffrey MICHAIE
From:
http://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-14.html
For partitioned tables, queries could return different results depending on whether Index Merge was used. (Bug #16862316)
[5 Nov 2013 17:05] Jonathan Stephens
Fixed in 5.5+. Documented in the 5.5.36, 5.6.16, and 5.7.4 changelogs, as follows:
      Queries using index_merge optimization (see 
      http://dev.mysql.com/doc/refman/5.5/en/index-merge-optimization.html) 
      could return invalid results when run against tables that were 
      partitioned by HASH. 
Closed.
[2 Feb 17:20] Laurynas Biveinis
5.5$ bzr log -r 4538
------------------------------------------------------------
revno: 4538
committer: Aditya A <aditya.a@oracle.com>
branch nick: mysql-5.5
timestamp: Tue 2013-11-05 19:25:26 +0530
message:
  Bug#17588348: INDEX MERGE USED ON PARTITIONED TABLE 
                 CAN RETURN WRONG RESULT SET
  
  PROBLEM
  -------
  In ha_partition::cmp_ref() we were only calling the 
  underlying cmp_ref() of storage engine if the records
  are in the same partiton,else we sort by partition and
  returns the result.But the index merge intersect 
  algorithm expects first to sort by row-id first and 
  then by partition id.
  
  FIX
  ---
  Compare the refernces first using storage engine cmp_ref
  and then if references are equal(only happens if 
  non clustered index is used) then sort it by partition id.
  
  [Approved by Mattiasj #rb3755]
  -
posted @ 2014-12-08 17:33 小马歌 阅读(201) | 评论 (0)编辑 收藏
 

一、概述:

      在Redis中,我们可以将Set类型看作为没有排序的字符集合,和List类型一样,我们也可以在该类型的数据值上执行添加、删除或判断某一元素是否存在等操作。需要说明的是,这些操作的时间复杂度为O(1),即常量时间内完成次操作。Set可包含的最大元素数量是4294967295。
      和List类型不同的是,Set集合中不允许出现重复的元素,这一点和C++标准库中的set容器是完全相同的。换句话说,如果多次添加相同元素,Set中将仅保留该元素的一份拷贝。和List类型相比,Set类型在功能上还存在着一个非常重要的特性,即在服务器端完成多个Sets之间的聚合计算操作,如unions、intersections和differences。由于这些操作均在服务端完成,因此效率极高,而且也节省了大量的网络IO开销。

二、相关命令列表:

命令原型时间复杂度命令描述返回值
SADD key member [member ...]O(N)时间复杂度中的N表示操作的成员数量。如果在插入的过程用,参数中有的成员在Set中已经存在,该成员将被忽略,而其它成员仍将会被正常插入。如果执行该命令之前,该Key并不存在,该命令将会创建一个新的Set,此后再将参数中的成员陆续插入。如果该Key的Value不是Set类型,该命令将返回相关的错误信息。本次操作实际插入的成员数量。
SCARD keyO(1)获取Set中成员的数量。返回Set中成员的数量,如果该Key并不存在,返回0。
SISMEMBERkey memberO(1)判断参数中指定成员是否已经存在于与Key相关联的Set集合中。1表示已经存在,0表示不存在,或该Key本身并不存在。
SMEMBERS keyO(N)时间复杂度中的N表示Set中已经存在的成员数量。获取与该Key关联的Set中所有的成员。

返回Set中所有的成员。

SPOP key O(1) 随机的移除并返回Set中的某一成员。 由于Set中元素的布局不受外部控制,因此无法像List那样确定哪个元素位于Set的头部或者尾部。返回移除的成员,如果该Key并不存在,则返回nil。
SREM key member [member ...]O(N) 时间复杂度中的N表示被删除的成员数量。从与Key关联的Set中删除参数中指定的成员,不存在的参数成员将被忽略,如果该Key并不存在,将视为空Set处理。从Set中实际移除的成员数量,如果没有则返回0。
SRANDMEMBERkey O(1) 和SPOP一样,随机的返回Set中的一个成员,不同的是该命令并不会删除返回的成员。返回随机位置的成员,如果Key不存在则返回nil。
SMOVE source destination memberO(1) 原子性的将参数中的成员从source键移入到destination键所关联的Set中。因此在某一时刻,该成员或者出现在source中,或者出现在destination中。如果该成员在source中并不存在,该命令将不会再执行任何操作并返回0,否则,该成员将从source移入到destination。如果此时该成员已经在destination中存在,那么该命令仅是将该成员从source中移出。如果和Key关联的Value不是Set,将返回相关的错误信息。1表示正常移动,0表示source中并不包含参数成员。
SDIFF key [key ...]O(N) 时间复杂度中的N表示所有Sets中成员的总数量。返回参数中第一个Key所关联的Set和其后所有Keys所关联的Sets中成员的差异。如果Key不存在,则视为空Set。差异结果成员的集合。
SDIFFSTOREdestination key [key ...] O(N) 该命令和SDIFF命令在功能上完全相同,两者之间唯一的差别是SDIFF返回差异的结果成员,而该命令将差异成员存储在destination关联的Set中。如果destination键已经存在,该操作将覆盖它的成员。返回差异成员的数量。
SINTER key [key ...] O(N*M) 时间复杂度中的N表示最小Set中元素的数量,M则表示参数中Sets的数量。该命令将返回参数中所有Keys关联的Sets中成员的交集。因此如果参数中任何一个Key关联的Set为空,或某一Key不存在,那么该命令的结果将为空集。交集结果成员的集合。
SINTERSTOREdestination key [key ...]O(N*M) 该命令和SINTER命令在功能上完全相同,两者之间唯一的差别是SINTER返回交集的结果成员,而该命令将交集成员存储在destination关联的Set中。如果destination键已经存在,该操作将覆盖它的成员。返回交集成员的数量。 
SUNION key [key ...] O(N)时间复杂度中的N表示所有Sets中成员的总数量。该命令将返回参数中所有Keys关联的Sets中成员的并集。并集结果成员的集合。
SUNIONSTOREdestination key [key ...] O(N) 该命令和SUNION命令在功能上完全相同,两者之间唯一的差别是SUNION返回并集的结果成员,而该命令将并集成员存储在destination关联的Set中。如果destination键已经存在,该操作将覆盖它的成员。 返回并集成员的数量。

三、命令示例:

   1. SADD/SMEMBERS/SCARD/SISMEMBER:
    #在Shell命令行下启动Redis的客户端程序。
    /> redis-cli
    #插入测试数据,由于该键myset之前并不存在,因此参数中的三个成员都被正常插入。
    redis 127.0.0.1:6379> sadd myset a b c
    (integer) 3
    #由于参数中的a在myset中已经存在,因此本次操作仅仅插入了d和e两个新成员。
    redis 127.0.0.1:6379> sadd myset a d e
    (integer) 2
    #判断a是否已经存在,返回值为1表示存在。
    redis 127.0.0.1:6379> sismember myset a
    (integer) 1
    #判断f是否已经存在,返回值为0表示不存在。
    redis 127.0.0.1:6379> sismember myset f
    (integer) 0
    #通过smembers命令查看插入的结果,从结果可以,输出的顺序和插入顺序无关。
    redis 127.0.0.1:6379> smembers myset
    1) "c"
    2) "d"
    3) "a"
    4) "b"
    5) "e"
    #获取Set集合中元素的数量。
    redis 127.0.0.1:6379> scard myset
    (integer) 5

    2. SPOP/SREM/SRANDMEMBER/SMOVE:
    #删除该键,便于后面的测试。
    redis 127.0.0.1:6379> del myset
    (integer) 1
    #为后面的示例准备测试数据。
    redis 127.0.0.1:6379> sadd myset a b c d
    (integer) 4
    #查看Set中成员的位置。
    redis 127.0.0.1:6379> smembers myset
    1) "c"
    2) "d"
    3) "a"
    4) "b"
    #从结果可以看出,该命令确实是随机的返回了某一成员。
    redis 127.0.0.1:6379> srandmember myset
    "c"
    #Set中尾部的成员b被移出并返回,事实上b并不是之前插入的第一个或最后一个成员。
    redis 127.0.0.1:6379> spop myset
    "b"
    #查看移出后Set的成员信息。
    redis 127.0.0.1:6379> smembers myset
    1) "c"
    2) "d"
    3) "a"
    #从Set中移出a、d和f三个成员,其中f并不存在,因此只有a和d两个成员被移出,返回为2。
    redis 127.0.0.1:6379> srem myset a d f
    (integer) 2
    #查看移出后的输出结果。
    redis 127.0.0.1:6379> smembers myset
    1) "c"
    #为后面的smove命令准备数据。
    redis 127.0.0.1:6379> sadd myset a b
    (integer) 2
    redis 127.0.0.1:6379> sadd myset2 c d
    (integer) 2
    #将a从myset移到myset2,从结果可以看出移动成功。
    redis 127.0.0.1:6379> smove myset myset2 a
    (integer) 1
    #再次将a从myset移到myset2,由于此时a已经不是myset的成员了,因此移动失败并返回0。
    redis 127.0.0.1:6379> smove myset myset2 a
    (integer) 0
    #分别查看myset和myset2的成员,确认移动是否真的成功。
    redis 127.0.0.1:6379> smembers myset
    1) "b"
    redis 127.0.0.1:6379> smembers myset2
    1) "c"
    2) "d"
    3) "a"

   3. SDIFF/SDIFFSTORE/SINTER/SINTERSTORE:
    #为后面的命令准备测试数据。
    redis 127.0.0.1:6379> sadd myset a b c d
    (integer) 4
    redis 127.0.0.1:6379> sadd myset2 c
    (integer) 1
    redis 127.0.0.1:6379> sadd myset3 a c e
    (integer) 3
    #myset和myset2相比,a、b和d三个成员是两者之间的差异成员。再用这个结果继续和myset3进行差异比较,b和d是myset3不存在的成员。
    redis 127.0.0.1:6379> sdiff myset myset2 myset3
    1) "d"
    2) "b"
    #将3个集合的差异成员存在在diffkey关联的Set中,并返回插入的成员数量。
    redis 127.0.0.1:6379> sdiffstore diffkey myset myset2 myset3
    (integer) 2
    #查看一下sdiffstore的操作结果。
    redis 127.0.0.1:6379> smembers diffkey
    1) "d"
    2) "b"
    #从之前准备的数据就可以看出,这三个Set的成员交集只有c。
    redis 127.0.0.1:6379> sinter myset myset2 myset3
    1) "c"
    #将3个集合中的交集成员存储到与interkey关联的Set中,并返回交集成员的数量。
    redis 127.0.0.1:6379> sinterstore interkey myset myset2 myset3
    (integer) 1
    #查看一下sinterstore的操作结果。
    redis 127.0.0.1:6379> smembers interkey
    1) "c"
    #获取3个集合中的成员的并集。    
    redis 127.0.0.1:6379> sunion myset myset2 myset3
    1) "b"
    2) "c"
    3) "d"
    4) "e"
    5) "a"
    #将3个集合中成员的并集存储到unionkey关联的set中,并返回并集成员的数量。
    redis 127.0.0.1:6379> sunionstore unionkey myset myset2 myset3
    (integer) 5
    #查看一下suiionstore的操作结果。
    redis 127.0.0.1:6379> smembers unionkey
    1) "b"
    2) "c"
    3) "d"
    4) "e"
    5) "a"

四、应用范围:

      1). 可以使用Redis的Set数据类型跟踪一些唯一性数据,比如访问某一博客的唯一IP地址信息。对于此场景,我们仅需在每次访问该博客时将访问者的IP存入Redis中,Set数据类型会自动保证IP地址的唯一性。
      2). 充分利用Set类型的服务端聚合操作方便、高效的特性,可以用于维护数据对象之间的关联关系。比如所有购买某一电子设备的客户ID被存储在一个指定的Set中,而购买另外一种电子产品的客户ID被存储在另外一个Set中,如果此时我们想获取有哪些客户同时购买了这两种商品时,Set的intersections命令就可以充分发挥它的方便和效率的优势了。

分类: Redis
posted @ 2014-12-01 19:45 小马歌 阅读(219) | 评论 (0)编辑 收藏
 

一、概述:

      我们可以将Redis中的Hashes类型看成具有String Key和String Value的map容器。所以该类型非常适合于存储值对象的信息。如Username、Password和Age等。如果Hash中包含很少的字段,那么该类型的数据也将仅占用很少的磁盘空间。每一个Hash可以存储4294967295个键值对。

二、相关命令列表:

命令原型时间复杂度命令描述返回值
HSET key field valueO(1)为指定的Key设定Field/Value对,如果Key不存在,该命令将创建新Key以参数中的Field/Value对,如果参数中的Field在该Key中已经存在,则用新值覆盖其原有值。 1表示新的Field被设置了新值,0表示Field已经存在,用新值覆盖原有值。 
HGET key field O(1) 返回指定Key中指定Field的关联值。返回参数中Field的关联值,如果参数中的Key或Field不存,返回nil。
HEXISTSkey field O(1) 判断指定Key中的指定Field是否存在。1表示存在,0表示参数中的Field或Key不存在。
HLEN key O(1)获取该Key所包含的Field的数量。返回Key包含的Field数量,如果Key不存在,返回0。
HDEL key field [field ...] O(N)时间复杂度中的N表示参数中待删除的字段数量。从指定Key的Hashes Value中删除参数中指定的多个字段,如果不存在的字段将被忽略。如果Key不存在,则将其视为空Hashes,并返回0.实际删除的Field数量。
HSETNXkey field valueO(1)只有当参数中的Key或Field不存在的情况下,为指定的Key设定Field/Value对,否则该命令不会进行任何操作。 1表示新的Field被设置了新值,0表示Key或Field已经存在,该命令没有进行任何操作。
HINCRBYkey field increment O(1)增加指定Key中指定Field关联的Value的值。如果Key或Field不存在,该命令将会创建一个新Key或新Field,并将其关联的Value初始化为0,之后再指定数字增加的操作。该命令支持的数字是64位有符号整型,即increment可以负数。 返回运算后的值。
HGETALLkeyO(N) 时间复杂度中的N表示Key包含的Field数量。获取该键包含的所有Field/Value。其返回格式为一个Field、一个Value,并以此类推。Field/Value的列表。
HKEYSkey O(N)时间复杂度中的N表示Key包含的Field数量。返回指定Key的所有Fields名。Field的列表。
HVALSkey O(N)时间复杂度中的N表示Key包含的Field数量。返回指定Key的所有Values名。 Value的列表。 
HMGETkey field [field ...] O(N) 时间复杂度中的N表示请求的Field数量。获取和参数中指定Fields关联的一组Values。如果请求的Field不存在,其值返回nil。如果Key不存在,该命令将其视为空Hash,因此返回一组nil。返回和请求Fields关联的一组Values,其返回顺序等同于Fields的请求顺序。
HMSET key field value [field value ...]O(N)时间复杂度中的N表示被设置的Field数量。逐对依次设置参数中给出的Field/Value对。如果其中某个Field已经存在,则用新值覆盖原有值。如果Key不存在,则创建新Key,同时设定参数中的Field/Value。   

三、命令示例:

    1. HSET/HGET/HDEL/HEXISTS/HLEN/HSETNX:
    #在Shell命令行启动Redis客户端程序
    /> redis-cli
    #给键值为myhash的键设置字段为field1,值为stephen。
    redis 127.0.0.1:6379> hset myhash field1 "stephen"
    (integer) 1
    #获取键值为myhash,字段为field1的值。
    redis 127.0.0.1:6379> hget myhash field1
    "stephen"
    #myhash键中不存在field2字段,因此返回nil。
    redis 127.0.0.1:6379> hget myhash field2
    (nil)
    #给myhash关联的Hashes值添加一个新的字段field2,其值为liu。
    redis 127.0.0.1:6379> hset myhash field2 "liu"
    (integer) 1
    #获取myhash键的字段数量。
    redis 127.0.0.1:6379> hlen myhash
    (integer) 2
    #判断myhash键中是否存在字段名为field1的字段,由于存在,返回值为1。
    redis 127.0.0.1:6379> hexists myhash field1
    (integer) 1
    #删除myhash键中字段名为field1的字段,删除成功返回1。
    redis 127.0.0.1:6379> hdel myhash field1
    (integer) 1
    #再次删除myhash键中字段名为field1的字段,由于上一条命令已经将其删除,因为没有删除,返回0。
    redis 127.0.0.1:6379> hdel myhash field1
    (integer) 0
    #判断myhash键中是否存在field1字段,由于上一条命令已经将其删除,因为返回0。
    redis 127.0.0.1:6379> hexists myhash field1
    (integer) 0
    #通过hsetnx命令给myhash添加新字段field1,其值为stephen,因为该字段已经被删除,所以该命令添加成功并返回1。
    redis 127.0.0.1:6379> hsetnx myhash field1 stephen
    (integer) 1
    #由于myhash的field1字段已经通过上一条命令添加成功,因为本条命令不做任何操作后返回0。
    redis 127.0.0.1:6379> hsetnx myhash field1 stephen
    (integer) 0

   2. HINCRBY:
    #删除该键,便于后面示例的测试。
    redis 127.0.0.1:6379> del myhash
    (integer) 1
    #准备测试数据,该myhash的field字段设定值1。
    redis 127.0.0.1:6379> hset myhash field 5
    (integer) 1
    #给myhash的field字段的值加1,返回加后的结果。
    redis 127.0.0.1:6379> hincrby myhash field 1
    (integer) 6
    #给myhash的field字段的值加-1,返回加后的结果。
    redis 127.0.0.1:6379> hincrby myhash field -1
    (integer) 5
    #给myhash的field字段的值加-10,返回加后的结果。
    redis 127.0.0.1:6379> hincrby myhash field -10
    (integer) -5   

    3. HGETALL/HKEYS/HVALS/HMGET/HMSET:
    #删除该键,便于后面示例测试。
    redis 127.0.0.1:6379> del myhash
    (integer) 1
    #为该键myhash,一次性设置多个字段,分别是field1 = "hello", field2 = "world"。
    redis 127.0.0.1:6379> hmset myhash field1 "hello" field2 "world"
    OK
    #获取myhash键的多个字段,其中field3并不存在,因为在返回结果中与该字段对应的值为nil。
    redis 127.0.0.1:6379> hmget myhash field1 field2 field3
    1) "hello"
    2) "world"
    3) (nil)
    #返回myhash键的所有字段及其值,从结果中可以看出,他们是逐对列出的。
    redis 127.0.0.1:6379> hgetall myhash
    1) "field1"
    2) "hello"
    3) "field2"
    4) "world"
    #仅获取myhash键中所有字段的名字。
    redis 127.0.0.1:6379> hkeys myhash
    1) "field1"
    2) "field2"
    #仅获取myhash键中所有字段的值。
    redis 127.0.0.1:6379> hvals myhash
    1) "hello"
    2) "world" 

分类: Redis
posted @ 2014-12-01 19:44 小马歌 阅读(208) | 评论 (0)编辑 收藏
 

一、概述:

      在Redis中,List类型是按照插入顺序排序的字符串链表。和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的元素。在插入时,如果该键并不存在,Redis将为该键创建一个新的链表。与此相反,如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除。List中可以包含的最大元素数量是4294967295。
      从元素插入和删除的效率视角来看,如果我们是在链表的两头插入或删除元素,这将会是非常高效的操作,即使链表中已经存储了百万条记录,该操作也可以在常量时间内完成。然而需要说明的是,如果元素插入或删除操作是作用于链表中间,那将会是非常低效的。相信对于有良好数据结构基础的开发者而言,这一点并不难理解。

二、相关命令列表:

命令原型时间复杂度命令描述返回值
LPUSH key value [value ...] O(1)在指定Key所关联的List Value的头部插入参数中给出的所有Values。如果该Key不存在,该命令将在插入之前创建一个与该Key关联的空链表,之后再将数据从链表的头部插入。如果该键的Value不是链表类型,该命令将返回相关的错误信息。 插入后链表中元素的数量。
LPUSHX key value O(1)  仅有当参数中指定的Key存在时,该命令才会在其所关联的List Value的头部插入参数中给出的Value,否则将不会有任何操作发生。插入后链表中元素的数量。 
LRANGE key start stop O(S+N)时间复杂度中的S为start参数表示的偏移量,N表示元素的数量。该命令的参数start和end都是0-based。即0表示链表头部(leftmost)的第一个元素。其中start的值也可以为负值,-1将表示链表中的最后一个元素,即尾部元素,-2表示倒数第二个并以此类推。该命令在获取元素时,start和end位置上的元素也会被取出。如果start的值大于链表中元素的数量,空链表将会被返回。如果end的值大于元素的数量,该命令则获取从start(包括start)开始,链表中剩余的所有元素。返回指定范围内元素的列表。
LPOP key O(1) 返回并弹出指定Key关联的链表中的第一个元素,即头部元素,。如果该Key不存,返回nil。链表头部的元素。
LLEN keyO(1) 返回指定Key关联的链表中元素的数量,如果该Key不存在,则返回0。如果与该Key关联的Value的类型不是链表,则返回相关的错误信息。链表中元素的数量。
LREM key count value O(N) 时间复杂度中N表示链表中元素的数量。在指定Key关联的链表中,删除前count个值等于value的元素。如果count大于0,从头向尾遍历并删除,如果count小于0,则从尾向头遍历并删除。如果count等于0,则删除链表中所有等于value的元素。如果指定的Key不存在,则直接返回0。返回被删除的元素数量。
LSET key index value O(N) 时间复杂度中N表示链表中元素的数量。但是设定头部或尾部的元素时,其时间复杂度为O(1)。设定链表中指定位置的值为新值,其中0表示第一个元素,即头部元素,-1表示尾部元素。如果索引值Index超出了链表中元素的数量范围,该命令将返回相关的错误信息。 
LINDEX key index O(N) 时间复杂度中N表示在找到该元素时需要遍历的元素数量。对于头部或尾部元素,其时间复杂度为O(1)。该命令将返回链表中指定位置(index)的元素,index是0-based,表示头部元素,如果index为-1,表示尾部元素。如果与该Key关联的不是链表,该命令将返回相关的错误信息。返回请求的元素,如果index超出范围,则返回nil。
LTRIM key start stop O(N) N表示被删除的元素数量。该命令将仅保留指定范围内的元素,从而保证链接中的元素数量相对恒定。start和stop参数都是0-based,0表示头部元素。和其他命令一样,start和stop也可以为负值,-1表示尾部元素。如果start大于链表的尾部,或start大于stop,该命令不错报错,而是返回一个空的链表,与此同时该Key也将被删除。如果stop大于元素的数量,则保留从start开始剩余的所有元素。 
LINSERT key BEFORE|AFTER pivot value O(N) 时间复杂度中N表示在找到该元素pivot之前需要遍历的元素数量。这样意味着如果pivot位于链表的头部或尾部时,该命令的时间复杂度为O(1)。该命令的功能是在pivot元素的前面或后面插入参数中的元素value。如果Key不存在,该命令将不执行任何操作。如果与Key关联的Value类型不是链表,相关的错误信息将被返回。成功插入后链表中元素的数量,如果没有找到pivot,返回-1,如果key不存在,返回0。
RPUSH key value [value ...] O(1) 在指定Key所关联的List Value的尾部插入参数中给出的所有Values。如果该Key不存在,该命令将在插入之前创建一个与该Key关联的空链表,之后再将数据从链表的尾部插入。如果该键的Value不是链表类型,该命令将返回相关的错误信息。 插入后链表中元素的数量。 
RPUSHX key value O(1) 仅有当参数中指定的Key存在时,该命令才会在其所关联的List Value的尾部插入参数中给出的Value,否则将不会有任何操作发生。 插入后链表中元素的数量。 
RPOP key O(1) 返回并弹出指定Key关联的链表中的最后一个元素,即尾部元素,。如果该Key不存,返回nil。 链表尾部的元素。 
RPOPLPUSHsource destination O(1) 原子性的从与source键关联的链表尾部弹出一个元素,同时再将弹出的元素插入到与destination键关联的链表的头部。如果source键不存在,该命令将返回nil,同时不再做任何其它的操作了。如果source和destination是同一个键,则相当于原子性的将其关联链表中的尾部元素移到该链表的头部。返回弹出和插入的元素。

三、命令示例:

    1. LPUSH/LPUSHX/LRANGE:
    /> redis-cli    #在Shell提示符下启动redis客户端工具。
    redis 127.0.0.1:6379> del mykey
    (integer) 1
    #mykey键并不存在,该命令会创建该键及与其关联的List,之后在将参数中的values从左到右依次插入。
    redis 127.0.0.1:6379> lpush mykey a b c d
    (integer) 4
    #取从位置0开始到位置2结束的3个元素。
    redis 127.0.0.1:6379> lrange mykey 0 2
    1) "d"
    2) "c"
    3) "b"
    #取链表中的全部元素,其中0表示第一个元素,-1表示最后一个元素。
    redis 127.0.0.1:6379> lrange mykey 0 -1
    1) "d"
    2) "c"
    3) "b"
    4) "a"
    #mykey2键此时并不存在,因此该命令将不会进行任何操作,其返回值为0。
    redis 127.0.0.1:6379> lpushx mykey2 e
    (integer) 0
    #可以看到mykey2没有关联任何List Value。
    redis 127.0.0.1:6379> lrange mykey2 0 -1
    (empty list or set)
    #mykey键此时已经存在,所以该命令插入成功,并返回链表中当前元素的数量。
    redis 127.0.0.1:6379> lpushx mykey e
    (integer) 5
    #获取该键的List Value的头部元素。
    redis 127.0.0.1:6379> lrange mykey 0 0
    1) "e"

    2. LPOP/LLEN:
    redis 127.0.0.1:6379> lpush mykey a b c d
    (integer) 4
    redis 127.0.0.1:6379> lpop mykey
    "d"
    redis 127.0.0.1:6379> lpop mykey
    "c"
    #在执行lpop命令两次后,链表头部的两个元素已经被弹出,此时链表中元素的数量是2
    redis 127.0.0.1:6379> llen mykey
    (integer) 2

   3. LREM/LSET/LINDEX/LTRIM:
    #为后面的示例准备测试数据。
    redis 127.0.0.1:6379> lpush mykey a b c d a c
    (integer) 6
    #从头部(left)向尾部(right)变量链表,删除2个值等于a的元素,返回值为实际删除的数量。
    redis 127.0.0.1:6379> lrem mykey 2 a
    (integer) 2
    #看出删除后链表中的全部元素。
    redis 127.0.0.1:6379> lrange mykey 0 -1
    1) "c"
    2) "d"
    3) "c"
    4) "b"
    #获取索引值为1(头部的第二个元素)的元素值。
    redis 127.0.0.1:6379> lindex mykey 1
    "d"
    #将索引值为1(头部的第二个元素)的元素值设置为新值e。
    redis 127.0.0.1:6379> lset mykey 1 e
    OK
    #查看是否设置成功。
    redis 127.0.0.1:6379> lindex mykey 1
    "e"
    #索引值6超过了链表中元素的数量,该命令返回nil。
    redis 127.0.0.1:6379> lindex mykey 6
    (nil)
    #设置的索引值6超过了链表中元素的数量,设置失败,该命令返回错误信息。
    redis 127.0.0.1:6379> lset mykey 6 hh
    (error) ERR index out of range
    #仅保留索引值0到2之间的3个元素,注意第0个和第2个元素均被保留。
    redis 127.0.0.1:6379> ltrim mykey 0 2
    OK
    #查看trim后的结果。
    redis 127.0.0.1:6379> lrange mykey 0 -1
    1) "c"
    2) "e"
    3) "c"

    4. LINSERT:
    #删除该键便于后面的测试。
    redis 127.0.0.1:6379> del mykey
    (integer) 1
    #为后面的示例准备测试数据。
    redis 127.0.0.1:6379> lpush mykey a b c d e
    (integer) 5
    #在a的前面插入新元素a1。
    redis 127.0.0.1:6379> linsert mykey before a a1
    (integer) 6
    #查看是否插入成功,从结果看已经插入。注意lindex的index值是0-based。
    redis 127.0.0.1:6379> lindex mykey 0
    "e"
    #在e的后面插入新元素e2,从返回结果看已经插入成功。
    redis 127.0.0.1:6379> linsert mykey after e e2
    (integer) 7
    #再次查看是否插入成功。
    redis 127.0.0.1:6379> lindex mykey 1
    "e2"
    #在不存在的元素之前或之后插入新元素,该命令操作失败,并返回-1。
    redis 127.0.0.1:6379> linsert mykey after k a
    (integer) -1
    #为不存在的Key插入新元素,该命令操作失败,返回0。
    redis 127.0.0.1:6379> linsert mykey1 after a a2
    (integer) 0

    5. RPUSH/RPUSHX/RPOP/RPOPLPUSH:
    #删除该键,以便于后面的测试。
    redis 127.0.0.1:6379> del mykey
    (integer) 1
    #从链表的尾部插入参数中给出的values,插入顺序是从左到右依次插入。
    redis 127.0.0.1:6379> rpush mykey a b c d
    (integer) 4
    #通过lrange的可以获悉rpush在插入多值时的插入顺序。
    redis 127.0.0.1:6379> lrange mykey 0 -1
    1) "a"
    2) "b"
    3) "c"
    4) "d"
    #该键已经存在并且包含4个元素,rpushx命令将执行成功,并将元素e插入到链表的尾部。
    redis 127.0.0.1:6379> rpushx mykey e
    (integer) 5
    #通过lindex命令可以看出之前的rpushx命令确实执行成功,因为索引值为4的元素已经是新元素了。
    redis 127.0.0.1:6379> lindex mykey 4
    "e"
    #由于mykey2键并不存在,因此该命令不会插入数据,其返回值为0。
    redis 127.0.0.1:6379> rpushx mykey2 e
    (integer) 0
    #在执行rpoplpush命令前,先看一下mykey中链表的元素有哪些,注意他们的位置关系。
    redis 127.0.0.1:6379> lrange mykey 0 -1
    1) "a"
    2) "b"
    3) "c"
    4) "d"
    5) "e"
    #将mykey的尾部元素e弹出,同时再插入到mykey2的头部(原子性的完成这两步操作)。
    redis 127.0.0.1:6379> rpoplpush mykey mykey2
    "e"
    #通过lrange命令查看mykey在弹出尾部元素后的结果。
    redis 127.0.0.1:6379> lrange mykey 0 -1
    1) "a"
    2) "b"
    3) "c"
    4) "d"
    #通过lrange命令查看mykey2在插入元素后的结果。
    redis 127.0.0.1:6379> lrange mykey2 0 -1
    1) "e"
    #将source和destination设为同一键,将mykey中的尾部元素移到其头部。
    redis 127.0.0.1:6379> rpoplpush mykey mykey
    "d"
    #查看移动结果。
    redis 127.0.0.1:6379> lrange mykey 0 -1
    1) "d"
    2) "a"
    3) "b"
    4) "c"

四、链表结构的小技巧:

      针对链表结构的Value,Redis在其官方文档中给出了一些实用技巧,如RPOPLPUSH命令,下面给出具体的解释。
      Redis链表经常会被用于消息队列的服务,以完成多程序之间的消息交换。假设一个应用程序正在执行LPUSH操作向链表中添加新的元素,我们通常将这样的程序称之为"生产者(Producer)",而另外一个应用程序正在执行RPOP操作从链表中取出元素,我们称这样的程序为"消费者(Consumer)"。如果此时,消费者程序在取出消息元素后立刻崩溃,由于该消息已经被取出且没有被正常处理,那么我们就可以认为该消息已经丢失,由此可能会导致业务数据丢失,或业务状态的不一致等现象的发生。然而通过使用RPOPLPUSH命令,消费者程序在从主消息队列中取出消息之后再将其插入到备份队列中,直到消费者程序完成正常的处理逻辑后再将该消息从备份队列中删除。同时我们还可以提供一个守护进程,当发现备份队列中的消息过期时,可以重新将其再放回到主消息队列中,以便其它的消费者程序继续处理。

分类: Redis
posted @ 2014-12-01 19:43 小马歌 阅读(239) | 评论 (0)编辑 收藏
仅列出标题
共95页: First 上一页 14 15 16 17 18 19 20 21 22 下一页 Last