Monday, 20 October 2014

HBase vs Cassandra

Apache HBase vs Apache Cassandra

This comparative study was done by me and Larry Thomas in May, 2012. Cassandra stuff was prepared by Larry Thomas.
This information is NOT intended to be a tutorial for either Apache Cassandra orApache HBase. We tried our level best to provide the most accurate information. Please comment or email me if you find any corrections. I would be happy to maintain this list with the most accurate and updated information.


Point
HBase
Cassandra

Foundations

HBase is based on BigTable (Google)
Cassandra is based on DynamoDB (Amazon).   Initially developed at Facebook by former Amazon engineers.  This is one reason why Cassandra supports multi data center.  Rackspace is a big contributor to Cassandra due to multi data center support.
Infrastructure
HBase uses the Hadoop Infrastructure (Zookeeper, NameNode, HDFS).  Organizations that will deploy Hadoop anyway may be comfortable with leveraging Hadoop knowledge by using HBase
Cassandra started and evolved separate from Hadoop and its infrastructure and Operational knowledge requirements are different than Hadoop.  However, for analytics, many Cassandra deployments use Cassandra + Storm (which uses Zookeeper), and/or Cassandra + Hadoop.
Infrastructure Simplicity and SPOF
The HBase-Hadoop Infrastructure has several "moving parts" consisting of Zookeeper,  Name Node,  Hbase Master, and Data Nodes,   Zookeeper is clustered and naturally fault tolerant.  Name Node needs to be clustered to be fault tolerant.
Cassandra uses a a single Node-type.  All nodes are equal and perform all functions.   Any Node can act as a coordinator, ensuring no SPOF.   Adding Storm or Hadoop, of course, adds complexity to the infrastructure.
Read Intensive Use Cases
HBase is optimized for reads, supported by single-write master, and resulting strict consistency model, as well as use of Ordered Partitioning which supports row-scans.  HBase is well suited for doing Range based scans.
Cassandra has excellent single-row read performance as long as eventual consistency semantics are sufficient for the use-case.  Cassandra quorum reads, which are required for strict consistency will naturally be slower than Hbase reads.  Cassandra does not support Range based row-scans which may be limiting in certain use-cases.  Cassandra is well suited for supporting single-row queries,  or selecting multiple rows based on a  Column-Value index.
Multi-Data Center Support and Disaster Recovery
HBase provides for asynchronous replication of an HBase Cluster across a WAN.   HBase clusters cannot be set up to achieve zero RPO, but in steady-state HBase should be roughly failover-equivalent  to any other DBMS that relies on asynchronous replication over a WAN.   Fall-back processes and procedures (e.g. after failover) are TBD.
Cassandra Random Partitioning provides for row-replication of a single row across a WAN, either asynchronous (write.ONE,  write.LOCAL_QUORUM),  or synchronous (write.QUORUM,  write.ALL).  Cassandra clusters can therefore be set up to achieve zero RPO, but each write will require at least one wan-ACK back to the coordinator to achieve this capability.
Write.ONE Durability
Writes are replicated in a pipeline fashion: the first-data-node for the region persists the write, and then sends the write to the next Natural Endpoint, and so-on in a pipeline fashion. HBase’s commit log "acks" a write only after *all* of the nodes in the pipeline have written the data to their OS buffers.  The first Region Server in the pipeline must also have persisted the write to its WAL.
Cassandra's coordinators will send parallel write-requests to all Natural Endpoints, The coordinator will "ack" the write after exactly one Natural Endpoint has "acked" the write, which means that node has also persisted the write to its WAL.   The writes may or may not have committed to any other Natural Endpoint.
Ordered Partitioning
HBase only supports Ordered Partitoning.  This means that Rows for a CF are stored in RowKey order in HFiles, where each Hfile contains a "block" or "shard" of all the rows in a CF.  HFiles are distributed across all data-nodes in the Cluster
Cassandra officially supports Ordered Partitioning, but no production user of Cassandra uses Ordered Partitioning due to the "hot spots" it creates and the operational difficulties such hot-spots cause.  Random Partitioning is the only recommended Cassandra partitioning scheme, and rows are distributed across all nodes in the cluster.



RowKey Range Scans
Because of ordered partitioning,  HBase queries can be formulated with partial start and end row-keys, and can locate rows inclusive-of, or exclusive of these partial-rowkeys.  The start and end row-keys in a range-scan need not even exist in Hbase.
Because of random partitioning,  partial rowkeys cannot be used with Cassandra.  RowKeys must be known exactly.  Counting rows in a CF is complicated.   It is highly recommended that for these types of use-cases,  data should be stored in columns in Cassandra, not in rows.
Linear Scalability for large tables and range scans
Due to Ordered Partitioning, HBase will easily scale horizontally while still supporting rowkey range scans.
If data is stored in columns in Cassandra to support range scans, the practical limitation of a row size in Cassandra is 10's of Megabytes.  Rows larger than that causes problems with compaction overhead and time.
Atomic Compare and Set
HBase supports Atomic Compare and Set. HBase supports supports transaction within a Row.
Cassandra does not support Atomic Compare and Set.   Counters require dedicated counter column-families which because of eventual-consistency requires that all replicas in all natural end-points be read and updated with ACK.  However, hinted-handoff mechanisms can make even these built-in counters suspect for accuracy.   FIFO queues are difficult (if not impossible) to implement with Cassandra.
Read Load Balancing - single Row
Hbase does not support Read Load Balancing against a single row.  A single row is served by exactly one region server at a time.  Other replicas are used ony in case of a node failure.  Scalability is primarily supported by Partitioning which statistically distributes reads of different rows across multiple data nodes.
Cassandra will support Read Load Balancing against a single row.  However,  this is primarily supported by Read.ONE, and eventual consistency must be taken into consideration.  Scalability is primarily supported by Partitioning which distributes reads of different rows across multiple data nodes. 
Bloom Filters
Bloom Filters can be used in HBase as another form of Indexing.  They work on the basis of RowKey or RowKey+ColumnName to reduce the number of data-blocks that HBase has to read to satisfy a query.  (Bloom Filters may exhibit false-positives (reading too much data), but never false negatives (reading not enough data).
Cassandra uses bloom filters for key lookup.
Triggers
Triggers are supported by the CoProcessor capability in HBase.  They allow HBase to observe the get/put/delete events on a table (CF), and then execute the trigger-logic.    Triggers are coded as java classes.
Cassandra does not support co-processor-like functionality (as far as we know)
Secondary Indexes
Hbase does not natively support secondary indexes, but one use-case of Triggers is that a trigger on a "put" can automatically keep a secondary index up-to-date, and therefore not put the burden on the application (client).
Cassandra supports secondary indexes on column families where the column name is known.  (Not on dynamic columns).
Simple Aggregation
Hbase CoProcessors support out-of-the-box simple aggregations in HBase.   SUM, MIN, MAX, AVG,  STD.   Other aggregations can be built by defining java-classes to perform the aggregation
Aggregations in Cassandra are not supported by the Cassandra nodes - client must provide aggregations.  When the aggregation requirement spans multiple rows, Random Partitioning makes aggregations very difficult for the client.   Recommendation is to use Storm or Hadoop for aggregations.
HIVE Integration
HIVE can access HBase tables directly (uses de-serialization under the hood that is aware of the HBase file format).
Work in Progress (https://issues.apache.org/jira/browse/CASSANDRA-4131)
PIG Integration
PIG has native support for writing into/reading from HBase.
Cassandra 0.7.4+









          Point
        HBase
             Cassandra

CAP Theorem Focus
Consistency, Availability
Availability, Partition-Tolerance
Consistency
Strong
Eventual (Strong is Optional)
Single Write Master
Yes
No (R+W+1 to get Strong Consistency)
Optimized For
Reads
Writes
Main Data Structure
CF, RowKey,  Name Value Pair Set
CF, RowKey, Name Value Pair Set
Dynamic Columns
Yes
Yes
Column Names as Data
Yes
Yes
Static Columns
No
Yes
RowKey Slices
Yes
No
Static Column Value Indexes
No
Yes
Sorted Column Names
Yes
Yes
Cell Versioning Support
Yes
No



Bloom Filters
Yes
Yes(only on Key)
CoProcessors
Yes
No
Triggers
Yes(Part of Coprocessor)
No
Push Down Predicates
Yes(Part of Coprocessor)
No
Atomic Compare and Set
Yes
No
Explicit Row Locks
Yes
No
Row Key Caching
Yes
Yes
Partitioning Strategy
Ordered Partitioning
Random Partitioning recommended
Rebalancing
Automatic
Not Needed with Random Partitioning
Availability
N-Replicas across Nodes
N-Replicas across Nodes
Data Node Failure
Graceful Degredation
Graceful Degredation
Data Node Failure - Replication
N-Replicas Preserved
(N-1) Replicas Preserved + Hinted Handoff
Data Node Restoration
Same as Node Addition
Requires Node Repair Admin-action
Data Node Addition
Rebalancing Automatic
Rebalancing Requires Token-Assignment Adjustment
Data Node Management
Simple (Roll In, Role Out)
Human Admin Action Required
Cluster Admin Nodes
Zookeeper, NameNode, HMaster
All Nodes are Equal
SPOF
Now, all the Admin Nodes are Fault Tolerant
All Nodes are Equal
Write.ANY
No, but Replicas are Node Agnostic
Yes (Writes Never Fail if this option is used)
Write.ONE
Standard, HA, Strong Consistency
Yes (often used), HA,  Weak Consistency
Write.QUORUM
No (not required)
Yes (often used with Read.QUORUM for Strong Consistency
Write.ALL
Yes (performance penalty)
Yes (performance penalty, not HA)
Asynchronous WAN Replication
Yes, but it needs testing on corner cases.
Yes (Replica's can span data centers)
Synchronous WAN Replication
No
Yes with Write.QUORUM or Write.EACH-QUORUM
Compression Support
Yes
Yes

Tuesday, 14 October 2014

Ten Things You Can Do With Spring Security

One

You can specify the authorisation provider of your choice in your Spring XML config file. You do this by configuring an authentication-manager as defined in Spring’s http://www.springframework.org/schema/security/spring-security-3.1.xsd schema. The simplifiedauthentication-manager element definition looks something like this:

<xs:element name="authentication-manager">
 <xs:complexType>
  <xs:choice minOccurs="0" maxOccurs="unbounded">
   <xs:element name="authentication-provider">
    <xs:complexType>
     <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element ref="security:any-user-service"/>
      <xs:element name="password-encoder">...</xs:element>
     </xs:choice>
     <xs:attributeGroup ref="security:ap.attlist"/>
    </xs:complexType>
   </xs:element>
   <!-- This is BIG -->
   <xs:element name="ldap-authentication-provider">...</xs:element>
  </xs:choice>
  <xs:attributeGroup ref="security:authman.attlist"/>
 </xs:complexType>
</xs:element>

This means that, for example, you can use any number of authentication providers including basic authentication and JDBC authentication as shown in the snippet below:

<authentication-manager alias="authenticationManager">
  <authentication-provider>
   <user-service>
    <user authorities="ROLE_GUEST" name="guest" password=""/>
   </user-service>
  </authentication-provider>
  <authentication-provider>
   <jdbc-user-service data-source-ref="dataSource"/>
  </authentication-provider>
 </authentication-manager>


Two

You can configure authorisation rules in your Spring XML file by linking URLs to user roles using the intercept-url element. Theintercept-url element is a child element of the http element, whose abridged definition looks like this:

<xs:element name="http">
 <xs:complexType>
  <xs:choice minOccurs="0" maxOccurs="unbounded">
   <xs:element name="intercept-url">
    <xs:complexType>
     <xs:attributeGroup ref="security:intercept-url.attlist"/>
    </xs:complexType>
   </xs:element>
   <!-- Details omitted for clarity -->
   <xs:element name="access-denied-handler">...</xs:element>
   <xs:element name="form-login">...</xs:element>
   <xs:element name="openid-login">...</xs:element>
   <xs:element name="x509">...</xs:element>
   <xs:element ref="security:jee"/>
   <xs:element name="http-basic">...</xs:element>
   <xs:element name="logout">...</xs:element>
   <xs:element name="session-management">...</xs:element>
   <xs:element name="remember-me">...</xs:element>
   <xs:element name="anonymous">...</xs:element>
   <xs:element name="port-mappings">...</xs:element>
   <xs:element ref="security:custom-filter"/>
   <xs:element ref="security:request-cache"/>
   <xs:element name="expression-handler">...</xs:element>
  </xs:choice>
  <xs:attributeGroup ref="security:http.attlist"/>
 </xs:complexType>
</xs:element>

Example usage:

<security:http>
 <security:intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
 <security:intercept-url pattern="/account/**" access="hasRole('ROLE_USER')" />
 <security:intercept-url pattern="/**" access="hasRole('ROLE_ANONYMOUS')" />
 <!-- other elements removed for clarity -->
</security:http>


Three

You can encode and validate passwords using several classes that implement Spring’sorg.springframework.security.authentication.encoding.PasswordEncoder interface. This only has two methods:encodePassword and isPasswordValid. Its many implementations include:
  • BaseDigestPasswordEncoder
  • BasePasswordEncoder
  • LdapShaPasswordEncoder
  • Md4PasswordEncoder,
  • Md5PasswordEncoder
  • MessageDigestPasswordEncoder
  • MessageDigestPasswordEncoder
  • PlaintextPasswordEncoder
  • ShaPasswordEncoder

Four

You can restrict access to page elements using Spring Security’s tag library. To use this library you include the following taglib definition in your JSP:

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

The taglib contains three useful tags:
  • authorize
  • authentication
  • accesscontrollist

The most useful seems to be the authorize tag, which, taking examples from the Spring documentation, can be used in two ways. Firstly, you can authorize against roles:

<sec:authorize access="hasRole('supervisor')">
This content will only be visible to users who have
the "supervisor" authority in their list of <tt>GrantedAuthority</tt>s.
</sec:authorize>

...and secondly you can authorize against URLs

<sec:authorize url="/admin">
This content will only be visible to users who are authorized to send requests to the "/admin" URL.
</sec:authorize>

The URL specified must tie in with the intercept-url tag described in item 2.


Five

You can perform method level authorization using Spring’s in-house annotations

  • @PreAuthorize("spEL expression")
  • @PostAuthorize("spEL expression")
  • @Secure

where the spEL expression can be anything, but is usually something like: hasRole('ROLE_USER').

To enable @PreAuthorize(...) and @PostAuthorize(...) add the following to your XML config file:

<global-method-security pre-post-annotations="enabled" />

@PreAuthorize(...) is used as shown in the following example:


  
@PreAuthorize("hasRole('ROLE_ADMIN')")
  
public void deleteUser(String username);

To enable @Secure add the following to your Spring config file:

<global-method-security pre-post-annotations="enabled" />


Six

You can perform method level security using Spring’s JSR-250 implementation by adding the following to your Spring config file:

<global-method-security jsr250-annotations=”enabled”/>

The JSR-250 security annotations are a sub set of the JSR-250 annotations and include:

  • @RolesAllowed({“ROLE_USER”,”ROLE_ADMIN”})
  • @PermitAll
  • @DenyAll

When used, a JSR-250 annotation looks something like this:


  
@RolesAllowed({"ROLE_ADMIN","ROLE_USER"})
  
public void deleteUser(String username);


Seven

You can integrate Spring Security with OpenID authentication with a few simple steps. The first of these is writing a simple JSP form where the action value is set to j_spring_openid_security_check, which at its most minimal looks something like this:

<form action="j_spring-openid-security-check" method="post">
 <label for="openid_idenifier">Login</label>: 
 <input id="openid_identifier" name="openid_identifier" type="text"/>
 <input type="submit" value="Login" />
</form>

The next step is add the openid-login element to http:

<xs:element name="http">
 <xs:complexType>
  <xs:choice minOccurs="0" maxOccurs="unbounded">
   <xs:element name="openid-login">
    <xs:annotation>
     <xs:documentation>
      Sets up form login for authentication with an
      Open ID identity
     </xs:documentation>
    </xs:annotation>
    <xs:complexType>
     <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded"
       ref="security:attribute-exchange" />
     </xs:sequence>
     <xs:attributeGroup ref="security:form-login.attlist" />
     <xs:attribute name="user-service-ref" type="xs:token">
      <xs:annotation>
       <xs:documentation>
        A reference to a user-service (or
        UserDetailsService bean) Id
       </xs:documentation>
      </xs:annotation>
     </xs:attribute>
    </xs:complexType>
   </xs:element>
   <!-- Other elements omitted for clarity -->
  </xs:choice>
 </xs:complexType>
</xs:element>

As all of openid-login child elements are optional, the simplest way to enable OpenID is to write:

<http auto-config="true">
 <openid-login/>
 <!-- other tags and attributes omitted for clarity -->
</http>

Lastly, you’ll need to add the spring-security-openid.jar to your project.


Eight

You can configure your app to authenticate users with an embedded LDAP (Lightweight Directory Access Protocol) Server using XML config. This is described in the abridged XML schema show below:

<xs:element name="ldap-server">
 <xs:complexType>
  <xs:attributeGroup ref="security:ldap-server.attlist" />
 </xs:complexType>
</xs:element>
<xs:attributeGroup name="ldap-server.attlist">
 <xs:attribute name="id" type="xs:token">
  <xs:annotation>
   <xs:documentation>
    A bean identifier, used for referring to the bean elsewhere in the context.
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
 <xs:attribute name="port" type="xs:positiveInteger"/>
 <xs:attribute name="ldif" type="xs:string">
  <xs:annotation>
   <xs:documentation>
    Explicitly specifies an ldif file resource to load
    into an embedded LDAP
    server. The default is classpath*:*.ldiff
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
 <xs:attribute name="root" type="xs:string">
  <xs:annotation>
   <xs:documentation>
    Optional root suffix for the embedded LDAP server. Default is
    "dc=springframework,dc=org"
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
</xs:attributeGroup>

The LDIF file, where LDIF stands for LDAP Interchange Format, is a plain text file format used to describe a set of LDAP records.

An example of the ldap-server element usage would be:

<ldap-server ldif="classpath:my-ldif-file.ldif" id="localserver" /> 

To use Spring Security LDAP integration, remember to include the spring-security-ldap.jar jar in your project’s POM.XML.


Nine

You can configure your app to authenticate users with remote LDAP (Lightweight Directory Access Protocol) Server using XML config. This is described in the abridged XML schema show below:

<xs:element name="ldap-server">
 <xs:complexType>
  <xs:attributeGroup ref="security:ldap-server.attlist" />
 </xs:complexType>
</xs:element>
<xs:attributeGroup name="ldap-server.attlist">
 <xs:attribute name="id" type="xs:token">
  <xs:annotation>
   <xs:documentation>
    A bean identifier, used for referring to the bean elsewhere 
    in the context.
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
 <xs:attribute name="url" type="xs:token"/>
 <xs:attribute name="port" type="xs:positiveInteger"/>
 <xs:attribute name="manager-dn" type="xs:string">
  <xs:annotation>
   <xs:documentation>
    Username (DN) of the "manager" user identity which will be used to
    authenticate to a (non-embedded) LDAP server. If omitted, anonymous
    access will be used.
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
 <xs:attribute name="manager-password" type="xs:string">
  <xs:annotation>
   <xs:documentation>
    The password for the manager DN. This is required
    if the manager-dn is specified.
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
</xs:attributeGroup>

The documentation states that the ldap-server element “Defines an LDAP server location or starts an embedded server. The url indicates the location of a remote server. If no url is given, an embedded server will be started, listening on the supplied port number. The port is optional and defaults to 33389. A Spring LDAP ContextSource bean will be registered for the server with the id supplied”.

This is an example of a really minimal configuration:

<ldap-server url="ldap://myServer/dc=captaindebug,dc=com:389" id="ldapExternal" 
  manager-dn="uid=admin,ou=users,ou=systems" manager-password="s3cret"/>

Having configured the server, you also need to configure the LDAP authentication provider. There seem to be several methods of doing this and it’s not so straightforward, so more on that later, possibly...

Ten

You can add the requires-channel="https" attribute to your Spring Security Config's <intercept-url /> element to force any matching URL to use HTTPS. For example, if you wanted to ensure that password were always encrypted before being sent, then you could add this abridged XML to your config:

<http auto-config="true" use-expressions="true">
    <intercept-url pattern="/login" requires-channel="https"/>
    <!-- Other attributes and elements omitted -->    
</https>

There are another couple of things to do here, but more on that later...

You may have noticed that I’ve used the Spring Security XML schema file (http://www.springframework.org/schema/security/spring-security-3.1.xsd) to explain some of the features in my list of things you can do with Spring Security. That’s because I always treat the Spring XSDs as the definitive reference point for all things Spring. In November 2011 I wrote a blog on Spring’s JSR-250’s @PostConstruct Annotation that contained a mistake (Yes, it true it does happen), which was quite rightly pointed out by Spring’s Chris Beams - @CBeams, who left a comment on the JavaLobby Version of this blog. I decided to check the schemas and found that we were both wrong (although I was a lot more wrong than Chris) - the Captain Debug article is now, so far as I can tell, correct.

Application security is a pretty complex subject and if it’s something you’ll be looking at in depth then I suggest that you get a copy ofSpring Security 3 by Peter Mularien - it’s also recommended by the Guys at Spring.

Finally, if there’s one key idea to appreciate about Spring Security is that, as an application bolt-on, it provides a really rich security feature set. You should therefore try to let Spring Security handle as much possible of your app’s security details rather than diving in and unnecessarily writing your own code.

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...